提交 b4151361 编写于 作者: D Dave Gamble

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).
上级 c6d868cf
......@@ -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. */
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册