|
@@ -241,9 +241,9 @@ static unsigned char* ensure(printbuffer *p, size_t needed)
|
|
|
unsigned char *newbuffer = NULL;
|
|
|
size_t newsize = 0;
|
|
|
|
|
|
- if (p == NULL)
|
|
|
+ if ((p == NULL) || (p->buffer == NULL))
|
|
|
{
|
|
|
- return (unsigned char*)cJSON_malloc(needed);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
if (needed > INT_MAX)
|
|
@@ -252,10 +252,6 @@ static unsigned char* ensure(printbuffer *p, size_t needed)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- if (p->buffer == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
needed += p->offset;
|
|
|
if (needed <= p->length)
|
|
|
{
|
|
@@ -328,6 +324,12 @@ static unsigned char *print_number(const cJSON *item, printbuffer *p)
|
|
|
{
|
|
|
unsigned char *str = NULL;
|
|
|
double d = item->valuedouble;
|
|
|
+
|
|
|
+ if (p == NULL)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
/* special case for 0. */
|
|
|
if (d == 0)
|
|
|
{
|
|
@@ -678,6 +680,11 @@ static unsigned char *print_string_ptr(const unsigned char *str, printbuffer *p)
|
|
|
cjbool flag = false;
|
|
|
unsigned char token = '\0';
|
|
|
|
|
|
+ if (p == NULL)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
/* empty string */
|
|
|
if (!str)
|
|
|
{
|
|
@@ -865,15 +872,66 @@ cJSON *cJSON_Parse(const char *value)
|
|
|
return cJSON_ParseWithOpts(value, 0, 0);
|
|
|
}
|
|
|
|
|
|
+#define min(a, b) ((a < b) ? a : b)
|
|
|
+
|
|
|
+static unsigned char *print(const cJSON * const item, cjbool format)
|
|
|
+{
|
|
|
+ printbuffer buffer[1];
|
|
|
+ unsigned char *printed = NULL;
|
|
|
+
|
|
|
+ memset(buffer, 0, sizeof(buffer));
|
|
|
+
|
|
|
+ /* create buffer */
|
|
|
+ buffer->buffer = (unsigned char*) cJSON_malloc(256);
|
|
|
+ if (buffer->buffer == NULL)
|
|
|
+ {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* print the value */
|
|
|
+ if (print_value(item, 0, format, buffer) == NULL)
|
|
|
+ {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ buffer->offset = update(buffer); /* update the length of the string */
|
|
|
+
|
|
|
+ /* copy the buffer over to a new one */
|
|
|
+ printed = (unsigned char*) cJSON_malloc(buffer->offset + 1);
|
|
|
+ if (printed == NULL)
|
|
|
+ {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ strncpy((char*)printed, (char*)buffer->buffer, min(buffer->length, buffer->offset + 1));
|
|
|
+ printed[buffer->offset] = '\0'; /* just to be sure */
|
|
|
+
|
|
|
+ /* free the buffer */
|
|
|
+ cJSON_free(buffer->buffer);
|
|
|
+
|
|
|
+ return printed;
|
|
|
+
|
|
|
+fail:
|
|
|
+ if (buffer->buffer != NULL)
|
|
|
+ {
|
|
|
+ cJSON_free(buffer->buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (printed != NULL)
|
|
|
+ {
|
|
|
+ cJSON_free(printed);
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/* Render a cJSON item/entity/structure to text. */
|
|
|
char *cJSON_Print(const cJSON *item)
|
|
|
{
|
|
|
- return (char*)print_value(item, 0, 1, 0);
|
|
|
+ return (char*)print(item, true);
|
|
|
}
|
|
|
|
|
|
char *cJSON_PrintUnformatted(const cJSON *item)
|
|
|
{
|
|
|
- return (char*)print_value(item, 0, 0, 0);
|
|
|
+ return (char*)print(item, false);
|
|
|
}
|
|
|
|
|
|
char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
|
|
@@ -977,101 +1035,71 @@ static unsigned char *print_value(const cJSON *item, size_t depth, cjbool fmt, p
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
- if (p)
|
|
|
+
|
|
|
+ if (p == NULL)
|
|
|
{
|
|
|
- switch ((item->type) & 0xFF)
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch ((item->type) & 0xFF)
|
|
|
+ {
|
|
|
+ case cJSON_NULL:
|
|
|
+ out = ensure(p, 5);
|
|
|
+ if (out != NULL)
|
|
|
+ {
|
|
|
+ strcpy((char*)out, "null");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case cJSON_False:
|
|
|
+ out = ensure(p, 6);
|
|
|
+ if (out != NULL)
|
|
|
+ {
|
|
|
+ strcpy((char*)out, "false");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case cJSON_True:
|
|
|
+ out = ensure(p, 5);
|
|
|
+ if (out != NULL)
|
|
|
+ {
|
|
|
+ strcpy((char*)out, "true");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case cJSON_Number:
|
|
|
+ out = print_number(item, p);
|
|
|
+ break;
|
|
|
+ case cJSON_Raw:
|
|
|
{
|
|
|
- case cJSON_NULL:
|
|
|
- out = ensure(p, 5);
|
|
|
- if (out != NULL)
|
|
|
- {
|
|
|
- strcpy((char*)out, "null");
|
|
|
- }
|
|
|
- break;
|
|
|
- case cJSON_False:
|
|
|
- out = ensure(p, 6);
|
|
|
- if (out != NULL)
|
|
|
- {
|
|
|
- strcpy((char*)out, "false");
|
|
|
- }
|
|
|
- break;
|
|
|
- case cJSON_True:
|
|
|
- out = ensure(p, 5);
|
|
|
- if (out != NULL)
|
|
|
- {
|
|
|
- strcpy((char*)out, "true");
|
|
|
- }
|
|
|
- break;
|
|
|
- case cJSON_Number:
|
|
|
- out = print_number(item, p);
|
|
|
- break;
|
|
|
- case cJSON_Raw:
|
|
|
+ size_t raw_length = 0;
|
|
|
+ if (item->valuestring == NULL)
|
|
|
{
|
|
|
- size_t raw_length = 0;
|
|
|
- if (item->valuestring == NULL)
|
|
|
+ if (!p->noalloc)
|
|
|
{
|
|
|
- if (!p->noalloc)
|
|
|
- {
|
|
|
- cJSON_free(p->buffer);
|
|
|
- }
|
|
|
- out = NULL;
|
|
|
- break;
|
|
|
+ cJSON_free(p->buffer);
|
|
|
}
|
|
|
-
|
|
|
- raw_length = strlen(item->valuestring) + sizeof('\0');
|
|
|
- out = ensure(p, raw_length);
|
|
|
- if (out != NULL)
|
|
|
- {
|
|
|
- memcpy(out, item->valuestring, raw_length);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- case cJSON_String:
|
|
|
- out = print_string(item, p);
|
|
|
- break;
|
|
|
- case cJSON_Array:
|
|
|
- out = print_array(item, depth, fmt, p);
|
|
|
- break;
|
|
|
- case cJSON_Object:
|
|
|
- out = print_object(item, depth, fmt, p);
|
|
|
- break;
|
|
|
- default:
|
|
|
- out = NULL;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- switch ((item->type) & 0xFF)
|
|
|
- {
|
|
|
- case cJSON_NULL:
|
|
|
- out = cJSON_strdup((const unsigned char*)"null");
|
|
|
- break;
|
|
|
- case cJSON_False:
|
|
|
- out = cJSON_strdup((const unsigned char*)"false");
|
|
|
- break;
|
|
|
- case cJSON_True:
|
|
|
- out = cJSON_strdup((const unsigned char*)"true");
|
|
|
- break;
|
|
|
- case cJSON_Number:
|
|
|
- out = print_number(item, 0);
|
|
|
- break;
|
|
|
- case cJSON_Raw:
|
|
|
- out = cJSON_strdup((unsigned char*)item->valuestring);
|
|
|
- break;
|
|
|
- case cJSON_String:
|
|
|
- out = print_string(item, 0);
|
|
|
- break;
|
|
|
- case cJSON_Array:
|
|
|
- out = print_array(item, depth, fmt, 0);
|
|
|
- break;
|
|
|
- case cJSON_Object:
|
|
|
- out = print_object(item, depth, fmt, 0);
|
|
|
- break;
|
|
|
- default:
|
|
|
out = NULL;
|
|
|
break;
|
|
|
+ }
|
|
|
+
|
|
|
+ raw_length = strlen(item->valuestring) + sizeof('\0');
|
|
|
+ out = ensure(p, raw_length);
|
|
|
+ if (out != NULL)
|
|
|
+ {
|
|
|
+ memcpy(out, item->valuestring, raw_length);
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
+ case cJSON_String:
|
|
|
+ out = print_string(item, p);
|
|
|
+ break;
|
|
|
+ case cJSON_Array:
|
|
|
+ out = print_array(item, depth, fmt, p);
|
|
|
+ break;
|
|
|
+ case cJSON_Object:
|
|
|
+ out = print_object(item, depth, fmt, p);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ out = NULL;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
return out;
|
|
@@ -1158,16 +1186,18 @@ fail:
|
|
|
/* Render an array to text */
|
|
|
static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p)
|
|
|
{
|
|
|
- unsigned char **entries;
|
|
|
unsigned char *out = NULL;
|
|
|
unsigned char *ptr = NULL;
|
|
|
- unsigned char *ret = NULL;
|
|
|
size_t len = 5;
|
|
|
cJSON *child = item->child;
|
|
|
size_t numentries = 0;
|
|
|
size_t i = 0;
|
|
|
cjbool fail = false;
|
|
|
- size_t tmplen = 0;
|
|
|
+
|
|
|
+ if (p == NULL)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
/* How many entries in the array? */
|
|
|
while (child)
|
|
@@ -1188,131 +1218,51 @@ static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, p
|
|
|
return out;
|
|
|
}
|
|
|
|
|
|
- if (p)
|
|
|
+ /* Compose the output array. */
|
|
|
+ /* opening square bracket */
|
|
|
+ i = p->offset;
|
|
|
+ ptr = ensure(p, 1);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
- /* Compose the output array. */
|
|
|
- /* opening square bracket */
|
|
|
- i = p->offset;
|
|
|
- ptr = ensure(p, 1);
|
|
|
- if (ptr == NULL)
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ *ptr = '[';
|
|
|
+ p->offset++;
|
|
|
+
|
|
|
+ child = item->child;
|
|
|
+ while (child && !fail)
|
|
|
+ {
|
|
|
+ if (!print_value(child, depth + 1, fmt, p))
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
- *ptr = '[';
|
|
|
- p->offset++;
|
|
|
-
|
|
|
- child = item->child;
|
|
|
- while (child && !fail)
|
|
|
+ p->offset = update(p);
|
|
|
+ if (child->next)
|
|
|
{
|
|
|
- if (!print_value(child, depth + 1, fmt, p))
|
|
|
+ len = fmt ? 2 : 1;
|
|
|
+ ptr = ensure(p, len + 1);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
- p->offset = update(p);
|
|
|
- if (child->next)
|
|
|
+ *ptr++ = ',';
|
|
|
+ if(fmt)
|
|
|
{
|
|
|
- len = fmt ? 2 : 1;
|
|
|
- ptr = ensure(p, len + 1);
|
|
|
- if (ptr == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- *ptr++ = ',';
|
|
|
- if(fmt)
|
|
|
- {
|
|
|
- *ptr++ = ' ';
|
|
|
- }
|
|
|
- *ptr = '\0';
|
|
|
- p->offset += len;
|
|
|
+ *ptr++ = ' ';
|
|
|
}
|
|
|
- child = child->next;
|
|
|
- }
|
|
|
- ptr = ensure(p, 2);
|
|
|
- if (ptr == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
+ *ptr = '\0';
|
|
|
+ p->offset += len;
|
|
|
}
|
|
|
- *ptr++ = ']';
|
|
|
- *ptr = '\0';
|
|
|
- out = (p->buffer) + i;
|
|
|
+ child = child->next;
|
|
|
}
|
|
|
- else
|
|
|
+ ptr = ensure(p, 2);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
- /* Allocate an array to hold the pointers to all printed values */
|
|
|
- entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
|
|
|
- if (!entries)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- memset(entries, '\0', numentries * sizeof(unsigned char*));
|
|
|
-
|
|
|
- /* Retrieve all the results: */
|
|
|
- child = item->child;
|
|
|
- while (child && !fail)
|
|
|
- {
|
|
|
- ret = print_value(child, depth + 1, fmt, 0);
|
|
|
- entries[i++] = ret;
|
|
|
- if (ret)
|
|
|
- {
|
|
|
- len += strlen((char*)ret) + 2 + (fmt ? 1 : 0);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fail = true;
|
|
|
- }
|
|
|
- child = child->next;
|
|
|
- }
|
|
|
-
|
|
|
- /* If we didn't fail, try to malloc the output string */
|
|
|
- if (!fail)
|
|
|
- {
|
|
|
- out = (unsigned char*)cJSON_malloc(len);
|
|
|
- }
|
|
|
- /* If that fails, we fail. */
|
|
|
- if (!out)
|
|
|
- {
|
|
|
- fail = true;
|
|
|
- }
|
|
|
-
|
|
|
- /* Handle failure. */
|
|
|
- if (fail)
|
|
|
- {
|
|
|
- /* free all the entries in the array */
|
|
|
- for (i = 0; i < numentries; i++)
|
|
|
- {
|
|
|
- if (entries[i])
|
|
|
- {
|
|
|
- cJSON_free(entries[i]);
|
|
|
- }
|
|
|
- }
|
|
|
- cJSON_free(entries);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- /* Compose the output array. */
|
|
|
- *out='[';
|
|
|
- ptr = out + 1;
|
|
|
- *ptr = '\0';
|
|
|
- for (i = 0; i < numentries; i++)
|
|
|
- {
|
|
|
- tmplen = strlen((char*)entries[i]);
|
|
|
- memcpy(ptr, entries[i], tmplen);
|
|
|
- ptr += tmplen;
|
|
|
- if (i != (numentries - 1))
|
|
|
- {
|
|
|
- *ptr++ = ',';
|
|
|
- if(fmt)
|
|
|
- {
|
|
|
- *ptr++ = ' ';
|
|
|
- }
|
|
|
- *ptr = '\0';
|
|
|
- }
|
|
|
- cJSON_free(entries[i]);
|
|
|
- }
|
|
|
- cJSON_free(entries);
|
|
|
- *ptr++ = ']';
|
|
|
- *ptr++ = '\0';
|
|
|
+ return NULL;
|
|
|
}
|
|
|
+ *ptr++ = ']';
|
|
|
+ *ptr = '\0';
|
|
|
+ out = (p->buffer) + i;
|
|
|
|
|
|
return out;
|
|
|
}
|
|
@@ -1415,19 +1365,18 @@ fail:
|
|
|
/* Render an object to text. */
|
|
|
static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p)
|
|
|
{
|
|
|
- unsigned char **entries = NULL;
|
|
|
- unsigned char **names = NULL;
|
|
|
unsigned char *out = NULL;
|
|
|
unsigned char *ptr = NULL;
|
|
|
- unsigned char *ret = NULL;
|
|
|
- unsigned char *str = NULL;
|
|
|
size_t len = 7;
|
|
|
size_t i = 0;
|
|
|
size_t j = 0;
|
|
|
cJSON *child = item->child;
|
|
|
size_t numentries = 0;
|
|
|
- cjbool fail = false;
|
|
|
- size_t tmplen = 0;
|
|
|
+
|
|
|
+ if (p == NULL)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
/* Count the number of entries. */
|
|
|
while (child)
|
|
@@ -1459,229 +1408,105 @@ static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt,
|
|
|
return out;
|
|
|
}
|
|
|
|
|
|
- if (p)
|
|
|
+ /* Compose the output: */
|
|
|
+ i = p->offset;
|
|
|
+ len = fmt ? 2 : 1; /* fmt: {\n */
|
|
|
+ ptr = ensure(p, len + 1);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
- /* Compose the output: */
|
|
|
- i = p->offset;
|
|
|
- len = fmt ? 2 : 1; /* fmt: {\n */
|
|
|
- ptr = ensure(p, len + 1);
|
|
|
- if (ptr == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
- *ptr++ = '{';
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- *ptr++ = '\n';
|
|
|
- }
|
|
|
- *ptr = '\0';
|
|
|
- p->offset += len;
|
|
|
+ *ptr++ = '{';
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ *ptr++ = '\n';
|
|
|
+ }
|
|
|
+ *ptr = '\0';
|
|
|
+ p->offset += len;
|
|
|
|
|
|
- child = item->child;
|
|
|
- depth++;
|
|
|
- while (child)
|
|
|
+ child = item->child;
|
|
|
+ depth++;
|
|
|
+ while (child)
|
|
|
+ {
|
|
|
+ if (fmt)
|
|
|
{
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- ptr = ensure(p, depth);
|
|
|
- if (ptr == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- for (j = 0; j < depth; j++)
|
|
|
- {
|
|
|
- *ptr++ = '\t';
|
|
|
- }
|
|
|
- p->offset += depth;
|
|
|
- }
|
|
|
-
|
|
|
- /* print key */
|
|
|
- if (!print_string_ptr((unsigned char*)child->string, p))
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- p->offset = update(p);
|
|
|
-
|
|
|
- len = fmt ? 2 : 1;
|
|
|
- ptr = ensure(p, len);
|
|
|
+ ptr = ensure(p, depth);
|
|
|
if (ptr == NULL)
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
- *ptr++ = ':';
|
|
|
- if (fmt)
|
|
|
+ for (j = 0; j < depth; j++)
|
|
|
{
|
|
|
*ptr++ = '\t';
|
|
|
}
|
|
|
- p->offset+=len;
|
|
|
-
|
|
|
- /* print value */
|
|
|
- if (!print_value(child, depth, fmt, p))
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- };
|
|
|
- p->offset = update(p);
|
|
|
-
|
|
|
- /* print comma if not last */
|
|
|
- len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0);
|
|
|
- ptr = ensure(p, len + 1);
|
|
|
- if (ptr == NULL)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- if (child->next)
|
|
|
- {
|
|
|
- *ptr++ = ',';
|
|
|
- }
|
|
|
-
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- *ptr++ = '\n';
|
|
|
- }
|
|
|
- *ptr = '\0';
|
|
|
- p->offset += len;
|
|
|
-
|
|
|
- child = child->next;
|
|
|
+ p->offset += depth;
|
|
|
}
|
|
|
|
|
|
- ptr = ensure(p, fmt ? (depth + 1) : 2);
|
|
|
- if (ptr == NULL)
|
|
|
+ /* print key */
|
|
|
+ if (!print_string_ptr((unsigned char*)child->string, p))
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
- 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 = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
|
|
|
- if (!entries)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- names = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
|
|
|
- if (!names)
|
|
|
+ p->offset = update(p);
|
|
|
+
|
|
|
+ len = fmt ? 2 : 1;
|
|
|
+ ptr = ensure(p, len);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
- cJSON_free(entries);
|
|
|
return NULL;
|
|
|
}
|
|
|
- memset(entries, '\0', sizeof(unsigned char*) * numentries);
|
|
|
- memset(names, '\0', sizeof(unsigned char*) * numentries);
|
|
|
-
|
|
|
- /* Collect all the results into our arrays: */
|
|
|
- child = item->child;
|
|
|
- depth++;
|
|
|
+ *ptr++ = ':';
|
|
|
if (fmt)
|
|
|
{
|
|
|
- len += depth;
|
|
|
- }
|
|
|
- while (child && !fail)
|
|
|
- {
|
|
|
- names[i] = str = print_string_ptr((unsigned char*)child->string, 0); /* print key */
|
|
|
- entries[i++] = ret = print_value(child, depth, fmt, 0);
|
|
|
- if (str && ret)
|
|
|
- {
|
|
|
- len += strlen((char*)ret) + strlen((char*)str) + 2 + (fmt ? 2 + depth : 0);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fail = true;
|
|
|
- }
|
|
|
- child = child->next;
|
|
|
+ *ptr++ = '\t';
|
|
|
}
|
|
|
+ p->offset+=len;
|
|
|
|
|
|
- /* Try to allocate the output string */
|
|
|
- if (!fail)
|
|
|
+ /* print value */
|
|
|
+ if (!print_value(child, depth, fmt, p))
|
|
|
{
|
|
|
- out = (unsigned char*)cJSON_malloc(len);
|
|
|
- }
|
|
|
- if (!out)
|
|
|
- {
|
|
|
- fail = true;
|
|
|
+ return NULL;
|
|
|
}
|
|
|
+ p->offset = update(p);
|
|
|
|
|
|
- /* Handle failure */
|
|
|
- if (fail)
|
|
|
+ /* print comma if not last */
|
|
|
+ len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0);
|
|
|
+ ptr = ensure(p, len + 1);
|
|
|
+ if (ptr == NULL)
|
|
|
{
|
|
|
- /* 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 NULL;
|
|
|
}
|
|
|
+ if (child->next)
|
|
|
+ {
|
|
|
+ *ptr++ = ',';
|
|
|
+ }
|
|
|
|
|
|
- /* 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((char*)names[i]);
|
|
|
- memcpy(ptr, names[i], tmplen);
|
|
|
- ptr += tmplen;
|
|
|
- *ptr++ = ':';
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- *ptr++ = '\t';
|
|
|
- }
|
|
|
- strcpy((char*)ptr, (char*)entries[i]);
|
|
|
- ptr += strlen((char*)entries[i]);
|
|
|
- if (i != (numentries - 1))
|
|
|
- {
|
|
|
- *ptr++ = ',';
|
|
|
- }
|
|
|
- if (fmt)
|
|
|
- {
|
|
|
- *ptr++ = '\n';
|
|
|
- }
|
|
|
- *ptr = '\0';
|
|
|
- cJSON_free(names[i]);
|
|
|
- cJSON_free(entries[i]);
|
|
|
- }
|
|
|
+ p->offset += len;
|
|
|
|
|
|
- cJSON_free(names);
|
|
|
- cJSON_free(entries);
|
|
|
- if (fmt)
|
|
|
+ child = child->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ ptr = ensure(p, fmt ? (depth + 1) : 2);
|
|
|
+ if (ptr == NULL)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ if (fmt)
|
|
|
+ {
|
|
|
+ for (i = 0; i < (depth - 1); i++)
|
|
|
{
|
|
|
- for (i = 0; i < (depth - 1); i++)
|
|
|
- {
|
|
|
- *ptr++ = '\t';
|
|
|
- }
|
|
|
+ *ptr++ = '\t';
|
|
|
}
|
|
|
- *ptr++ = '}';
|
|
|
- *ptr++ = '\0';
|
|
|
}
|
|
|
+ *ptr++ = '}';
|
|
|
+ *ptr = '\0';
|
|
|
+ out = (p->buffer) + i;
|
|
|
|
|
|
return out;
|
|
|
}
|