mirror of https://github.com/DaveGamble/cJSON
Add cJSONUtils_SortObjectCaseSensitive
This commit is contained in:
parent
b674519695
commit
7f22948eec
246
cJSON_Utils.c
246
cJSON_Utils.c
|
@ -425,6 +425,122 @@ cleanup:
|
||||||
return detached_item;
|
return detached_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sort lists using mergesort */
|
||||||
|
static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
|
||||||
|
{
|
||||||
|
cJSON *first = list;
|
||||||
|
cJSON *second = list;
|
||||||
|
cJSON *current_item = list;
|
||||||
|
cJSON *result = list;
|
||||||
|
cJSON *result_tail = NULL;
|
||||||
|
|
||||||
|
if ((list == NULL) || (list->next == NULL))
|
||||||
|
{
|
||||||
|
/* One entry is sorted already. */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0))
|
||||||
|
{
|
||||||
|
/* Test for list sorted. */
|
||||||
|
current_item = current_item->next;
|
||||||
|
}
|
||||||
|
if ((current_item == NULL) || (current_item->next == NULL))
|
||||||
|
{
|
||||||
|
/* Leave sorted lists unmodified. */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset pointer to the beginning */
|
||||||
|
current_item = list;
|
||||||
|
while (current_item != NULL)
|
||||||
|
{
|
||||||
|
/* Walk two pointers to find the middle. */
|
||||||
|
second = second->next;
|
||||||
|
current_item = current_item->next;
|
||||||
|
/* advances current_item two steps at a time */
|
||||||
|
if (current_item != NULL)
|
||||||
|
{
|
||||||
|
current_item = current_item->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((second != NULL) && (second->prev != NULL))
|
||||||
|
{
|
||||||
|
/* Split the lists */
|
||||||
|
second->prev->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recursively sort the sub-lists. */
|
||||||
|
first = sort_list(first, case_sensitive);
|
||||||
|
second = sort_list(second, case_sensitive);
|
||||||
|
result = NULL;
|
||||||
|
|
||||||
|
/* Merge the sub-lists */
|
||||||
|
while ((first != NULL) && (second != NULL))
|
||||||
|
{
|
||||||
|
cJSON *smaller = NULL;
|
||||||
|
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, false) < 0)
|
||||||
|
{
|
||||||
|
smaller = first;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
smaller = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
/* start merged list with the smaller element */
|
||||||
|
result_tail = smaller;
|
||||||
|
result = smaller;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* add smaller element to the list */
|
||||||
|
result_tail->next = smaller;
|
||||||
|
smaller->prev = result_tail;
|
||||||
|
result_tail = smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first == smaller)
|
||||||
|
{
|
||||||
|
first = first->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
second = second->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first != NULL)
|
||||||
|
{
|
||||||
|
/* Append rest of first list. */
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
result_tail->next = first;
|
||||||
|
first->prev = result_tail;
|
||||||
|
}
|
||||||
|
if (second != NULL)
|
||||||
|
{
|
||||||
|
/* Append rest of second list */
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
result_tail->next = second;
|
||||||
|
second->prev = result_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sort_object(cJSON * const object, const cJSON_bool case_sensitive)
|
||||||
|
{
|
||||||
|
object->child = sort_list(object->child, case_sensitive);
|
||||||
|
}
|
||||||
|
|
||||||
static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive)
|
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)))
|
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
|
||||||
|
@ -477,8 +593,8 @@ static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensiti
|
||||||
}
|
}
|
||||||
|
|
||||||
case cJSON_Object:
|
case cJSON_Object:
|
||||||
cJSONUtils_SortObject(a);
|
sort_object(a, case_sensitive);
|
||||||
cJSONUtils_SortObject(b);
|
sort_object(b, case_sensitive);
|
||||||
for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next)
|
for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next)
|
||||||
{
|
{
|
||||||
cJSON_bool identical = false;
|
cJSON_bool identical = false;
|
||||||
|
@ -1018,8 +1134,8 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
|
||||||
{
|
{
|
||||||
cJSON *from_child = NULL;
|
cJSON *from_child = NULL;
|
||||||
cJSON *to_child = NULL;
|
cJSON *to_child = NULL;
|
||||||
cJSONUtils_SortObject(from);
|
sort_object(from, case_sensitive);
|
||||||
cJSONUtils_SortObject(to);
|
sort_object(to, case_sensitive);
|
||||||
|
|
||||||
from_child = from->child;
|
from_child = from->child;
|
||||||
to_child = to->child;
|
to_child = to->child;
|
||||||
|
@ -1096,120 +1212,14 @@ CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from
|
||||||
return patches;
|
return patches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sort lists using mergesort */
|
|
||||||
static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
|
|
||||||
{
|
|
||||||
cJSON *first = list;
|
|
||||||
cJSON *second = list;
|
|
||||||
cJSON *current_item = list;
|
|
||||||
cJSON *result = list;
|
|
||||||
cJSON *result_tail = NULL;
|
|
||||||
|
|
||||||
if ((list == NULL) || (list->next == NULL))
|
|
||||||
{
|
|
||||||
/* One entry is sorted already. */
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0))
|
|
||||||
{
|
|
||||||
/* Test for list sorted. */
|
|
||||||
current_item = current_item->next;
|
|
||||||
}
|
|
||||||
if ((current_item == NULL) || (current_item->next == NULL))
|
|
||||||
{
|
|
||||||
/* Leave sorted lists unmodified. */
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset pointer to the beginning */
|
|
||||||
current_item = list;
|
|
||||||
while (current_item != NULL)
|
|
||||||
{
|
|
||||||
/* Walk two pointers to find the middle. */
|
|
||||||
second = second->next;
|
|
||||||
current_item = current_item->next;
|
|
||||||
/* advances current_item two steps at a time */
|
|
||||||
if (current_item != NULL)
|
|
||||||
{
|
|
||||||
current_item = current_item->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((second != NULL) && (second->prev != NULL))
|
|
||||||
{
|
|
||||||
/* Split the lists */
|
|
||||||
second->prev->next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Recursively sort the sub-lists. */
|
|
||||||
first = sort_list(first, case_sensitive);
|
|
||||||
second = sort_list(second, case_sensitive);
|
|
||||||
result = NULL;
|
|
||||||
|
|
||||||
/* Merge the sub-lists */
|
|
||||||
while ((first != NULL) && (second != NULL))
|
|
||||||
{
|
|
||||||
cJSON *smaller = NULL;
|
|
||||||
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, false) < 0)
|
|
||||||
{
|
|
||||||
smaller = first;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
smaller = second;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
/* start merged list with the smaller element */
|
|
||||||
result_tail = smaller;
|
|
||||||
result = smaller;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* add smaller element to the list */
|
|
||||||
result_tail->next = smaller;
|
|
||||||
smaller->prev = result_tail;
|
|
||||||
result_tail = smaller;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first == smaller)
|
|
||||||
{
|
|
||||||
first = first->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
second = second->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first != NULL)
|
|
||||||
{
|
|
||||||
/* Append rest of first list. */
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
result_tail->next = first;
|
|
||||||
first->prev = result_tail;
|
|
||||||
}
|
|
||||||
if (second != NULL)
|
|
||||||
{
|
|
||||||
/* Append rest of second list */
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
result_tail->next = second;
|
|
||||||
second->prev = result_tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object)
|
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object)
|
||||||
{
|
{
|
||||||
object->child = sort_list(object->child, false);
|
sort_object(object, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object)
|
||||||
|
{
|
||||||
|
sort_object(object, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch)
|
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch)
|
||||||
|
@ -1262,8 +1272,8 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
|
||||||
return cJSON_Duplicate(to, 1);
|
return cJSON_Duplicate(to, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSONUtils_SortObject(from);
|
sort_object(from, case_sensitive);
|
||||||
cJSONUtils_SortObject(to);
|
sort_object(to, case_sensitive);
|
||||||
|
|
||||||
from_child = from->child;
|
from_child = from->child;
|
||||||
to_child = to->child;
|
to_child = to->child;
|
||||||
|
|
|
@ -70,3 +70,4 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
|
||||||
|
|
||||||
/* Sorts the members of the object into alphabetical order. */
|
/* Sorts the members of the object into alphabetical order. */
|
||||||
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
|
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
|
||||||
|
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
|
||||||
|
|
Loading…
Reference in New Issue