Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #904 : Fixes sort_list function to maintain previous node data after running mergesort #908

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 55 additions & 3 deletions cJSON_Utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,22 +508,41 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)

/* reset pointer to the beginning */
current_item = list;

/*Used to store the last item in list, before current_item becomes null*/
cJSON *last_valid_current_item = list;
while (current_item != NULL)
{
/* Walk two pointers to find the middle. */
second = second->next;
current_item = current_item->next;

/*store current_item as long as its not null*/
if(current_item != NULL)
{
last_valid_current_item = current_item;
}

/* advances current_item two steps at a time */
if (current_item != NULL)
{
current_item = current_item->next;

/*store current_item as long as its not null*/
if(current_item != NULL)
{
last_valid_current_item = current_item;
}
}
}
if ((second != NULL) && (second->prev != NULL))
{
/* Split the lists */
second->prev->next = NULL;
second->prev = NULL;

/*maintain prev data for split lists*/
first->prev = second->prev;
second->prev = last_valid_current_item;
}

/* Recursively sort the sub-lists. */
Expand All @@ -535,6 +554,10 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
while ((first != NULL) && (second != NULL))
{
cJSON *smaller = NULL;

/*used to store smaller->prev*/
cJSON *smaller_prev_storage = NULL;

if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0)
{
smaller = first;
Expand All @@ -549,22 +572,43 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
/* start merged list with the smaller element */
result_tail = smaller;
result = smaller;

/*save smaller->prev to storage for later use*/
smaller_prev_storage = smaller->prev;
}
else
{
{
/*save smaller->prev to storage before its changed*/
smaller_prev_storage = smaller->prev;

/* add smaller element to the list */
result_tail->next = smaller;
smaller->prev = result_tail;
result_tail = smaller;

/*maintain prev data for result*/
result->prev = result_tail;
}

if (first == smaller)
{
first = first->next;

/*maintain first->prev, if first exists*/
if(first != NULL)
{
first->prev = smaller_prev_storage;
}
}
else
{
second = second->next;

/*maintain second->prev, if second exists*/
if(second!=NULL)
{
second->prev = smaller_prev_storage;
}
}
}

Expand All @@ -576,6 +620,10 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
return first;
}
result_tail->next = first;

/*end of result list now equals end of first list*/
result->prev = first->prev;

first->prev = result_tail;
}
if (second != NULL)
Expand All @@ -586,6 +634,10 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
return second;
}
result_tail->next = second;

/*end of result list now equals end of second list*/
result->prev = second->prev;

second->prev = result_tail;
}

Expand Down Expand Up @@ -1478,4 +1530,4 @@ CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON *
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to)
{
return generate_merge_patch(from, to, true);
}
}