cJSON source code reading

前端之家收集整理的这篇文章主要介绍了cJSON source code reading前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

JSON

http://www.json.org/json-zh.html


cJSON.h

  1. /* cJSON Types: */
  2. #define cJSON_False (1 << 0)
  3. #define cJSON_True (1 << 1)
  4. #define cJSON_NULL (1 << 2)
  5. #define cJSON_Number (1 << 3)
  6. #define cJSON_String (1 << 4)
  7. #define cJSON_Array (1 << 5)
  8. #define cJSON_Object (1 << 6)
  9. #define cJSON_IsReference 256
  10. #define cJSON_StringIsConst 512
  11.  
  12. /* The cJSON structure: */
  13. typedef struct cJSON {
  14. struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively,use GetArraySize/GetArrayItem/GetObjectItem */
  15. struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
  16.  
  17. int type; /* The type of the item,as above. */
  18.  
  19. char *valuestring; /* The item's string,if type==cJSON_String */
  20. int valueint; /* The item's number,if type==cJSON_Number */
  21. double valuedouble; /* The item's number,if type==cJSON_Number */
  22.  
  23. char *string; /* The item's name string,if this item is the child of,or is in the list of subitems of an object. */
  24. } cJSON;
  1. /* You can customize memory allocation and deallocation */
  2. typedef struct cJSON_Hooks {
  3. void *(*malloc_fn)(size_t sz);
  4. void (*free_fn)(void *ptr);
  5. } cJSON_Hooks;

cJSON.c

  1. /* Memory management */
  2. static void *(*cJSON_malloc)(size_t sz) = malloc;
  3. static void (*cJSON_free)(void *ptr) = free;
  4.  
  5. void cJSON_InitHooks(cJSON_Hooks* hooks)
  6. {
  7. if (!hooks) { /* Reset hooks */
  8. cJSON_malloc = malloc;
  9. cJSON_free = free;
  10. return;
  11. }
  12.  
  13. cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
  14. cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
  15. }
  1. /* Internal constructor. */
  2. static cJSON *cJSON_New_Item(void)
  3. {
  4. cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
  5. if (node) memset(node,sizeof(cJSON));
  6. return node;
  7. }
  8.  
  9.  
  10. /* Delete a cJSON structure. */
  11. void cJSON_Delete(cJSON *c)
  12. {
  13. cJSON *next;
  14. while (c)
  15. {
  16. next=c->next;
  17. if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
  18. if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
  19. if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
  20. cJSON_free(c);
  21. c=next;
  22. }
  23. }

  1. /* String utility functions */
  2. static const char *global_ep;
  3.  
  4. const char *cJSON_GetErrorPtr(void) {return global_ep;}
  5.  
  6. static int cJSON_strcasecmp(const char *s1,const char *s2)
  7. {
  8. if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
  9. for(; tolower(*s1) == tolower(*s2); ++s1,++s2) if(*s1 == 0) return 0;
  10. return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
  11. }
  12.  
  13. static char* cJSON_strdup(const char* str)
  14. {
  15. size_t len;
  16. char* copy;
  17.  
  18. len = strlen(str) + 1;
  19. if (!(copy = (char*)cJSON_malloc(len))) return 0;
  20. memcpy(copy,str,len);
  21. return copy;
  22. }
  23.  
  1. /* Return the minimum pow(2,n) > x */
  2. static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; }
  3.  
  4. typedef struct {char *buffer; int length; int offset; } printbuffer;
  5.  
  6. static char* ensure(printbuffer *p,int needed)
  7. {
  8. char *newbuffer;int newsize;
  9. if (!p || !p->buffer) return 0;
  10. needed+=p->offset;
  11. if (needed<=p->length) return p->buffer+p->offset;
  12.  
  13. newsize=pow2gt(needed);
  14. newbuffer=(char*)cJSON_malloc(newsize);
  15. if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
  16. if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
  17. cJSON_free(p->buffer);
  18. p->length=newsize;
  19. p->buffer=newbuffer;
  20. return newbuffer+p->offset;
  21. }
  22.  
  23. static int update(printbuffer *p)
  24. {
  25. char *str;
  26. if (!p || !p->buffer) return 0;
  27. str=p->buffer+p->offset;
  28. return p->offset+strlen(str);
  29. }
  30.  
  31. char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
  32. {
  33. printbuffer p;
  34. p.buffer=(char*)cJSON_malloc(prebuffer);
  35. p.length=prebuffer;
  36. p.offset=0;
  37. return print_value(item,fmt,&p);
  38. }
  39.  
  40. static unsigned parse_hex4(const char *str)
  41. {
  42. unsigned h=0;
  43. if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
  44. h=h<<4;str++;
  45. if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
  46. h=h<<4;str++;
  47. if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
  48. h=h<<4;str++;
  49. if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
  50. return h;
  51. }
  52.  
  53. /* Utility to jump whitespace and cr/lf */
  54. static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
  1.  
  1. /* Parse and print number */
  2. /* Parse the input text to generate a number,and populate the result into item. */
  3. static const char *parse_number(cJSON *item,const char *num)
  4. {
  5. double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
  6.  
  7. if (*num=='-') sign=-1,num++; /* Has sign? */
  8. if (*num=='0') num++; /* is zero */
  9. if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
  10. if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
  11. if (*num=='e' || *num=='E') /* Exponent? */
  12. { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
  13. while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
  14. }
  15.  
  16. n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
  17. item->valuedouble=n;
  18. item->valueint=(int)n;
  19. item->type=cJSON_Number;
  20. return num;
  21. }
  22.  
  23. /* Render the number nicely from the given item into a string. */
  24. static char *print_number(cJSON *item,printbuffer *p)
  25. {
  26. char *str=0;
  27. double d=item->valuedouble;
  28. if (d==0)
  29. {
  30. if (p) str=ensure(p,2);
  31. else str=(char*)cJSON_malloc(2); /* special case for 0. */
  32. if (str) strcpy(str,"0");
  33. }
  34. else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
  35. {
  36. if (p) str=ensure(p,21);
  37. else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
  38. if (str) sprintf(str,"%d",item->valueint);
  39. }
  40. else
  41. {
  42. if (p) str=ensure(p,64);
  43. else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
  44. if (str)
  45. {
  46. if (d*0!=0) sprintf(str,"null"); /* This checks for NaN and Infinity */
  47. else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) sprintf(str,"%.0f",d);
  48. else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
  49. else sprintf(str,"%f",d);
  50. }
  51. }
  52. return str;
  53. }

  1. /* Parse and print string */
  2. /* Parse the input text into an unescaped cstring,and populate item. */
  3. static const unsigned char firstByteMark[7] = { 0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFC };
  4. static const char *parse_string(cJSON *item,const char *str,const char **ep)
  5. {
  6. const char *ptr=str+1,*end_ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
  7. if (*str!='\"') {*ep=str;return 0;} /* not a string! */
  8. while (*end_ptr!='\"' && *end_ptr && ++len) if (*end_ptr++ == '\\') end_ptr++; /* Skip escaped quotes. */
  9. out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string,roughly. */
  10. if (!out) return 0;
  11. item->valuestring=out; /* assign here so out will be deleted during cJSON_Delete() later */
  12. item->type=cJSON_String;
  13. ptr=str+1;ptr2=out;
  14. while (ptr < end_ptr)
  15. {
  16. if (*ptr!='\\') *ptr2++=*ptr++;
  17. else
  18. {
  19. ptr++;
  20. switch (*ptr)
  21. {
  22. case 'b': *ptr2++='\b'; break;
  23. case 'f': *ptr2++='\f'; break;
  24. case 'n': *ptr2++='\n'; break;
  25. case 'r': *ptr2++='\r'; break;
  26. case 't': *ptr2++='\t'; break;
  27. case 'u': /* transcode utf16 to utf8. */
  28. uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
  29. if (ptr >= end_ptr) {*ep=str;return 0;} /* invalid */
  30. if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) {*ep=str;return 0;} /* check for invalid. */
  31. if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
  32. {
  33. if (ptr+6 > end_ptr) {*ep=str;return 0;} /* invalid */
  34. if (ptr[1]!='\\' || ptr[2]!='u') {*ep=str;return 0;} /* missing second-half of surrogate. */
  35. uc2=parse_hex4(ptr+3);ptr+=6;
  36. if (uc2<0xDC00 || uc2>0xDFFF) {*ep=str;return 0;} /* invalid second-half of surrogate. */
  37. uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
  38. }
  39.  
  40. len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
  41. switch (len) {
  42. case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  43. case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  44. case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  45. case 1: *--ptr2 =(uc | firstByteMark[len]);
  46. }
  47. ptr2+=len;
  48. break;
  49. default: *ptr2++=*ptr; break;
  50. }
  51. ptr++;
  52. }
  53. }
  54. *ptr2=0;
  55. if (*ptr=='\"') ptr++;
  56. return ptr;
  57. }
  58.  
  59. /* Render the cstring provided to an escaped version that can be printed. */
  60. static char *print_string_ptr(const char *str,printbuffer *p)
  61. {
  62. const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
  63.  
  64. if (!str)
  65. {
  66. if (p) out=ensure(p,3);
  67. else out=(char*)cJSON_malloc(3);
  68. if (!out) return 0;
  69. strcpy(out,"\"\"");
  70. return out;
  71. }
  72. for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
  73. if (!flag)
  74. {
  75. len=ptr-str;
  76. if (p) out=ensure(p,len+3);
  77. else out=(char*)cJSON_malloc(len+3);
  78. if (!out) return 0;
  79. ptr2=out;*ptr2++='\"';
  80. strcpy(ptr2,str);
  81. ptr2[len]='\"';
  82. ptr2[len+1]=0;
  83. return out;
  84. }
  85. ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
  86. if (p) out=ensure(p,len+3);
  87. else out=(char*)cJSON_malloc(len+3);
  88. if (!out) return 0;
  89.  
  90. ptr2=out;ptr=str;
  91. *ptr2++='\"';
  92. while (*ptr)
  93. {
  94. if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
  95. else
  96. {
  97. *ptr2++='\\';
  98. switch (token=*ptr++)
  99. {
  100. case '\\': *ptr2++='\\'; break;
  101. case '\"': *ptr2++='\"'; break;
  102. case '\b': *ptr2++='b'; break;
  103. case '\f': *ptr2++='f'; break;
  104. case '\n': *ptr2++='n'; break;
  105. case '\r': *ptr2++='r'; break;
  106. case '\t': *ptr2++='t'; break;
  107. default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
  108. }
  109. }
  110. }
  111. *ptr2++='\"';*ptr2++=0;
  112. return out;
  113. }
  114. /* Invote print_string_ptr (which is useful) on an item. */
  115. static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);}

  1. /* Parse and print value */
  2. /* Parser core - when encountering text,process appropriately. */
  3. static const char *parse_value(cJSON *item,const char *value,const char **ep)
  4. {
  5. if (!value) return 0; /* Fail on null. */
  6. if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
  7. if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
  8. if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
  9. if (*value=='\"') { return parse_string(item,value,ep); }
  10. if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
  11. if (*value=='[') { return parse_array(item,ep); }
  12. if (*value=='{') { return parse_object(item,ep); }
  13.  
  14. *ep=value;return 0; /* failure. */
  15. }
  16.  
  17. /* Render a value to text. */
  18. static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
  19. {
  20. char *out=0;
  21. if (!item) return 0;
  22. if (p)
  23. {
  24. switch ((item->type)&255)
  25. {
  26. case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;}
  27. case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;}
  28. case cJSON_True: {out=ensure(p,"true"); break;}
  29. case cJSON_Number: out=print_number(item,p);break;
  30. case cJSON_String: out=print_string(item,p);break;
  31. case cJSON_Array: out=print_array(item,depth,p);break;
  32. case cJSON_Object: out=print_object(item,p);break;
  33. }
  34. }
  35. else
  36. {
  37. switch ((item->type)&255)
  38. {
  39. case cJSON_NULL: out=cJSON_strdup("null"); break;
  40. case cJSON_False: out=cJSON_strdup("false");break;
  41. case cJSON_True: out=cJSON_strdup("true"); break;
  42. case cJSON_Number: out=print_number(item,0);break;
  43. case cJSON_String: out=print_string(item,0);break;
  44. case cJSON_Array: out=print_array(item,0);break;
  45. case cJSON_Object: out=print_object(item,0);break;
  46. }
  47. }
  48. return out;
  49. }

  1. /* Parse and print array */
  2. /* Build an array from input text. */
  3. static const char *parse_array(cJSON *item,const char **ep)
  4. {
  5. cJSON *child;
  6. if (*value!='[') {*ep=value;return 0;} /* not an array! */
  7.  
  8. item->type=cJSON_Array;
  9. value=skip(value+1);
  10. if (*value==']') return value+1; /* empty array. */
  11.  
  12. item->child=child=cJSON_New_Item();
  13. if (!item->child) return 0; /* memory fail */
  14. value=skip(parse_value(child,skip(value),ep)); /* skip any spacing,get the value. */
  15. if (!value) return 0;
  16.  
  17. while (*value==',')
  18. {
  19. cJSON *new_item;
  20. if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
  21. child->next=new_item;new_item->prev=child;child=new_item;
  22. value=skip(parse_value(child,skip(value+1),ep));
  23. if (!value) return 0; /* memory fail */
  24. }
  25.  
  26. if (*value==']') return value+1; /* end of array */
  27. *ep=value;return 0; /* malformed. */
  28. }
  29.  
  30. /* Render an array to text */
  31. static char *print_array(cJSON *item,printbuffer *p)
  32. {
  33. char **entries;
  34. char *out=0,*ptr,*ret;int len=5;
  35. cJSON *child=item->child;
  36. int numentries=0,i=0,fail=0;
  37. size_t tmplen=0;
  38. /* How many entries in the array? */
  39. while (child) numentries++,child=child->next;
  40. /* Explicitly handle numentries==0 */
  41. if (!numentries)
  42. {
  43. if (p) out=ensure(p,3);
  44. else out=(char*)cJSON_malloc(3);
  45. if (out) strcpy(out,"[]");
  46. return out;
  47. }
  48.  
  49. if (p)
  50. {
  51. /* Compose the output array. */
  52. i=p->offset;
  53. ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++;
  54. child=item->child;
  55. while (child && !fail)
  56. {
  57. print_value(child,depth+1,p);
  58. p->offset=update(p);
  59. if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
  60. child=child->next;
  61. }
  62. ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
  63. out=(p->buffer)+i;
  64. }
  65. else
  66. {
  67. /* Allocate an array to hold the values for each */
  68. entries=(char**)cJSON_malloc(numentries*sizeof(char*));
  69. if (!entries) return 0;
  70. memset(entries,numentries*sizeof(char*));
  71. /* Retrieve all the results: */
  72. child=item->child;
  73. while (child && !fail)
  74. {
  75. ret=print_value(child,0);
  76. entries[i++]=ret;
  77. if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
  78. child=child->next;
  79. }
  80. /* If we didn't fail,try to malloc the output string */
  81. if (!fail) out=(char*)cJSON_malloc(len);
  82. /* If that fails,we fail. */
  83. if (!out) fail=1;
  84.  
  85. /* Handle failure. */
  86. if (fail)
  87. {
  88. for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
  89. cJSON_free(entries);
  90. return 0;
  91. }
  92. /* Compose the output array. */
  93. *out='[';
  94. ptr=out+1;*ptr=0;
  95. for (i=0;i<numentries;i++)
  96. {
  97. tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
  98. if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
  99. cJSON_free(entries[i]);
  100. }
  101. cJSON_free(entries);
  102. *ptr++=']';*ptr++=0;
  103. }
  104. return out;
  105. }

  1. /* Parse and print object */
  2. /* Build an object from the text. */
  3. static const char *parse_object(cJSON *item,const char **ep)
  4. {
  5. cJSON *child;
  6. if (*value!='{') {*ep=value;return 0;} /* not an object! */
  7. item->type=cJSON_Object;
  8. value=skip(value+1);
  9. if (*value=='}') return value+1; /* empty array. */
  10. item->child=child=cJSON_New_Item();
  11. if (!item->child) return 0;
  12. value=skip(parse_string(child,ep));
  13. if (!value) return 0;
  14. child->string=child->valuestring;child->valuestring=0;
  15. if (*value!=':') {*ep=value;return 0;} /* fail! */
  16. value=skip(parse_value(child,get the value. */
  17. if (!value) return 0;
  18. while (*value==',')
  19. {
  20. cJSON *new_item;
  21. if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
  22. child->next=new_item;new_item->prev=child;child=new_item;
  23. value=skip(parse_string(child,ep));
  24. if (!value) return 0;
  25. child->string=child->valuestring;child->valuestring=0;
  26. if (*value!=':') {*ep=value;return 0;} /* fail! */
  27. value=skip(parse_value(child,get the value. */
  28. if (!value) return 0;
  29. }
  30. if (*value=='}') return value+1; /* end of array */
  31. *ep=value;return 0; /* malformed. */
  32. }
  33.  
  34. /* Render an object to text. */
  35. static char *print_object(cJSON *item,printbuffer *p)
  36. {
  37. char **entries=0,**names=0;
  38. char *out=0,*ret,*str;int len=7,j;
  39. cJSON *child=item->child;
  40. int numentries=0,fail=0;
  41. size_t tmplen=0;
  42. /* Count the number of entries. */
  43. while (child) numentries++,child=child->next;
  44. /* Explicitly handle empty object case */
  45. if (!numentries)
  46. {
  47. if (p) out=ensure(p,fmt?depth+4:3);
  48. else out=(char*)cJSON_malloc(fmt?depth+4:3);
  49. if (!out) return 0;
  50. ptr=out;*ptr++='{';
  51. if (fmt) {*ptr++='\n';for (i=0;i<depth;i++) *ptr++='\t';}
  52. *ptr++='}';*ptr++=0;
  53. return out;
  54. }
  55. if (p)
  56. {
  57. /* Compose the output: */
  58. i=p->offset;
  59. len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
  60. *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
  61. child=item->child;depth++;
  62. while (child)
  63. {
  64. if (fmt)
  65. {
  66. ptr=ensure(p,depth); if (!ptr) return 0;
  67. for (j=0;j<depth;j++) *ptr++='\t';
  68. p->offset+=depth;
  69. }
  70. print_string_ptr(child->string,p);
  71. p->offset=update(p);
  72. len=fmt?2:1;
  73. ptr=ensure(p,len); if (!ptr) return 0;
  74. *ptr++=':';if (fmt) *ptr++='\t';
  75. p->offset+=len;
  76. print_value(child,p);
  77. p->offset=update(p);
  78.  
  79. len=(fmt?1:0)+(child->next?1:0);
  80. ptr=ensure(p,len+1); if (!ptr) return 0;
  81. if (child->next) *ptr++=',';
  82. if (fmt) *ptr++='\n';*ptr=0;
  83. p->offset+=len;
  84. child=child->next;
  85. }
  86. ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
  87. if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
  88. *ptr++='}';*ptr=0;
  89. out=(p->buffer)+i;
  90. }
  91. else
  92. {
  93. /* Allocate space for the names and the objects */
  94. entries=(char**)cJSON_malloc(numentries*sizeof(char*));
  95. if (!entries) return 0;
  96. names=(char**)cJSON_malloc(numentries*sizeof(char*));
  97. if (!names) {cJSON_free(entries);return 0;}
  98. memset(entries,sizeof(char*)*numentries);
  99. memset(names,sizeof(char*)*numentries);
  100.  
  101. /* Collect all the results into our arrays: */
  102. child=item->child;depth++;if (fmt) len+=depth;
  103. while (child && !fail)
  104. {
  105. names[i]=str=print_string_ptr(child->string,0);
  106. entries[i++]=ret=print_value(child,0);
  107. if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
  108. child=child->next;
  109. }
  110. /* Try to allocate the output string */
  111. if (!fail) out=(char*)cJSON_malloc(len);
  112. if (!out) fail=1;
  113.  
  114. /* Handle failure */
  115. if (fail)
  116. {
  117. for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
  118. cJSON_free(names);cJSON_free(entries);
  119. return 0;
  120. }
  121. /* Compose the output: */
  122. *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
  123. for (i=0;i<numentries;i++)
  124. {
  125. if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
  126. tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
  127. *ptr++=':';if (fmt) *ptr++='\t';
  128. strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
  129. if (i!=numentries-1) *ptr++=',';
  130. if (fmt) *ptr++='\n';*ptr=0;
  131. cJSON_free(names[i]);cJSON_free(entries[i]);
  132. }
  133. cJSON_free(names);cJSON_free(entries);
  134. if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
  135. *ptr++='}';*ptr++=0;
  136. }
  137. return out;
  138. }


  1. /* Wrapper for parse and print */
  2. /* Parse an object - create a new root,and populate. */
  3. cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
  4. {
  5. const char *end=0,**ep=return_parse_end?return_parse_end:&global_ep;
  6. cJSON *c=cJSON_New_Item();
  7. *ep=0;
  8. if (!c) return 0; /* memory fail */
  9.  
  10. end=parse_value(c,ep);
  11. if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
  12.  
  13. /* if we require null-terminated JSON without appended garbage,skip and then check for a null terminator */
  14. if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);*ep=end;return 0;}}
  15. if (return_parse_end) *return_parse_end=end;
  16. return c;
  17. }
  18. /* Default options for cJSON_Parse */
  19. cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0);}
  20.  
  21. /* Render a cJSON item/entity/structure to text. */
  22. char *cJSON_Print(cJSON *item) {return print_value(item,1,0);}
  23. char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0);}

  1. /* JSON utility functions */
  2. /* Get Array size/item / object item. */
  3. int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
  4. cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array?array->child:0;while (c && item>0) item--,c=c->next; return c;}
  5. cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object?object->child:0;while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
  6. int cJSON_HasObjectItem(cJSON *object,const char *string) {return cJSON_GetObjectItem(object,string)?1:0;}
  7.  
  8. /* Utility for array list handling. */
  9. static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
  10. /* Utility for handling references. */
  11. static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
  12.  
  13. /* Add item to array/object. */
  14. void cJSON_AddItemToArray(cJSON *array,cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
  15. void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
  16. void cJSON_AddItemToObjectCS(cJSON *object,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
  17. void cJSON_AddItemReferenceToArray(cJSON *array,cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
  18. void cJSON_AddItemReferenceToObject(cJSON *object,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
  19.  
  20. cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
  21. if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
  22. void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
  23. cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
  24. void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
  25.  
  26. /* Replace array/object items with new ones. */
  27. void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
  28. newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
  29. void cJSON_ReplaceItemInArray(cJSON *array,which--;if (!c) return;
  30. newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
  31. if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
  32. void cJSON_ReplaceItemInObject(cJSON *object,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
  33.  
  34. /* Create basic types: */
  35. cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
  36. cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
  37. cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
  38. cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
  39. cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
  40. cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);if(!item->valuestring){cJSON_Delete(item);return 0;}}return item;}
  41. cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
  42. cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
  43.  
  44. /* Create Arrays: */
  45. cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
  46. cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,n);p=n;}return a;}
  47. cJSON *cJSON_CreateDoubleArray(const double *numbers,n);p=n;}return a;}
  48. cJSON *cJSON_CreateStringArray(const char **strings,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
  1. /* Duplication */
  2. cJSON *cJSON_Duplicate(cJSON *item,int recurse)
  3. {
  4. cJSON *newitem,*cptr,*nptr=0,*newchild;
  5. /* Bail on bad ptr */
  6. if (!item) return 0;
  7. /* Create new item */
  8. newitem=cJSON_New_Item();
  9. if (!newitem) return 0;
  10. /* Copy over all vars */
  11. newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
  12. if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
  13. if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
  14. /* If non-recursive,then we're done! */
  15. if (!recurse) return newitem;
  16. /* Walk the ->next chain for the child. */
  17. cptr=item->child;
  18. while (cptr)
  19. {
  20. newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
  21. if (!newchild) {cJSON_Delete(newitem);return 0;}
  22. if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set,then crosswire ->prev and ->next and move on */
  23. else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
  24. cptr=cptr->next;
  25. }
  26. return newitem;
  27. }
  28.  
  29. void cJSON_Minify(char *json)
  30. {
  31. char *into=json;
  32. while (*json)
  33. {
  34. if (*json==' ') json++;
  35. else if (*json=='\t') json++; /* Whitespace characters. */
  36. else if (*json=='\r') json++;
  37. else if (*json=='\n') json++;
  38. else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments,to end of line. */
  39. else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */
  40. else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals,which are \" sensitive. */
  41. else *into++=*json++; /* All other characters. */
  42. }
  43. *into=0; /* and null-terminate. */
  44. }

Reference

https://github.com/DaveGamble/cJSON

猜你在找的Json相关文章