From 5cca4e2c571793317b4094bc3a4066b61db99df1 Mon Sep 17 00:00:00 2001 From: Dave Gamble Date: Tue, 10 Nov 2009 22:57:37 +0000 Subject: [PATCH] simplify the rendering code so there's no 'realloc' going on. That seemed horribly inefficient to me. Now we use multiple passes and can test for failure more carefully. git-svn-id: http://svn.code.sf.net/p/cjson/code@12 e3330c51-1366-4df0-8b21-3ccf24e3d50e --- cJSON.c | 115 ++++++++++++++++++++++++++++++++++++++++---------------- cJSON.h | 1 - 2 files changed, 83 insertions(+), 33 deletions(-) diff --git a/cJSON.c b/cJSON.c index b200467..552cf46 100644 --- a/cJSON.c +++ b/cJSON.c @@ -36,7 +36,6 @@ #endif static void *(*cJSON_malloc)(size_t sz) = malloc; -static void *(*cJSON_realloc)(void *ptr, size_t sz) = realloc; static void (*cJSON_free)(void *ptr) = free; static char* cJSON_strdup(const char* str) @@ -54,13 +53,11 @@ void cJSON_InitHooks(cJSON_Hooks* hooks) { if (!hooks) { /* Reset hooks */ cJSON_malloc = malloc; - cJSON_realloc = realloc; cJSON_free = free; return; } cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_realloc= (hooks->realloc_fn)?hooks->realloc_fn:realloc; cJSON_free = (hooks->free_fn)?hooks->free_fn:free; } @@ -300,23 +297,50 @@ static const char *parse_array(cJSON *item,const char *value) // Render an array to text static char *print_array(cJSON *item,int depth) { - char *out,*ptr,*ret;int len=5; + char **entries; + char *out=0,*ptr,*ret;int len=5; cJSON *child=item->child; + int numentries=0,i=0,fail=0; - out=(char*)cJSON_malloc(len);*out='['; - ptr=out+1;*ptr=0; - while (child) + // How many entries in the array? + while (child) numentries++,child=child->next; + // Allocate an array to hold the values for each + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + // Retrieve all the results: + child=item->child; + while (child && !fail) { ret=print_value(child,depth+1); - if (!ret) {cJSON_free(out);return 0;} // Check for failure! - len+=strlen(ret)+3; - out=(char*)cJSON_realloc(out,len); - ptr=out+strlen(out); - ptr+=sprintf(ptr,"%s",ret); - if (child->next) {*ptr++=',';*ptr++=' ';*ptr=0;} + entries[i++]=ret; + if (ret) len+=strlen(ret)+3; else fail=1; child=child->next; - cJSON_free(ret); } + + // If we didn't fail, try to malloc the output string + if (!fail) out=cJSON_malloc(len); + // If that fails, we fail. + if (!out) fail=1; + + // Handle failure. + if (fail) + { + for (i=0;ichild; - - depth++;len+=depth;out=(char*)cJSON_malloc(len);*out='{'; - ptr=out+1;*ptr++='\n';*ptr=0; + int numentries=0,fail=0; + // Count the number of entries. + while (child) numentries++,child=child->next; + // 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++;len+=depth; while (child) { - str=print_string_ptr(child->string); - if (!str) {cJSON_free(out);return 0;} - ret=print_value(child,depth); - if (!ret) {cJSON_free(str);cJSON_free(out);return 0;} // Check for failure! - len+=strlen(ret)+strlen(str)+4+depth; - out=(char*)cJSON_realloc(out,len); - ptr=out+strlen(out); - for (i=0;inext) *ptr++=','; - *ptr++='\n';*ptr=0; + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth); + if (str && ret) len+=strlen(ret)+strlen(str)+4+depth; else fail=1; child=child->next; - cJSON_free(str);cJSON_free(ret); } + + // 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