int main (int argc, char *argv[]) { int started = bsonsearch_startup(); int i =0; do { i++; BSON_ASSERT(compare_json("{ \"arr\" : { \"$binary\" : { \"base64\": \"qGC2JlwgCAAn9gzECABFEEBI6ApAAEAG4PXAqFg2wKhYGAAW7McL7DTmTwx9KoAYBZhx2gAAAQEIChYLl5g0Mjly\", \"subType\" : \"00\" } }}", "{\"arr\":{\"$module\":{\"name\":\"ether\", \"config\":{\"type\":\"srcip&dstip\", \"query\":[ [\"192.168.88.54\"],[\"192.168.88.54\",\"255.255.255.0\"] ] }}}}")); BSON_ASSERT(compare_json("{ \"arr\" : { \"$binary\" : { \"base64\": \"qGC2JlwgCAAn9gzECABFEEBI6ApAAEAG4PXAqFg2wKhYGAAW7McL7DTmTwx9KoAYBZhx2gAAAQEIChYLl5g0Mjly\", \"subType\" : \"00\" } }}", "{\"arr\":{\"$module\":{\"name\":\"ether\", \"config\":{\"type\":\"dstiplist\", \"query\":[ \"192.168.88.1\", \"192.168.88.24\", \"192.168.88.3\", \"192.168.88.52\"] }}}}")); BSON_ASSERT(!compare_json("{ \"arr\" : { \"$binary\" : { \"base64\": \"qGC2JlwgCAAn9gzECABFEEBI6ApAAEAG4PXAqFg2wKhYGAAW7McL7DTmTwx9KoAYBZhx2gAAAQEIChYLl5g0Mjly\", \"subType\" : \"00\" } }}", "{\"arr\":{\"$module\":{\"name\":\"ether\", \"config\":{\"type\":\"srciplist\", \"query\":[ \"192.168.88.1\", \"192.168.88.2\", \"192.168.88.3\", \"192.168.88.52\"] }}}}")); BSON_ASSERT(compare_json("{ \"arr\" : { \"$binary\" : { \"base64\": \"qGC2JlwgCAAn9gzECABFEEBI6ApAAEAG4PXAqFg2wKhYGAAW7McL7DTmTwx9KoAYBZhx2gAAAQEIChYLl5g0Mjly\", \"subType\" : \"00\" } }}", "{\"arr\":{\"$module\":{\"name\":\"ether\", \"config\":{\"type\":\"srciplist\", \"query\":[ \"192.168.88.1\", \"192.168.88.2\", \"192.168.88.3\", \"192.168.88.54\"] }}}}")); BSON_ASSERT(compare_json("{ \"arr\" : { \"$binary\" : { \"base64\": \"qGC2JlwgCAAn9gzECABFEEBI6ApAAEAG4PXAqFg2wKhYGAAW7McL7DTmTwx9KoAYBZhx2gAAAQEIChYLl5g0Mjly\", \"subType\" : \"00\" } }}", "{\"arr\":{\"$module\":{\"name\":\"ether\", \"config\":{\"type\":\"srcip&dstip\", \"query\":[ [\"192.168.88.54\",\"255.255.255.255\"],[\"192.168.88.54\",\"255.255.255.0\"] ] }}}}")); /**/ } while (i<10); int finished = bsonsearch_shutdown(); return 0; }
int main (int argc, char *argv[]) { BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$date\": 1454621111904}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$gte\":{\"$date\": 1454621111904}}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$lte\":{\"$date\": 1454621111904}}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$gt\":{\"$date\": 1454621111903}}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$lt\":{\"$date\": 1454621111905}}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$ne\":{\"$date\": 1454621111905}}}")); BSON_ASSERT(compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$in\": [{\"$date\": 1454621111904}]}}")); BSON_ASSERT(!compare_json("{\"dt\": {\"$date\": 1454621111904}}", "{\"dt\": {\"$in\": [{\"$date\": 1454621111905}]}}")); BSON_ASSERT(compare_json("{\"dt\": [{\"$date\": 1454621111905}]}", "{\"dt\": {\"$in\": [{\"$date\": 1454621111905}]}}")); return 0; }
int main (int argc, char *argv[]) { BSON_ASSERT(compare_json("{\"loc\": [1,1]}", "{\"loc\": { \"$geoWithin\": { \"$polygon\": [ [ 1 , 1 ], [ 3 , 6 ], [ 6 , 0 ] ] } } }")); BSON_ASSERT(compare_json("{\"loc\": [2,3]}", "{\"loc\": { \"$geoWithin\": { \"$polygon\": [ [ 1 , 1 ], [ 3 , 6 ], [ 6 , 0 ] ] } } }")); BSON_ASSERT(!compare_json("{\"loc\": [20,3]}", "{\"loc\": { \"$geoWithin\": { \"$polygon\": [ [ 1 , 1 ], [ 3 , 6 ], [ 6 , 0 ] ] } } }")); BSON_ASSERT(compare_json("{\"loc\": [0,3]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 101 ] ] } } }")); BSON_ASSERT(compare_json("{\"loc\": [3,0]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 100 ] ] } } }")); BSON_ASSERT(compare_json("{\"loc\": [100,0]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 100 ] ] } } }")); BSON_ASSERT(compare_json("{\"loc\": [0,100]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 100 ] ] } } }")); BSON_ASSERT(!compare_json("{\"loc\": [-1,100]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 100 ] ] } } }")); BSON_ASSERT(!compare_json("{\"loc\": [2,101]}", "{\"loc\": { \"$geoWithin\": { \"$box\": [ [ 0, 0 ], [ 100, 100 ] ] } } }")); return 0; }
static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive) { cJSON *path = NULL; cJSON *value = NULL; cJSON *parent = NULL; enum patch_operation opcode = INVALID; unsigned char *parent_pointer = NULL; unsigned char *child_pointer = NULL; int status = 0; path = get_object_item(patch, "path", case_sensitive); if (!cJSON_IsString(path)) { /* malformed patch. */ status = 2; goto cleanup; } opcode = decode_patch_operation(patch, case_sensitive); if (opcode == INVALID) { status = 3; goto cleanup; } else if (opcode == TEST) { /* compare value: {...} with the given path */ status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive); goto cleanup; } /* special case for replacing the root */ if (path->valuestring[0] == '\0') { if (opcode == REMOVE) { static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; overwrite_item(object, invalid); status = 0; goto cleanup; } if ((opcode == REPLACE) || (opcode == ADD)) { value = get_object_item(patch, "value", case_sensitive); if (value == NULL) { /* missing "value" for add/replace. */ status = 7; goto cleanup; } value = cJSON_Duplicate(value, 1); if (value == NULL) { /* out of memory for add/replace. */ status = 8; goto cleanup; } overwrite_item(object, *value); /* delete the duplicated value */ cJSON_free(value); value = NULL; /* the string "value" isn't needed */ if (object->string != NULL) { cJSON_free(object->string); object->string = NULL; } status = 0; goto cleanup; } } if ((opcode == REMOVE) || (opcode == REPLACE)) { /* Get rid of old. */ cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive); if (old_item == NULL) { status = 13; goto cleanup; } cJSON_Delete(old_item); if (opcode == REMOVE) { /* For Remove, this job is done. */ status = 0; goto cleanup; } } /* Copy/Move uses "from". */ if ((opcode == MOVE) || (opcode == COPY)) { cJSON *from = get_object_item(patch, "from", case_sensitive); if (from == NULL) { /* missing "from" for copy/move. */ status = 4; goto cleanup; } if (opcode == MOVE) { value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive); } if (opcode == COPY) { value = get_item_from_pointer(object, from->valuestring, case_sensitive); } if (value == NULL) { /* missing "from" for copy/move. */ status = 5; goto cleanup; } if (opcode == COPY) { value = cJSON_Duplicate(value, 1); } if (value == NULL) { /* out of memory for copy/move. */ status = 6; goto cleanup; } } else /* Add/Replace uses "value". */ { value = get_object_item(patch, "value", case_sensitive); if (value == NULL) { /* missing "value" for add/replace. */ status = 7; goto cleanup; } value = cJSON_Duplicate(value, 1); if (value == NULL) { /* out of memory for add/replace. */ status = 8; goto cleanup; } } /* Now, just add "value" to "path". */ /* split pointer in parent and child */ parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); if (child_pointer != NULL) { child_pointer[0] = '\0'; child_pointer++; } parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); decode_pointer_inplace(child_pointer); /* add, remove, replace, move, copy, test. */ if ((parent == NULL) || (child_pointer == NULL)) { /* Couldn't find object to add to. */ status = 9; goto cleanup; } else if (cJSON_IsArray(parent)) { if (strcmp((char*)child_pointer, "-") == 0) { cJSON_AddItemToArray(parent, value); value = NULL; } else { size_t index = 0; if (!decode_array_index_from_pointer(child_pointer, &index)) { status = 11; goto cleanup; } if (!insert_item_in_array(parent, index, value)) { status = 10; goto cleanup; } value = NULL; } } else if (cJSON_IsObject(parent)) { cJSON_DeleteItemFromObject(parent, (char*)child_pointer); cJSON_AddItemToObject(parent, (char*)child_pointer, value); value = NULL; } cleanup: if (value != NULL) { cJSON_Delete(value); } if (parent_pointer != NULL) { cJSON_free(parent_pointer); } return status; }
static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive) { if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { /* mismatched type. */ return false; } switch (a->type & 0xFF) { case cJSON_Number: /* numeric mismatch. */ if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble)) { return false; } else { return true; } case cJSON_String: /* string mismatch. */ if (strcmp(a->valuestring, b->valuestring) != 0) { return false; } else { return true; } case cJSON_Array: for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) { cJSON_bool identical = compare_json(a, b, case_sensitive); if (!identical) { return false; } } /* array size mismatch? (one of both children is not NULL) */ if ((a != NULL) || (b != NULL)) { return false; } else { return true; } case cJSON_Object: sort_object(a, case_sensitive); sort_object(b, case_sensitive); for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) { cJSON_bool identical = false; /* compare object keys */ if (compare_strings((unsigned char*)a->string, (unsigned char*)b->string, case_sensitive)) { /* missing member */ return false; } identical = compare_json(a, b, case_sensitive); if (!identical) { return false; } } /* object length mismatch (one of both children is not null) */ if ((a != NULL) || (b != NULL)) { return false; } else { return true; } default: break; } /* null, true or false */ return true; }
static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) { cJSON *from_child = NULL; cJSON *to_child = NULL; cJSON *patch = NULL; if (to == NULL) { /* patch to delete everything */ return cJSON_CreateNull(); } if (!cJSON_IsObject(to) || !cJSON_IsObject(from)) { return cJSON_Duplicate(to, 1); } sort_object(from, case_sensitive); sort_object(to, case_sensitive); from_child = from->child; to_child = to->child; patch = cJSON_CreateObject(); while (from_child || to_child) { int diff; if (from_child != NULL) { if (to_child != NULL) { diff = strcmp(from_child->string, to_child->string); } else { diff = -1; } } else { diff = 1; } if (diff < 0) { /* from has a value that to doesn't have -> remove */ cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull()); from_child = from_child->next; } else if (diff > 0) { /* to has a value that from doesn't have -> add to patch */ cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1)); to_child = to_child->next; } else { /* object key exists in both objects */ if (!compare_json(from_child, to_child, case_sensitive)) { /* not identical --> generate a patch */ cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child)); } /* next key in the object */ from_child = from_child->next; to_child = to_child->next; } } if (patch->child == NULL) { /* no patch generated */ cJSON_Delete(patch); return NULL; } return patch; }