diff --git a/cJSON.c b/cJSON.c index 3dc6491..4263c9b 100644 --- a/cJSON.c +++ b/cJSON.c @@ -244,6 +244,7 @@ typedef struct char *buffer; int length; int offset; + cjbool noalloc; } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ @@ -261,6 +262,10 @@ static char* ensure(printbuffer *p, int needed) return p->buffer + p->offset; } + if (p->noalloc) { + return NULL; + } + newsize = pow2gt(needed); newbuffer = (char*)cJSON_malloc(newsize); if (!newbuffer) @@ -882,17 +887,19 @@ char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt) } p.length = prebuffer; p.offset = 0; + p.noalloc = false; return print_value(item, 0, fmt, &p); } -int cJSON_PrintMallocedBuffer(cJSON *item,char *buf,const int len, cjbool fmt) +int cJSON_PrintPreallocated(cJSON *item,char *buf, const int len, const cjbool fmt) { char *out; printbuffer p; p.buffer = buf; p.length = len; p.offset = 0; + p.noalloc = true; out = print_value(item,0,fmt,&p); return (out != buf ? -1 : 0); } @@ -1147,7 +1154,11 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * child = item->child; while (child && !fail) { - print_value(child, depth + 1, fmt, p); + ptr = print_value(child, depth + 1, fmt, p); + if (!ptr) + { + return NULL; + } p->offset = update(p); if (child->next) { diff --git a/cJSON.h b/cJSON.h index 1f1ed7b..4d015c3 100644 --- a/cJSON.h +++ b/cJSON.h @@ -84,7 +84,7 @@ extern char *cJSON_PrintUnformatted(const cJSON *item); /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ extern char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, int fmt); /* Render a cJSON entity to text using a buffer already allocated in memory with length buf_len */ -extern int cJSON_PrintMallocedBuffer(cJSON *item, char *buf, const int len, int fmt); +extern int cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const int fmt); /* Delete a cJSON entity and all subentities. */ extern void cJSON_Delete(cJSON *c); diff --git a/test.c b/test.c index 7706d97..1952858 100644 --- a/test.c +++ b/test.c @@ -22,6 +22,7 @@ #include #include +#include #include "cJSON.h" /* Parse text to JSON, then render back to text, and print! */ @@ -219,16 +220,60 @@ void create_objects(void) /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ out = cJSON_Print(root); - cJSON_Delete(root); printf("%s\n", out); + + printf("Test cJSON_PrintPreallocated:\n"); + /* create buffer */ + size_t len = strlen(out) + 1; + char *buf = malloc(len); + + /* create buffer to fail */ + size_t len_fail = strlen(out); + char *buf_fail = malloc(len_fail); + free(out); + /* Print to buffer */ + if (cJSON_PrintPreallocated(root, buf, len, 1) != 0) { + printf("cJSON_PrintPreallocated failed (but it should not have!)\n"); + free(buf_fail); + free(buf); + exit(EXIT_FAILURE); + } else { + printf("cJSON_PrintPreallocated:\n%s\n", buf); + } + + /* unformatted output */ + if (cJSON_PrintPreallocated(root, buf, len, 0) != 0) { + printf("cJSON_PrintPreallocated failed (but it should not have!)\n"); + free(buf_fail); + free(buf); + exit(EXIT_FAILURE); + } else { + printf("cJSON_PrintPreallocated (unformatted):\n%s\n", buf); + } + + free(buf); + + /* force it to fail */ + if (cJSON_PrintPreallocated(root, buf_fail, len_fail, 1) != 0) { + printf("cJSON_PrintPreallocated failed (as expected)\n"); + } else { + printf("cJSON_PrintPreallocated worked (but it should have failed!)\n"); + printf("cJSON_PrintPreallocated:\n%s\n", buf_fail); + } + + free(buf_fail); + cJSON_Delete(root); + root = cJSON_CreateObject(); cJSON_AddNumberToObject(root, "number", 1.0 / zero); out = cJSON_Print(root); - cJSON_Delete(root); printf("%s\n", out); + cJSON_Delete(root); + free(out); + } int main(void)