|  | @@ -4,6 +4,13 @@
 | 
											
												
													
														|  |  #include <stdio.h>
 |  |  #include <stdio.h>
 | 
											
												
													
														|  |  #include "cJSON_Utils.h"
 |  |  #include "cJSON_Utils.h"
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +static int cJSONUtils_strcasecmp(const char *s1,const char *s2)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
 | 
											
												
													
														|  | 
 |  | +	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
 | 
											
												
													
														|  | 
 |  | +	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  /* JSON Pointer implementation: */
 |  |  /* JSON Pointer implementation: */
 | 
											
												
													
														|  |  static int cJSONUtils_Pstrcasecmp(const char *a,const char *e)
 |  |  static int cJSONUtils_Pstrcasecmp(const char *a,const char *e)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -115,13 +122,18 @@ static int cJSONUtils_Compare(cJSON *a,cJSON *b)
 | 
											
												
													
														|  |  	case cJSON_Array:	for (a=a->child,b=b->child;a && b;a=a->next,b=b->next)	{int err=cJSONUtils_Compare(a,b);if (err) return err;}
 |  |  	case cJSON_Array:	for (a=a->child,b=b->child;a && b;a=a->next,b=b->next)	{int err=cJSONUtils_Compare(a,b);if (err) return err;}
 | 
											
												
													
														|  |  						return (a || b)?-4:0;	/* array size mismatch. */
 |  |  						return (a || b)?-4:0;	/* array size mismatch. */
 | 
											
												
													
														|  |  	case cJSON_Object:
 |  |  	case cJSON_Object:
 | 
											
												
													
														|  | -						if (cJSON_GetArraySize(a)!=cJSON_GetArraySize(b))	return -5;	/* object length mismatch. */
 |  | 
 | 
											
												
													
														|  | -						for (a=a->child;a;a=a->next)
 |  | 
 | 
											
												
													
														|  | 
 |  | +						cJSONUtils_SortObject(a);
 | 
											
												
													
														|  | 
 |  | +						cJSONUtils_SortObject(b);
 | 
											
												
													
														|  | 
 |  | +						a=a->child,b=b->child;
 | 
											
												
													
														|  | 
 |  | +						while (a && b)
 | 
											
												
													
														|  |  						{
 |  |  						{
 | 
											
												
													
														|  | -							int err=0;cJSON *s=cJSON_GetObjectItem(b,a->string); if (!s) return -6;	/* missing object member. */
 |  | 
 | 
											
												
													
														|  | -							err=cJSONUtils_Compare(a,s);if (err) return err;
 |  | 
 | 
											
												
													
														|  | 
 |  | +							int err;
 | 
											
												
													
														|  | 
 |  | +							if (cJSONUtils_strcasecmp(a->string,b->string))	return -6;	/* missing member */
 | 
											
												
													
														|  | 
 |  | +							err=cJSONUtils_Compare(a,b);if (err) return err;
 | 
											
												
													
														|  | 
 |  | +							a=a->next,b=b->next;
 | 
											
												
													
														|  |  						}
 |  |  						}
 | 
											
												
													
														|  | -						return 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +						return (a || b)?-5:0;	/* object length mismatch */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	default:			break;
 |  |  	default:			break;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  	return 0;
 |  |  	return 0;
 | 
											
										
											
												
													
														|  | @@ -251,22 +263,25 @@ static void cJSONUtils_CompareToPatch(cJSON *patches,const char *path,cJSON *fro
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	case cJSON_Object:
 |  |  	case cJSON_Object:
 | 
											
												
													
														|  |  	{
 |  |  	{
 | 
											
												
													
														|  | -		cJSON *a;
 |  | 
 | 
											
												
													
														|  | -		for (a=from->child;a;a=a->next)
 |  | 
 | 
											
												
													
														|  | -		{
 |  | 
 | 
											
												
													
														|  | -			if (!cJSON_GetObjectItem(to,a->string))	cJSONUtils_GeneratePatch(patches,"remove",path,a->string,0);
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		for (a=to->child;a;a=a->next)
 |  | 
 | 
											
												
													
														|  | 
 |  | +		cJSON *a,*b;
 | 
											
												
													
														|  | 
 |  | +		cJSONUtils_SortObject(from);
 | 
											
												
													
														|  | 
 |  | +		cJSONUtils_SortObject(to);
 | 
											
												
													
														|  | 
 |  | +		
 | 
											
												
													
														|  | 
 |  | +		a=from->child,b=to->child;
 | 
											
												
													
														|  | 
 |  | +		while (a || b)
 | 
											
												
													
														|  |  		{
 |  |  		{
 | 
											
												
													
														|  | -			cJSON *other=cJSON_GetObjectItem(from,a->string);
 |  | 
 | 
											
												
													
														|  | -			if (!other)	cJSONUtils_GeneratePatch(patches,"add",path,a->string,a);
 |  | 
 | 
											
												
													
														|  | -			else
 |  | 
 | 
											
												
													
														|  | 
 |  | +			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);
 |  |  				char *newpath=(char*)malloc(strlen(path)+cJSONUtils_PointerEncodedstrlen(a->string)+2);
 | 
											
												
													
														|  |  				cJSONUtils_PointerEncodedstrcpy(newpath+sprintf(newpath,"%s/",path),a->string);
 |  |  				cJSONUtils_PointerEncodedstrcpy(newpath+sprintf(newpath,"%s/",path),a->string);
 | 
											
												
													
														|  | -				cJSONUtils_CompareToPatch(patches,newpath,other,a);
 |  | 
 | 
											
												
													
														|  | 
 |  | +				cJSONUtils_CompareToPatch(patches,newpath,a,b);
 | 
											
												
													
														|  |  				free(newpath);
 |  |  				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;
 |  |  		return;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -283,12 +298,6 @@ cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to)
 | 
											
												
													
														|  |  	return patches;
 |  |  	return patches;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -static int cJSONUtils_strcasecmp(const char *s1,const char *s2)
 |  | 
 | 
											
												
													
														|  | -{
 |  | 
 | 
											
												
													
														|  | -	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
 |  | 
 | 
											
												
													
														|  | -	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
 |  | 
 | 
											
												
													
														|  | -	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
 |  | 
 | 
											
												
													
														|  | -}
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static cJSON *cJSONUtils_SortList(cJSON *list)
 |  |  static cJSON *cJSONUtils_SortList(cJSON *list)
 | 
											
												
													
														|  |  {
 |  |  {
 |