Quellcode durchsuchen

Merge branch 'print_preallocated'

Max Bruckner vor 8 Jahren
Ursprung
Commit
bf17703012
4 geänderte Dateien mit 120 neuen und 32 gelöschten Zeilen
  1. 8 5
      Makefile
  2. 27 3
      cJSON.c
  3. 2 0
      cJSON.h
  4. 83 24
      test.c

+ 8 - 5
Makefile

@@ -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
@@ -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
@@ -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

+ 27 - 3
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)
@@ -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)
@@ -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)
             {
@@ -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;
@@ -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 */

+ 2 - 0
cJSON.h

@@ -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);
 

+ 83 - 24
test.c

@@ -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! */
@@ -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)
 {
@@ -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: */
@@ -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();
@@ -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();
@@ -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++)
     {
@@ -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)