Skip to content

Commit

Permalink
Merge branch 'print_preallocated'
Browse files Browse the repository at this point in the history
  • Loading branch information
FSMaxB committed Nov 28, 2016
2 parents 59cf411 + 6622c54 commit bf17703
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 32 deletions.
13 changes: 8 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ UTILS_LIBNAME = libcjson_utils
CJSON_TEST = cJSON_test
UTILS_TEST = cJSON_test_utils

CJSON_TEST_SRC = cJSON.c test.c
UTILS_TEST_SRC = cJSON.c cJSON_Utils.c test_utils.c

LDLIBS = -lm

LIBVERSION = 1.0.2
Expand All @@ -27,7 +30,7 @@ uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
#library file extensions
SHARED = so
STATIC = a

## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
ifeq (Darwin, $(uname))
SHARED = dylib
Expand Down Expand Up @@ -66,11 +69,11 @@ test: tests

#tests
#cJSON
$(CJSON_TEST): cJSON.c cJSON.h test.c
$(CC) $(R_CFLAGS) $^ -o $@ $(LDLIBS) -I.
$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC) -o $@ $(LDLIBS) -I.
#cJSON_Utils
$(UTILS_TEST): cJSON.c cJSON.h test.c
$(CC) $(R_CFLAGS) $^ -o $@ $(LDLIBS) -I.
$(UTILS_TEST): $(UTILS_TEST_SRC) cJSON.h cJSON_Utils.h
$(CC) $(R_CFLAGS) $(UTILS_TEST_SRC) -o $@ $(LDLIBS) -I.

#static libraries
#cJSON
Expand Down
30 changes: 27 additions & 3 deletions cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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)
Expand Down Expand Up @@ -883,10 +888,20 @@ 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_PrintPreallocated(cJSON *item,char *buf, const int len, const cjbool fmt)
{
printbuffer p;
p.buffer = buf;
p.length = len;
p.offset = 0;
p.noalloc = true;
return print_value(item,0,fmt,&p) != NULL;
}

/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item, const char *value, const char **ep)
Expand Down Expand Up @@ -1138,7 +1153,10 @@ 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);
if (!print_value(child, depth + 1, fmt, p))
{
return NULL;
}
p->offset = update(p);
if (child->next)
{
Expand Down Expand Up @@ -1435,7 +1453,10 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer
}

/* print key */
print_string_ptr(child->string, p);
if (!print_string_ptr(child->string, p))
{
return NULL;
}
p->offset = update(p);

len = fmt ? 2 : 1;
Expand All @@ -1452,7 +1473,10 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer
p->offset+=len;

/* print value */
print_value(child, depth, fmt, p);
if (!print_value(child, depth, fmt, p))
{
return NULL;
};
p->offset = update(p);

/* print comma if not last */
Expand Down
2 changes: 2 additions & 0 deletions cJSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ extern char *cJSON_Print(const cJSON *item);
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_PrintPreallocated(cJSON *item, char *buf, const int len, const int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);

Expand Down
107 changes: 83 additions & 24 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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! */
Expand Down Expand Up @@ -83,6 +84,63 @@ struct record
const char *country;
};


/* Create a bunch of objects as demonstration. */
int print_preallocated(cJSON *root)
{
/* declarations */
char *out = NULL;
char *buf = NULL;
char *buf_fail = NULL;
int len = 0;
int len_fail = 0;

/* formatted print */
out = cJSON_Print(root);

/* create buffer to succeed */
/* the extra 64 bytes are in case a floating point value is printed */
len = strlen(out) + 64;
buf = malloc(len);

/* create buffer to fail */
len_fail = strlen(out);
buf_fail = malloc(len_fail);

/* Print to buffer */
if (cJSON_PrintPreallocated(root, buf, len, 1) != 0) {
printf("cJSON_PrintPreallocated failed!\n");
if (strcmp(out, buf) != 0) {
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf);
}
free(out);
free(buf_fail);
free(buf);
return -1;
}

/* success */
printf("%s\n", buf);

/* force it to fail */
if (cJSON_PrintPreallocated(root, buf_fail, len_fail, 1) == 0) {
printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);
free(out);
free(buf_fail);
free(buf);
return -1;
}

free(out);
free(buf_fail);
free(buf);
return 0;
}

/* Create a bunch of objects as demonstration. */
static void create_objects(void)
{
Expand All @@ -92,7 +150,6 @@ static void create_objects(void)
cJSON *img = NULL;
cJSON *thm = NULL;
cJSON *fld = NULL;
char *out = NULL;
int i = 0;

/* Our "days of the week" array: */
Expand Down Expand Up @@ -154,21 +211,20 @@ static void create_objects(void)
cJSON_AddNumberToObject(fmt, "frame rate", 24);

/* Print to text */
out = cJSON_Print(root);
/* Delete the cJSON */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* print it */
printf("%s\n",out);
/* release the string */
free(out);

/* Our "days of the week" array: */
root = cJSON_CreateStringArray(strings, 7);

out = cJSON_Print(root);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
printf("%s\n", out);
free(out);

/* Our matrix: */
root = cJSON_CreateArray();
Expand All @@ -179,11 +235,11 @@ static void create_objects(void)

/* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */

out = cJSON_Print(root);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
printf("%s\n", out);
free(out);


/* Our "gallery" item: */
root = cJSON_CreateObject();
Expand All @@ -197,13 +253,13 @@ static void create_objects(void)
cJSON_AddStringToObject(thm, "Width", "100");
cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4));

out = cJSON_Print(root);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
printf("%s\n", out);
free(out);

/* Our array of "records": */

root = cJSON_CreateArray();
for (i = 0; i < 2; i++)
{
Expand All @@ -220,17 +276,20 @@ static void create_objects(void)

/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */

out = cJSON_Print(root);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
printf("%s\n", out);
free(out);

root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "number", 1.0 / zero);
out = cJSON_Print(root);

if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
printf("%s\n", out);
free(out);
}

int main(void)
Expand Down

0 comments on commit bf17703

Please sign in to comment.