|
@@ -1306,114 +1306,278 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
|
|
}
|
|
|
|
|
|
/* Render an object to text. */
|
|
|
-static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
|
|
|
+static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p)
|
|
|
{
|
|
|
- char **entries=0,**names=0;
|
|
|
- char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
|
|
|
- cJSON *child=item->child;
|
|
|
- int numentries=0,fail=0;
|
|
|
- size_t tmplen=0;
|
|
|
- /* Count the number of entries. */
|
|
|
- while (child) numentries++,child=child->next;
|
|
|
- /* Explicitly handle empty object case */
|
|
|
- if (!numentries)
|
|
|
- {
|
|
|
- if (p) out=ensure(p,fmt?depth+4:3);
|
|
|
- else out=(char*)cJSON_malloc(fmt?depth+4:3);
|
|
|
- if (!out) return 0;
|
|
|
- ptr=out;*ptr++='{';
|
|
|
- if (fmt) {*ptr++='\n';for (i=0;i<depth;i++) *ptr++='\t';}
|
|
|
- *ptr++='}';*ptr++=0;
|
|
|
- return out;
|
|
|
- }
|
|
|
- if (p)
|
|
|
- {
|
|
|
- /* Compose the output: */
|
|
|
- i=p->offset;
|
|
|
- len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
|
|
|
- *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
|
|
|
- child=item->child;depth++;
|
|
|
- while (child)
|
|
|
- {
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- ptr=ensure(p,depth); if (!ptr) return 0;
|
|
|
- for (j=0;j<depth;j++) *ptr++='\t';
|
|
|
- p->offset+=depth;
|
|
|
- }
|
|
|
- print_string_ptr(child->string,p);
|
|
|
- p->offset=update(p);
|
|
|
-
|
|
|
- len=fmt?2:1;
|
|
|
- ptr=ensure(p,len); if (!ptr) return 0;
|
|
|
- *ptr++=':';if (fmt) *ptr++='\t';
|
|
|
- p->offset+=len;
|
|
|
-
|
|
|
- print_value(child,depth,fmt,p);
|
|
|
- p->offset=update(p);
|
|
|
-
|
|
|
- len=(fmt?1:0)+(child->next?1:0);
|
|
|
- ptr=ensure(p,len+1); if (!ptr) return 0;
|
|
|
- if (child->next) *ptr++=',';
|
|
|
- if (fmt) *ptr++='\n';*ptr=0;
|
|
|
- p->offset+=len;
|
|
|
- child=child->next;
|
|
|
- }
|
|
|
- ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
|
|
|
- if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
|
|
- *ptr++='}';*ptr=0;
|
|
|
- out=(p->buffer)+i;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* Allocate space for the names and the objects */
|
|
|
- entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
|
|
- if (!entries) return 0;
|
|
|
- names=(char**)cJSON_malloc(numentries*sizeof(char*));
|
|
|
- if (!names) {cJSON_free(entries);return 0;}
|
|
|
- memset(entries,0,sizeof(char*)*numentries);
|
|
|
- memset(names,0,sizeof(char*)*numentries);
|
|
|
-
|
|
|
- /* Collect all the results into our arrays: */
|
|
|
- child=item->child;depth++;if (fmt) len+=depth;
|
|
|
- while (child && !fail)
|
|
|
- {
|
|
|
- names[i]=str=print_string_ptr(child->string,0);
|
|
|
- entries[i++]=ret=print_value(child,depth,fmt,0);
|
|
|
- if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
|
|
|
- child=child->next;
|
|
|
- }
|
|
|
-
|
|
|
- /* Try to allocate the output string */
|
|
|
- if (!fail) out=(char*)cJSON_malloc(len);
|
|
|
- if (!out) fail=1;
|
|
|
-
|
|
|
- /* Handle failure */
|
|
|
- if (fail)
|
|
|
- {
|
|
|
- for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
|
|
|
- cJSON_free(names);cJSON_free(entries);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* Compose the output: */
|
|
|
- *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
|
|
- for (i=0;i<numentries;i++)
|
|
|
- {
|
|
|
- if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
|
|
|
- tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
|
|
|
- *ptr++=':';if (fmt) *ptr++='\t';
|
|
|
- strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
|
|
- if (i!=numentries-1) *ptr++=',';
|
|
|
- if (fmt) *ptr++='\n';*ptr=0;
|
|
|
- cJSON_free(names[i]);cJSON_free(entries[i]);
|
|
|
- }
|
|
|
-
|
|
|
- cJSON_free(names);cJSON_free(entries);
|
|
|
- if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
|
|
- *ptr++='}';*ptr++=0;
|
|
|
- }
|
|
|
- return out;
|
|
|
+ char **entries = 0;
|
|
|
+ char **names = 0;
|
|
|
+ char *out = 0;
|
|
|
+ char *ptr;
|
|
|
+ char *ret;
|
|
|
+ char *str;
|
|
|
+ int len = 7;
|
|
|
+ int i = 0;
|
|
|
+ int j;
|
|
|
+ cJSON *child = item->child;
|
|
|
+ int numentries = 0;
|
|
|
+ int fail = 0;
|
|
|
+ size_t tmplen = 0;
|
|
|
+
|
|
|
+ /* Count the number of entries. */
|
|
|
+ while (child)
|
|
|
+ {
|
|
|
+ numentries++;
|
|
|
+ child = child->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Explicitly handle empty object case */
|
|
|
+ if (!numentries)
|
|
|
+ {
|
|
|
+ if (p)
|
|
|
+ {
|
|
|
+ out = ensure(p, fmt ? depth + 4 : 3);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ out = (char*)cJSON_malloc(fmt ? depth + 4 : 3);
|
|
|
+ }
|
|
|
+ if (!out)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ ptr = out;
|
|
|
+ *ptr++ = '{';
|
|
|
+ if (fmt) {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ for (i = 0; i < depth; i++)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *ptr++ = '}';
|
|
|
+ *ptr++ = '\0';
|
|
|
+
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p)
|
|
|
+ {
|
|
|
+ /* Compose the output: */
|
|
|
+ i = p->offset;
|
|
|
+ len = fmt ? 2 : 1; /* fmt: {\n */
|
|
|
+ ptr = ensure(p, len + 1);
|
|
|
+ if (!ptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *ptr++ = '{';
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ }
|
|
|
+ *ptr = '\0';
|
|
|
+ p->offset += len;
|
|
|
+
|
|
|
+ child = item->child;
|
|
|
+ depth++;
|
|
|
+ while (child)
|
|
|
+ {
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ ptr = ensure(p, depth);
|
|
|
+ if (!ptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ for (j = 0; j < depth; j++)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ p->offset += depth;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* print key */
|
|
|
+ print_string_ptr(child->string, p);
|
|
|
+ p->offset = update(p);
|
|
|
+
|
|
|
+ len = fmt ? 2 : 1;
|
|
|
+ ptr = ensure(p, len);
|
|
|
+ if (!ptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ *ptr++ = ':';
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ p->offset+=len;
|
|
|
+
|
|
|
+ /* print value */
|
|
|
+ print_value(child, depth, fmt, p);
|
|
|
+ p->offset = update(p);
|
|
|
+
|
|
|
+ /* print comma if not last */
|
|
|
+ len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
|
|
|
+ ptr = ensure(p, len + 1);
|
|
|
+ if (!ptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (child->next)
|
|
|
+ {
|
|
|
+ *ptr++ = ',';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ }
|
|
|
+ *ptr = '\0';
|
|
|
+ p->offset += len;
|
|
|
+
|
|
|
+ child = child->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ ptr = ensure(p, fmt ? (depth + 1) : 2);
|
|
|
+ if (!ptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ for (i = 0; i < (depth - 1); i++)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *ptr++ = '}';
|
|
|
+ *ptr = '\0';
|
|
|
+ out = (p->buffer) + i;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* Allocate space for the names and the objects */
|
|
|
+ entries = (char**)cJSON_malloc(numentries * sizeof(char*));
|
|
|
+ if (!entries)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ names = (char**)cJSON_malloc(numentries * sizeof(char*));
|
|
|
+ if (!names)
|
|
|
+ {
|
|
|
+ cJSON_free(entries);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ memset(entries,0, sizeof(char*) * numentries);
|
|
|
+ memset(names, 0, sizeof(char*) * numentries);
|
|
|
+
|
|
|
+ /* Collect all the results into our arrays: */
|
|
|
+ child = item->child;
|
|
|
+ depth++;
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ len += depth;
|
|
|
+ }
|
|
|
+ while (child && !fail)
|
|
|
+ {
|
|
|
+ names[i] = str = print_string_ptr(child->string, 0); /* print key */
|
|
|
+ entries[i++] = ret = print_value(child, depth, fmt, 0);
|
|
|
+ if (str && ret)
|
|
|
+ {
|
|
|
+ len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fail = 1;
|
|
|
+ }
|
|
|
+ child = child->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Try to allocate the output string */
|
|
|
+ if (!fail)
|
|
|
+ {
|
|
|
+ out = (char*)cJSON_malloc(len);
|
|
|
+ }
|
|
|
+ if (!out)
|
|
|
+ {
|
|
|
+ fail = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Handle failure */
|
|
|
+ if (fail)
|
|
|
+ {
|
|
|
+ /* free all the printed keys and values */
|
|
|
+ for (i = 0; i < numentries; i++)
|
|
|
+ {
|
|
|
+ if (names[i])
|
|
|
+ {
|
|
|
+ cJSON_free(names[i]);
|
|
|
+ }
|
|
|
+ if (entries[i])
|
|
|
+ {
|
|
|
+ cJSON_free(entries[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ cJSON_free(names);
|
|
|
+ cJSON_free(entries);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Compose the output: */
|
|
|
+ *out = '{';
|
|
|
+ ptr = out + 1;
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ }
|
|
|
+ *ptr = 0;
|
|
|
+ for (i = 0; i < numentries; i++)
|
|
|
+ {
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ for (j = 0; j < depth; j++)
|
|
|
+ {
|
|
|
+ *ptr++='\t';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tmplen = strlen(names[i]);
|
|
|
+ memcpy(ptr, names[i], tmplen);
|
|
|
+ ptr += tmplen;
|
|
|
+ *ptr++ = ':';
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ strcpy(ptr, entries[i]);
|
|
|
+ ptr += strlen(entries[i]);
|
|
|
+ if (i != (numentries - 1))
|
|
|
+ {
|
|
|
+ *ptr++ = ',';
|
|
|
+ }
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ }
|
|
|
+ *ptr = 0;
|
|
|
+ cJSON_free(names[i]);
|
|
|
+ cJSON_free(entries[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ cJSON_free(names);
|
|
|
+ cJSON_free(entries);
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ for (i = 0; i < (depth - 1); i++)
|
|
|
+ {
|
|
|
+ *ptr++ = '\t';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *ptr++ = '}';
|
|
|
+ *ptr++ = '\0';
|
|
|
+ }
|
|
|
+
|
|
|
+ return out;
|
|
|
}
|
|
|
|
|
|
/* Get Array size/item / object item. */
|