-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added a function to print to pre-allocated buffer #72
Changes from 4 commits
2387d9d
1193d24
df093c3
42496b2
4150c30
6ce0915
6e1b4ba
652bb77
e559516
e3e7726
32f3316
7083240
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -244,8 +244,10 @@ typedef struct | |
char *buffer; | ||
int length; | ||
int offset; | ||
int noalloc; | ||
} printbuffer; | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't add random whitespace. |
||
/* realloc printbuffer if necessary to have at least "needed" bytes more */ | ||
static char* ensure(printbuffer *p, int needed) | ||
{ | ||
|
@@ -261,12 +263,17 @@ 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) | ||
{ | ||
cJSON_free(p->buffer); | ||
p->length = 0; | ||
p->noalloc = 0; | ||
p->buffer = NULL; | ||
|
||
return NULL; | ||
|
@@ -882,10 +889,22 @@ char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt) | |
} | ||
p.length = prebuffer; | ||
p.offset = 0; | ||
p.noalloc = 0; | ||
|
||
return print_value(item, 0, fmt, &p); | ||
} | ||
|
||
int cJSON_PrintPreallocated(cJSON *item,char *buf, const size_t len, const cjbool fmt) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. About the So please change to |
||
{ | ||
char *out; | ||
printbuffer p; | ||
p.buffer = buf; | ||
p.length = len; | ||
p.offset = 0; | ||
p.noalloc = 1; | ||
out = print_value(item,0,fmt,&p); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By doing this you risk crashes, because |
||
return (out != buf ? -1 : 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this function returns a char pointer (effectively providing an alias to the input There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm. Good point. Considering this, your way of returning true or false might actually be better. An API should be hard to misuse in a dangerous way (like having a double free because of the alias). This will then not allow the use of If you do it the way you suggested, you can just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be more concise. Made the change. |
||
} | ||
|
||
/* Parser core - when encountering text, process appropriately. */ | ||
static const char *parse_value(cJSON *item, const char *value, const char **ep) | ||
|
@@ -1137,7 +1156,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; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change this to: if (!print_value(child, depth + 1, fmt, p))
{
return NULL;
} Thank you for finding this problem btw. after that I was taking a closer look to the rest of the library and there are quite some cases where out of memory errors are not handled properly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will also fix these other cases in the next release. |
||
p->offset = update(p); | ||
if (child->next) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ | |
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not allowed to mix code and declarations in C89. I have a bug in the Makefile and CMakelists.txt so that the compiler option is not enforced, sorry for that. I suggest you create a new function just for testing preallocated printing and call it from main (you can pass one of the texts to it). |
||
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) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use
cjbool
and usetrue
andfalse
when assigning to it.