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; }
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; }
int main() { /* integer tests */ struct json_object *int1 = json_object_new_int(0); struct json_object *int2 = json_object_new_int(1); struct json_object *int3 = json_object_new_int(1); if (!json_object_equal(int1, int2)) printf("JSON integer comparision is correct\n"); else printf("JSON integer comparision failed\n"); if (json_object_equal(int1, int1)) printf("JSON same object comparision is correct\n"); else printf("JSON same object comparision failed\n"); if (json_object_equal(int2, int3)) printf("JSON same integer comparision is correct\n"); else printf("JSON same integer comparision failed\n"); json_object_put(int1); json_object_put(int2); json_object_put(int3); /* string tests */ struct json_object *str1 = json_object_new_string("TESTSTRING"); struct json_object *str2 = json_object_new_string("TESTSTRING"); struct json_object *str3 = json_object_new_string("DIFFERENT"); if (json_object_equal(str1, str2)) printf("Comparing equal strings is correct\n"); else printf("Comparing equal strings failed\n"); if (!json_object_equal(str1, str3)) printf("Comparing different strings is correct\n"); else printf("Comparing different strings failed\n"); json_object_put(str1); json_object_put(str2); json_object_put(str3); /* double tests */ struct json_object *dbl1 = json_object_new_double(3.14159); struct json_object *dbl2 = json_object_new_double(3.14159); struct json_object *dbl3 = json_object_new_double(3.0); if (json_object_equal(dbl1, dbl2)) printf("Comparing equal doubles is correct\n"); else printf("Comparing equal doubles failed\n"); if (!json_object_equal(dbl1, dbl3)) printf("Comparing different doubles is correct\n"); else printf("Comparing different doubles failed\n"); json_object_put(dbl1); json_object_put(dbl2); json_object_put(dbl3); /* array tests */ struct json_object *ar1 = json_object_new_array(); struct json_object *ar2 = json_object_new_array(); struct json_object *ar3 = json_object_new_array(); struct json_object *ar4 = json_object_new_array(); json_object_array_add(ar1, json_object_new_int(1)); json_object_array_add(ar1, json_object_new_int(2)); json_object_array_add(ar2, json_object_new_int(1)); json_object_array_add(ar2, json_object_new_int(2)); json_object_array_add(ar3, json_object_new_int(1)); json_object_array_add(ar3, json_object_new_int(1)); if (json_object_equal(ar1, ar2)) printf("Comparing equal arrays is correct\n"); else printf("Comparing equal arrays failed\n"); json_object_array_add(ar2, json_object_new_int(1)); if (!json_object_equal(ar1, ar2)) printf("Comparing arrays of different len is correct\n"); else printf("Comparing arrays of different len failed\n"); if (!json_object_equal(ar1, ar3)) printf("Comparing different arrays is correct\n"); else printf("Comparing different arrays failed\n"); if (!json_object_equal(ar1, ar4)) printf("Comparing different arrays (one empty) is correct\n"); else printf("Comparing different arrays (one empty) failed\n"); json_object_put(ar1); json_object_put(ar2); json_object_put(ar3); json_object_put(ar4); /* object tests */ struct json_object *obj1 = json_object_new_object(); struct json_object *obj2 = json_object_new_object(); json_object_object_add(obj1, "test1", json_object_new_int(123)); json_object_object_add(obj1, "test2", json_object_new_int(321)); json_object_object_add(obj2, "test2", json_object_new_int(123)); json_object_object_add(obj2, "test1", json_object_new_int(321)); /* key-order is different between obj1 and obj2, should still be equal */ if (json_object_equal(obj1, obj2)) printf("Comparing JSON object with different key order is correct\n"); else printf("Comparing JSON object with different key order is incorrect\n"); /* make obj2 look different to obj1 */ json_object_object_add(obj2, "test3", json_object_new_int(234)); if (!json_object_equal(obj1, obj2)) printf("Comparing different objects is correct\n"); else printf("Comparing different objects is incorrect\n"); json_object_put(obj1); json_object_put(obj2); return 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 (); } }