Kaynağa Gözat

Allow for global/local error pointers. If you supply a return_parse_end
to cJSON_ParseWithOpts, then that will store the error pointer (if
parsing fails).

Dave Gamble 9 yıl önce
ebeveyn
işleme
b4151361de
2 değiştirilmiş dosya ile 36 ekleme ve 35 silme
  1. 35 35
      cJSON.c
  2. 1 0
      cJSON.h

+ 35 - 35
cJSON.c

@@ -32,9 +32,9 @@
 #include <ctype.h>
 #include "cJSON.h"
 
-static const char *ep;
+static const char *global_ep;
 
-const char *cJSON_GetErrorPtr(void) {return ep;}
+const char *cJSON_GetErrorPtr(void) {return global_ep;}
 
 static int cJSON_strcasecmp(const char *s1,const char *s2)
 {
@@ -190,10 +190,10 @@ static unsigned parse_hex4(const char *str)
 
 /* Parse the input text into an unescaped cstring, and populate item. */
 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-static const char *parse_string(cJSON *item,const char *str)
+static const char *parse_string(cJSON *item,const char *str,const char **ep)
 {
 	const char *ptr=str+1,*end_ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
-	if (*str!='\"') {ep=str;return 0;}	/* not a string! */
+	if (*str!='\"') {*ep=str;return 0;}	/* not a string! */
 	
 	while (*end_ptr!='\"' && *end_ptr && ++len) if (*end_ptr++ == '\\') end_ptr++;	/* Skip escaped quotes. */
 	
@@ -218,16 +218,16 @@ static const char *parse_string(cJSON *item,const char *str)
 				case 't': *ptr2++='\t';	break;
 				case 'u':	 /* transcode utf16 to utf8. */
 					uc=parse_hex4(ptr+1);ptr+=4;	/* get the unicode char. */
-					if (ptr >= end_ptr) {ep=str;return 0;}	/* invalid */
+					if (ptr >= end_ptr) {*ep=str;return 0;}	/* invalid */
 					
-					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    {ep=str;return 0;}	/* check for invalid.   */
+					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    {*ep=str;return 0;}	/* check for invalid.   */
 					
 					if (uc>=0xD800 && uc<=0xDBFF)	/* UTF16 surrogate pairs.	*/
 					{
-						if (ptr+6 > end_ptr)    {ep=str;return 0;}	/* invalid */
-						if (ptr[1]!='\\' || ptr[2]!='u')    {ep=str;return 0;}	/* missing second-half of surrogate.    */
+						if (ptr+6 > end_ptr)    {*ep=str;return 0;}	/* invalid */
+						if (ptr[1]!='\\' || ptr[2]!='u')    {*ep=str;return 0;}	/* missing second-half of surrogate.    */
 						uc2=parse_hex4(ptr+3);ptr+=6;
-						if (uc2<0xDC00 || uc2>0xDFFF)       {ep=str;return 0;}	/* invalid second-half of surrogate.    */
+						if (uc2<0xDC00 || uc2>0xDFFF)       {*ep=str;return 0;}	/* invalid second-half of surrogate.    */
 						uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
 					}
 
@@ -313,11 +313,11 @@ static char *print_string_ptr(const char *str,printbuffer *p)
 static char *print_string(cJSON *item,printbuffer *p)	{return print_string_ptr(item->valuestring,p);}
 
 /* Predeclare these prototypes. */
-static const char *parse_value(cJSON *item,const char *value);
+static const char *parse_value(cJSON *item,const char *value,const char **ep);
 static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
-static const char *parse_array(cJSON *item,const char *value);
+static const char *parse_array(cJSON *item,const char *value,const char **ep);
 static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
-static const char *parse_object(cJSON *item,const char *value);
+static const char *parse_object(cJSON *item,const char *value,const char **ep);
 static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
 
 /* Utility to jump whitespace and cr/lf */
@@ -326,16 +326,16 @@ static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<
 /* Parse an object - create a new root, and populate. */
 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
 {
-	const char *end=0;
+	const char *end=0,**ep=return_parse_end?return_parse_end:&global_ep;
 	cJSON *c=cJSON_New_Item();
-	ep=0;
+	*ep=0;
 	if (!c) return 0;       /* memory fail */
 
-	end=parse_value(c,skip(value));
+	end=parse_value(c,skip(value),ep);
 	if (!end)	{cJSON_Delete(c);return 0;}	/* parse failure. ep is set. */
 
 	/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
-	if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
+	if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);*ep=end;return 0;}}
 	if (return_parse_end) *return_parse_end=end;
 	return c;
 }
@@ -357,18 +357,18 @@ char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
 
 
 /* Parser core - when encountering text, process appropriately. */
-static const char *parse_value(cJSON *item,const char *value)
+static const char *parse_value(cJSON *item,const char *value,const char **ep)
 {
 	if (!value)						return 0;	/* Fail on null. */
 	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
 	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
 	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
-	if (*value=='\"')				{ return parse_string(item,value); }
+	if (*value=='\"')				{ return parse_string(item,value,ep); }
 	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
-	if (*value=='[')				{ return parse_array(item,value); }
-	if (*value=='{')				{ return parse_object(item,value); }
+	if (*value=='[')				{ return parse_array(item,value,ep); }
+	if (*value=='{')				{ return parse_object(item,value,ep); }
 
-	ep=value;return 0;	/* failure. */
+	*ep=value;return 0;	/* failure. */
 }
 
 /* Render a value to text. */
@@ -406,10 +406,10 @@ static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
 }
 
 /* Build an array from input text. */
-static const char *parse_array(cJSON *item,const char *value)
+static const char *parse_array(cJSON *item,const char *value,const char **ep)
 {
 	cJSON *child;
-	if (*value!='[')	{ep=value;return 0;}	/* not an array! */
+	if (*value!='[')	{*ep=value;return 0;}	/* not an array! */
 
 	item->type=cJSON_Array;
 	value=skip(value+1);
@@ -417,7 +417,7 @@ static const char *parse_array(cJSON *item,const char *value)
 
 	item->child=child=cJSON_New_Item();
 	if (!item->child) return 0;		 /* memory fail */
-	value=skip(parse_value(child,skip(value)));	/* skip any spacing, get the value. */
+	value=skip(parse_value(child,skip(value),ep));	/* skip any spacing, get the value. */
 	if (!value) return 0;
 
 	while (*value==',')
@@ -425,12 +425,12 @@ static const char *parse_array(cJSON *item,const char *value)
 		cJSON *new_item;
 		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
 		child->next=new_item;new_item->prev=child;child=new_item;
-		value=skip(parse_value(child,skip(value+1)));
+		value=skip(parse_value(child,skip(value+1),ep));
 		if (!value) return 0;	/* memory fail */
 	}
 
 	if (*value==']') return value+1;	/* end of array */
-	ep=value;return 0;	/* malformed. */
+	*ep=value;return 0;	/* malformed. */
 }
 
 /* Render an array to text */
@@ -514,10 +514,10 @@ static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
 }
 
 /* Build an object from the text. */
-static const char *parse_object(cJSON *item,const char *value)
+static const char *parse_object(cJSON *item,const char *value,const char **ep)
 {
 	cJSON *child;
-	if (*value!='{')	{ep=value;return 0;}	/* not an object! */
+	if (*value!='{')	{*ep=value;return 0;}	/* not an object! */
 	
 	item->type=cJSON_Object;
 	value=skip(value+1);
@@ -525,11 +525,11 @@ static const char *parse_object(cJSON *item,const char *value)
 	
 	item->child=child=cJSON_New_Item();
 	if (!item->child) return 0;
-	value=skip(parse_string(child,skip(value)));
+	value=skip(parse_string(child,skip(value),ep));
 	if (!value) return 0;
 	child->string=child->valuestring;child->valuestring=0;
-	if (*value!=':') {ep=value;return 0;}	/* fail! */
-	value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
+	if (*value!=':') {*ep=value;return 0;}	/* fail! */
+	value=skip(parse_value(child,skip(value+1),ep));	/* skip any spacing, get the value. */
 	if (!value) return 0;
 	
 	while (*value==',')
@@ -537,16 +537,16 @@ static const char *parse_object(cJSON *item,const char *value)
 		cJSON *new_item;
 		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
 		child->next=new_item;new_item->prev=child;child=new_item;
-		value=skip(parse_string(child,skip(value+1)));
+		value=skip(parse_string(child,skip(value+1),ep));
 		if (!value) return 0;
 		child->string=child->valuestring;child->valuestring=0;
-		if (*value!=':') {ep=value;return 0;}	/* fail! */
-		value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
+		if (*value!=':') {*ep=value;return 0;}	/* fail! */
+		value=skip(parse_value(child,skip(value+1),ep));	/* skip any spacing, get the value. */
 		if (!value) return 0;
 	}
 	
 	if (*value=='}') return value+1;	/* end of array */
-	ep=value;return 0;	/* malformed. */
+	*ep=value;return 0;	/* malformed. */
 }
 
 /* Render an object to text. */

+ 1 - 0
cJSON.h

@@ -126,6 +126,7 @@ need to be released. With recurse!=0, it will duplicate any children connected t
 The item->next and ->prev pointers are always zero on return from Duplicate. */
 
 /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
 extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
 
 extern void cJSON_Minify(char *json);