Example #1
0
int json_equal(json_t *json1, json_t *json2)
{
    if(!json1 || !json2)
        return 0;

    if(json_typeof(json1) != json_typeof(json2))
        return 0;

    /* this covers true, false and null as they are singletons */
    if(json1 == json2)
        return 1;

    if(json_is_object(json1))
        return json_object_equal(json1, json2);

    if(json_is_array(json1))
        return json_array_equal(json1, json2);

    if(json_is_string(json1))
        return json_string_equal(json1, json2);

    if(json_is_integer(json1))
        return json_integer_equal(json1, json2);

    if(json_is_real(json1))
        return json_real_equal(json1, json2);

    return 0;
}
Example #2
0
json_t *json_true(void)
{
    static json_t the_true = {
        .type = JSON_TRUE,
        .refcount = (unsigned int)1
    };
    return &the_true;
}


json_t *json_false(void)
{
    static json_t the_false = {
        .type = JSON_FALSE,
        .refcount = (unsigned int)1
    };
    return &the_false;
}


json_t *json_null(void)
{
    static json_t the_null = {
        .type = JSON_NULL,
        .refcount = (unsigned int)1
    };
    return &the_null;
}


/*** deletion ***/

void json_delete(json_t *json)
{
    if(json_is_object(json))
        json_delete_object(json_to_object(json));

    else if(json_is_array(json))
        json_delete_array(json_to_array(json));

    else if(json_is_string(json))
        json_delete_string(json_to_string(json));

    else if(json_is_integer(json))
        json_delete_integer(json_to_integer(json));

    else if(json_is_real(json))
        json_delete_real(json_to_real(json));

    /* json_delete is not called for true, false or null */
}


/*** equality ***/

int json_equal(json_t *json1, json_t *json2)
{
    if(!json1 || !json2)
        return 0;

    if(json_typeof(json1) != json_typeof(json2))
        return 0;

    /* this covers true, false and null as they are singletons */
    if(json1 == json2)
        return 1;

    if(json_is_object(json1))
        return json_object_equal(json1, json2);

    if(json_is_array(json1))
        return json_array_equal(json1, json2);

    if(json_is_string(json1))
        return json_string_equal(json1, json2);

    if(json_is_integer(json1))
        return json_integer_equal(json1, json2);

    if(json_is_real(json1))
        return json_real_equal(json1, json2);

    return 0;
}


/*** copying ***/

json_t *json_copy(json_t *json)
{
    if(!json)
        return NULL;

    if(json_is_object(json))
        return json_object_copy(json);

    if(json_is_array(json))
        return json_array_copy(json);

    if(json_is_string(json))
        return json_string_copy(json);

    if(json_is_integer(json))
        return json_integer_copy(json);

    if(json_is_real(json))
        return json_real_copy(json);

    if(json_is_true(json) || json_is_false(json) || json_is_null(json))
        return json;

    return NULL;
}

json_t *json_deep_copy(json_t *json)
{
    if(!json)
        return NULL;

    if(json_is_object(json))
        return json_object_deep_copy(json);

    if(json_is_array(json))
        return json_array_deep_copy(json);

    /* for the rest of the types, deep copying doesn't differ from
       shallow copying */

    if(json_is_string(json))
        return json_string_copy(json);

    if(json_is_integer(json))
        return json_integer_copy(json);

    if(json_is_real(json))
        return json_real_copy(json);

    if(json_is_true(json) || json_is_false(json) || json_is_null(json))
        return json;

    return NULL;
}
Example #3
0
/**
 * json_node_equal:
 * @a: (type JsonNode): a JSON node
 * @b: (type JsonNode): another JSON node
 *
 * Check whether @a and @b are equal #JsonNodes, meaning they have the same
 * type and same values (checked recursively). Note that integer values are
 * compared numerically, ignoring type, so a double value 4.0 is equal to the
 * integer value 4.
 *
 * Returns: %TRUE if @a and @b are equal; %FALSE otherwise
 * Since: 1.2
 */
gboolean
json_node_equal (gconstpointer  a,
                 gconstpointer  b)
{
  JsonNode *node_a, *node_b;  /* unowned */

  node_a = (JsonNode *) a;
  node_b = (JsonNode *) b;

  /* Identity comparison. */
  if (node_a == node_b)
    return TRUE;

  /* Eliminate mismatched types rapidly. */
  if (!json_type_is_a (node_a, node_b) &&
      !json_type_is_a (node_b, node_a))
    {
      return FALSE;
    }

  switch (node_a->type)
    {
    case JSON_NODE_NULL:
      /* Types match already. */
      return TRUE;
    case JSON_NODE_ARRAY:
      return json_array_equal (json_node_get_array (node_a),
                               json_node_get_array (node_b));
    case JSON_NODE_OBJECT:
      return json_object_equal (json_node_get_object (node_a),
                                json_node_get_object (node_b));
    case JSON_NODE_VALUE:
      /* Handled below. */
      break;
    default:
      g_assert_not_reached ();
    }

  /* Handle values. */
  switch (node_a->data.value->type)
    {
    case JSON_VALUE_NULL:
      /* Types already match. */
      return TRUE;
    case JSON_VALUE_BOOLEAN:
      return (json_node_get_boolean (node_a) == json_node_get_boolean (node_b));
    case JSON_VALUE_STRING:
      return json_string_equal (json_node_get_string (node_a),
                                json_node_get_string (node_b));
    case JSON_VALUE_DOUBLE:
    case JSON_VALUE_INT: {
      gdouble val_a, val_b;
      JsonValueType value_type_a, value_type_b;

      value_type_a = node_a->data.value->type;
      value_type_b = node_b->data.value->type;

      /* Integer comparison doesn’t need to involve doubles… */
      if (value_type_a == JSON_VALUE_INT &&
          value_type_b == JSON_VALUE_INT)
        {
          return (json_node_get_int (node_a) ==
                  json_node_get_int (node_b));
        }

      /* …but everything else does. We can use bitwise double equality here,
       * since we’re not doing any calculations which could introduce floating
       * point error. We expect that the doubles in the JSON nodes come directly
       * from strtod() or similar, so should be bitwise equal for equal string
       * representations.
       *
       * Interesting background reading:
       * http://randomascii.wordpress.com/2012/06/26/\
       *   doubles-are-not-floats-so-dont-compare-them/
       */
      if (value_type_a == JSON_VALUE_INT)
        val_a = json_node_get_int (node_a);
      else
        val_a = json_node_get_double (node_a);

      if (value_type_b == JSON_VALUE_INT)
        val_b = json_node_get_int (node_b);
      else
        val_b = json_node_get_double (node_b);

      return (val_a == val_b);
    }
    case JSON_VALUE_INVALID:
    default:
      g_assert_not_reached ();
    }
}