|  | @@ -509,63 +509,99 @@ void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path,
 | 
											
												
													
														|  |      cJSONUtils_GeneratePatch(array, op, path, 0, val);
 |  |      cJSONUtils_GeneratePatch(array, op, path, 0, val);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -static void cJSONUtils_CompareToPatch(cJSON *patches,const char *path,cJSON *from,cJSON *to)
 |  | 
 | 
											
												
													
														|  | 
 |  | +static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -	if (from->type!=to->type)	{cJSONUtils_GeneratePatch(patches,"replace",path,0,to);	return;	}
 |  | 
 | 
											
												
													
														|  | -	
 |  | 
 | 
											
												
													
														|  | -	switch (from->type)
 |  | 
 | 
											
												
													
														|  | -	{
 |  | 
 | 
											
												
													
														|  | -	case cJSON_Number:	
 |  | 
 | 
											
												
													
														|  | -		if (from->valueint!=to->valueint || from->valuedouble!=to->valuedouble)
 |  | 
 | 
											
												
													
														|  | -			cJSONUtils_GeneratePatch(patches,"replace",path,0,to);
 |  | 
 | 
											
												
													
														|  | -		return;
 |  | 
 | 
											
												
													
														|  | -						
 |  | 
 | 
											
												
													
														|  | -	case cJSON_String:	
 |  | 
 | 
											
												
													
														|  | -		if (strcmp(from->valuestring,to->valuestring)!=0)
 |  | 
 | 
											
												
													
														|  | -			cJSONUtils_GeneratePatch(patches,"replace",path,0,to);
 |  | 
 | 
											
												
													
														|  | -		return;
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	case cJSON_Array:
 |  | 
 | 
											
												
													
														|  | -	{
 |  | 
 | 
											
												
													
														|  | -		int c;char *newpath=(char*)malloc(strlen(path)+23);	/* Allow space for 64bit int. */
 |  | 
 | 
											
												
													
														|  | -		for (c=0,from=from->child,to=to->child;from && to;from=from->next,to=to->next,c++){
 |  | 
 | 
											
												
													
														|  | -										sprintf(newpath,"%s/%d",path,c);	cJSONUtils_CompareToPatch(patches,newpath,from,to);
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		for (;from;from=from->next,c++)	{sprintf(newpath,"%d",c);	cJSONUtils_GeneratePatch(patches,"remove",path,newpath,0);	}
 |  | 
 | 
											
												
													
														|  | -		for (;to;to=to->next,c++)		cJSONUtils_GeneratePatch(patches,"add",path,"-",to);
 |  | 
 | 
											
												
													
														|  | -		free(newpath);
 |  | 
 | 
											
												
													
														|  | -		return;
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (from->type != to->type)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	case cJSON_Object:
 |  | 
 | 
											
												
													
														|  | -	{
 |  | 
 | 
											
												
													
														|  | -		cJSON *a,*b;
 |  | 
 | 
											
												
													
														|  | -		cJSONUtils_SortObject(from);
 |  | 
 | 
											
												
													
														|  | -		cJSONUtils_SortObject(to);
 |  | 
 | 
											
												
													
														|  | -		
 |  | 
 | 
											
												
													
														|  | -		a=from->child,b=to->child;
 |  | 
 | 
											
												
													
														|  | -		while (a || b)
 |  | 
 | 
											
												
													
														|  | -		{
 |  | 
 | 
											
												
													
														|  | -			int diff=(!a)?1:(!b)?-1:cJSONUtils_strcasecmp(a->string,b->string);
 |  | 
 | 
											
												
													
														|  | -			if (!diff)
 |  | 
 | 
											
												
													
														|  | -			{
 |  | 
 | 
											
												
													
														|  | -				char *newpath=(char*)malloc(strlen(path)+cJSONUtils_PointerEncodedstrlen(a->string)+2);
 |  | 
 | 
											
												
													
														|  | -				cJSONUtils_PointerEncodedstrcpy(newpath+sprintf(newpath,"%s/",path),a->string);
 |  | 
 | 
											
												
													
														|  | -				cJSONUtils_CompareToPatch(patches,newpath,a,b);
 |  | 
 | 
											
												
													
														|  | -				free(newpath);
 |  | 
 | 
											
												
													
														|  | -				a=a->next;
 |  | 
 | 
											
												
													
														|  | -				b=b->next;
 |  | 
 | 
											
												
													
														|  | -			}
 |  | 
 | 
											
												
													
														|  | -			else if (diff<0)	{cJSONUtils_GeneratePatch(patches,"remove",path,a->string,0);	a=a->next;}
 |  | 
 | 
											
												
													
														|  | -			else				{cJSONUtils_GeneratePatch(patches,"add",path,b->string,b);		b=b->next;}
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		return;
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +    switch (from->type)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        case cJSON_Number:
 | 
											
												
													
														|  | 
 |  | +            if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            return;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	default:			break;
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -}
 |  | 
 | 
											
												
													
														|  | 
 |  | +        case cJSON_String:
 | 
											
												
													
														|  | 
 |  | +            if (strcmp(from->valuestring, to->valuestring) != 0)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            return;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        case cJSON_Array:
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            int c;
 | 
											
												
													
														|  | 
 |  | +            char *newpath = (char*)malloc(strlen(path) + 23); /* Allow space for 64bit int. */
 | 
											
												
													
														|  | 
 |  | +            /* generate patches for all array elements that exist in "from" and "to" */
 | 
											
												
													
														|  | 
 |  | +            for (c = 0, from = from->child, to = to->child; from && to; from = from->next, to = to->next, c++)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                sprintf(newpath, "%s/%d", path, c); /* path of the current array element */
 | 
											
												
													
														|  | 
 |  | +                cJSONUtils_CompareToPatch(patches, newpath, from, to);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            /* remove leftover elements from 'from' that are not in 'to' */
 | 
											
												
													
														|  | 
 |  | +            for (; from; from = from->next, c++)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                sprintf(newpath, "%d", c);
 | 
											
												
													
														|  | 
 |  | +                cJSONUtils_GeneratePatch(patches, "remove", path, newpath, 0);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            /* add new elements in 'to' that were not in 'from' */
 | 
											
												
													
														|  | 
 |  | +            for (; to; to = to->next, c++)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                cJSONUtils_GeneratePatch(patches, "add", path, "-", to);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            free(newpath);
 | 
											
												
													
														|  | 
 |  | +            return;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +        case cJSON_Object:
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            cJSON *a;
 | 
											
												
													
														|  | 
 |  | +            cJSON *b;
 | 
											
												
													
														|  | 
 |  | +            cJSONUtils_SortObject(from);
 | 
											
												
													
														|  | 
 |  | +            cJSONUtils_SortObject(to);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            a = from->child;
 | 
											
												
													
														|  | 
 |  | +            b = to->child;
 | 
											
												
													
														|  | 
 |  | +            /* for all object values in the object with more of them */
 | 
											
												
													
														|  | 
 |  | +            while (a || b)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp(a->string, b->string));
 | 
											
												
													
														|  | 
 |  | +                if (!diff)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    /* both object keys are the same */
 | 
											
												
													
														|  | 
 |  | +                    char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(a->string) + 2);
 | 
											
												
													
														|  | 
 |  | +                    cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), a->string);
 | 
											
												
													
														|  | 
 |  | +                    /* create a patch for the element */
 | 
											
												
													
														|  | 
 |  | +                    cJSONUtils_CompareToPatch(patches, newpath, a, b);
 | 
											
												
													
														|  | 
 |  | +                    free(newpath);
 | 
											
												
													
														|  | 
 |  | +                    a = a->next;
 | 
											
												
													
														|  | 
 |  | +                    b = b->next;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                else if (diff < 0)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    /* object element doesn't exist in 'to' --> remove it */
 | 
											
												
													
														|  | 
 |  | +                    cJSONUtils_GeneratePatch(patches, "remove", path, a->string, 0);
 | 
											
												
													
														|  | 
 |  | +                    a = a->next;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                else
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    /* object element doesn't exist in 'from' --> add it */
 | 
											
												
													
														|  | 
 |  | +                    cJSONUtils_GeneratePatch(patches, "add", path, b->string, b);
 | 
											
												
													
														|  | 
 |  | +                    b = b->next;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            return;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        default:
 | 
											
												
													
														|  | 
 |  | +            break;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to)
 |  |  cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to)
 | 
											
												
													
														|  |  {
 |  |  {
 |