diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1101bbc..0000000 --- a/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.svn -test -*.o -*.a -*.so -*.swp -*.patch -tags -*.dylib -build/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index ca8cedf..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,110 +0,0 @@ -set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 2.8) - -include(GNUInstallDirs) - -project(cJSON C) - -set(PROJECT_VERSION_MAJOR 1) -set(PROJECT_VERSION_MINOR 0) -set(PROJECT_VERSION_PATCH 1) -set(CJSON_VERSION_SO 1) -set(CJSON_UTILS_VERSION_SO 1) -set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") - -option(ENABLE_CUSTOM_COMPILER_FLAGS ON) -if (ENABLE_CUSTOM_COMPILER_FLAGS) - if(("${CMAKE_C_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89 -pedantic -Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings") - endif() -endif() - -#variables for pkg-config -set(prefix "${CMAKE_INSTALL_PREFIX}") -set(libdir "${CMAKE_INSTALL_LIBDIR}") -set(version "${PROJECT_VERSION}") -set(includedir "${CMAKE_INSTALL_INCLUDEDIR}") - -option(BUILD_SHARED_LIBS "Build shared libraries" ON) -option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON) - -#cJSON -set(CJSON_LIB cjson) - -file(GLOB HEADERS cJSON.h) -set(SOURCES cJSON.c) - -add_library("${CJSON_LIB}" "${HEADERS}" "${SOURCES}") -if (NOT WIN32) - target_link_libraries("${CJSON_LIB}" m) -endif() - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libcjson.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY) - -install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson") -install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") -install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_LIB}") -if(ENABLE_TARGET_EXPORT) - # export library information for CMake projects - install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON") -endif() - -set_target_properties("${CJSON_LIB}" - PROPERTIES - SOVERSION "${CJSON_VERSION_SO}" - VERSION "${PROJECT_VERSION}") - -#cJSON_Utils -option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF) -if(ENABLE_CJSON_UTILS) - set(CJSON_UTILS_LIB cjson_utils) - - file(GLOB HEADERS_UTILS cJSON_Utils.h) - set(SOURCES_UTILS cJSON_Utils.c) - - add_library("${CJSON_UTILS_LIB}" "${HEADERS_UTILS}" "${SOURCES_UTILS}") - target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}") - - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libcjson_utils.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY) - - install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}") - install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - if(ENABLE_TARGET_EXPORT) - # export library information for CMake projects - install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON") - endif() - - set_target_properties("${CJSON_UTILS_LIB}" - PROPERTIES - SOVERSION "${CJSON_UTILS_VERSION_SO}" - VERSION "${PROJECT_VERSION}") -endif() - -# create the other package config files -configure_file( - cJSONConfig.cmake.in - ${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY) -configure_file( - cJSONConfigVersion.cmake.in - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY) - -# Install package config files -install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON") - -option(ENABLE_CJSON_TEST "Enable building cJSON test" ON) -if(ENABLE_CJSON_TEST) - set(TEST_CJSON cJSON_test) - add_executable("${TEST_CJSON}" test.c) - target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}") - - if(ENABLE_CJSON_UTILS) - set(TEST_CJSON_UTILS cJSON_test_utils) - add_executable("${TEST_CJSON_UTILS}" test_utils.c) - target_link_libraries("${TEST_CJSON_UTILS}" "${CJSON_UTILS_LIB}") - endif() -endif() diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md deleted file mode 100644 index 6f2a93c..0000000 --- a/CONTRIBUTORS.md +++ /dev/null @@ -1,27 +0,0 @@ -Contributors -============ - -* [Ajay Bhargav](https://github.com/ajaybhargav) -* [Anton Sergeev](https://github.com/anton-sergeev) -* [Christian Schulze](https://github.com/ChristianSch) -* [Dave Gamble](https://github.com/DaveGamble) -* [dieyushi](https://github.com/dieyushi) -* [Dongwen Huang (黄东文)](https://github.com/DongwenHuang) -* Eswar Yaganti -* [Evan Todd](https://github.com/etodd) -* [Fabrice Fontaine](https://github.com/ffontaine) -* Ian Mobley -* Irwan Djadjadi -* [IvanVoid](https://github.com/npi3pak) -* [Jonathan Fether](https://github.com/jfether) -* [Kevin Branigan](https://github.com/kbranigan) -* [Linus Wallgren](https://github.com/ecksun) -* [Max Bruckner](https://github.com/FSMaxB) -* Mike Pontillo -* Paulo Antonio Alvarez -* [Rafael Leal Dias](https://github.com/rafaeldias) -* [Rod Vagg](https://github.com/rvagg) -* [Roland Meertens](https://github.com/rmeertens) -* [Weston Schmidt](https://github.com/schmidtw) - -And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0) diff --git a/LICENSE b/LICENSE deleted file mode 100644 index fa0a438..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - diff --git a/Makefile b/Makefile deleted file mode 100644 index 5b6b68e..0000000 --- a/Makefile +++ /dev/null @@ -1,145 +0,0 @@ -CJSON_OBJ = cJSON.o -UTILS_OBJ = cJSON_Utils.o -CJSON_LIBNAME = libcjson -UTILS_LIBNAME = libcjson_utils -CJSON_TEST = cJSON_test -UTILS_TEST = cJSON_test_utils - -LDLIBS = -lm - -LIBVERSION = 1.0.1 -CJSON_SOVERSION = 1 -UTILS_SOVERSION = 1 - -PREFIX ?= /usr/local -INCLUDE_PATH ?= include/cjson -LIBRARY_PATH ?= lib - -INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) - -INSTALL ?= cp -a - -R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings $(CFLAGS) - -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 -endif - -#cJSON library names -CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED) -CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION) -CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION) -CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC) - -#cJSON_Utils library names -UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED) -UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION) -UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION) -UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC) - -SHARED_CMD = $(CC) -shared -o - -.PHONY: all shared static tests clean install - -all: shared static tests - -shared: $(CJSON_SHARED) $(UTILS_SHARED) - -static: $(CJSON_STATIC) $(UTILS_STATIC) - -tests: $(CJSON_TEST) $(UTILS_TEST) - -test: tests - ./$(CJSON_TEST) - ./$(UTILS_TEST) - -.c.o: - $(CC) -ansi -pedantic -c $(R_CFLAGS) $< - -#tests -#cJSON -$(CJSON_TEST): cJSON.c cJSON.h test.c - $(CC) $^ -o $@ $(LDLIBS) -I. -#cJSON_Utils -$(UTILS_TEST): cJSON.c cJSON.h test.c - $(CC) $^ -o $@ $(LDLIBS) -I. - -#static libraries -#cJSON -$(CJSON_STATIC): $(CJSON_OBJ) - $(AR) rcs $@ $< -#cJSON_Utils -$(UTILS_STATIC): $(UTILS_OBJ) - $(AR) rcs $@ $< - -#shared libraries .so.1.0.0 -#cJSON -$(CJSON_SHARED_VERSION): $(CJSON_OBJ) - $(CC) -shared -o $@ $< $(LDFLAGS) -#cJSON_Utils -$(UTILS_SHARED_VERSION): $(UTILS_OBJ) - $(CC) -shared -o $@ $< $(LDFLAGS) - -#objects -#cJSON -$(CJSON_OBJ): cJSON.c cJSON.h -#cJSON_Utils -$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h - - -#links .so -> .so.1 -> .so.1.0.0 -#cJSON -$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION) - ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) -$(CJSON_SHARED): $(CJSON_SHARED_SO) - ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED) -#cJSON_Utils -$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION) - ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) -$(UTILS_SHARED): $(UTILS_SHARED_SO) - ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED) - -#install -#cJSON -install-cjson: - mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH) - $(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH) -#cJSON_Utils -install-utils: install-cjson - $(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH) - -install: install-cjson install-utils - -#uninstall -#cJSON -uninstall-cjson: uninstall-utils - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED) - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION) - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO) - rmdir $(INSTALL_LIBRARY_PATH) - $(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h - rmdir $(INSTALL_INCLUDE_PATH) -#cJSON_Utils -uninstall-utils: - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED) - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION) - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO) - $(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h - -uninstall: uninstall-utils uninstall-cjson - -clean: - $(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files - $(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON - $(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils - $(RM) $(CJSON_TEST) $(UTILS_TEST) #delete tests diff --git a/cJSON.c b/cJSON.c deleted file mode 100644 index 3578b57..0000000 --- a/cJSON.c +++ /dev/null @@ -1,2233 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -#include -#include -#include -#include -#include -#include -#include -#include "cJSON.h" - -/* Determine the number of bits that an integer has using the preprocessor */ -#if INT_MAX == 32767 - /* 16 bits */ - #define INTEGER_SIZE 0x0010 -#elif INT_MAX == 2147483647 - /* 32 bits */ - #define INTEGER_SIZE 0x0100 -#elif INT_MAX == 9223372036854775807 - /* 64 bits */ - #define INTEGER_SIZE 0x1000 -#else - #error "Failed to determine the size of an integer" -#endif - -/* define our own boolean type */ -typedef int bool; -#define true ((bool)1) -#define false ((bool)0) - -static const char *global_ep = NULL; - -const char *cJSON_GetErrorPtr(void) -{ - return global_ep; -} - -/* case insensitive strcmp */ -static int cJSON_strcasecmp(const char *s1, const char *s2) -{ - if (!s1) - { - return (s1 == s2) ? 0 : 1; /* both NULL? */ - } - if (!s2) - { - return 1; - } - for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) - { - if (*s1 == '\0') - { - return 0; - } - } - - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void (*cJSON_free)(void *ptr) = free; - -static char* cJSON_strdup(const char* str) -{ - size_t len = 0; - char *copy = NULL; - - len = strlen(str) + 1; - if (!(copy = (char*)cJSON_malloc(len))) - { - return NULL; - } - memcpy(copy, str, len); - - return copy; -} - -void cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) - { - /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc; - cJSON_free = (hooks->free_fn) ? hooks->free_fn : free; -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(void) -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -void cJSON_Delete(cJSON *c) -{ - cJSON *next = NULL; - while (c) - { - next = c->next; - if (!(c->type & cJSON_IsReference) && c->child) - { - cJSON_Delete(c->child); - } - if (!(c->type & cJSON_IsReference) && c->valuestring) - { - cJSON_free(c->valuestring); - } - if (!(c->type & cJSON_StringIsConst) && c->string) - { - cJSON_free(c->string); - } - cJSON_free(c); - c = next; - } -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item, const char *num) -{ - double n = 0; - double sign = 1; - double scale = 0; - int subscale = 0; - int signsubscale = 1; - - /* Has sign? */ - if (*num == '-') - { - sign = -1; - num++; - } - /* is zero */ - if (*num == '0') - { - num++; - } - /* Number? */ - if ((*num >= '1') && (*num <= '9')) - { - do - { - n = (n * 10.0) + (*num++ - '0'); - } - while ((*num >= '0') && (*num<='9')); - } - /* Fractional part? */ - if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9')) - { - num++; - do - { - n = (n *10.0) + (*num++ - '0'); - scale--; - } while ((*num >= '0') && (*num <= '9')); - } - /* Exponent? */ - if ((*num == 'e') || (*num == 'E')) - { - num++; - /* With sign? */ - if (*num == '+') - { - num++; - } - else if (*num == '-') - { - signsubscale = -1; - num++; - } - /* Number? */ - while ((*num>='0') && (*num<='9')) - { - subscale = (subscale * 10) + (*num++ - '0'); - } - } - - /* number = +/- number.fraction * 10^+/- exponent */ - n = sign * n * pow(10.0, (scale + subscale * signsubscale)); - - item->valuedouble = n; - item->valueint = (int)n; - item->type = cJSON_Number; - - return num; -} - -/* calculate the next largest power of 2 */ -static int pow2gt (int x) -{ - --x; - - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; -#if INTEGER_SIZE & 0x1110 /* at least 16 bit */ - x |= x >> 8; -#endif -#if INTEGER_SIZE & 0x1100 /* at least 32 bit */ - x |= x >> 16; -#endif -#if INT_SIZE & 0x1000 /* 64 bit */ - x |= x >> 32; -#endif - - return x + 1; -} - -typedef struct -{ - char *buffer; - int length; - int offset; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static char* ensure(printbuffer *p, int needed) -{ - char *newbuffer = NULL; - int newsize = 0; - if (!p || !p->buffer) - { - return NULL; - } - needed += p->offset; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - newsize = pow2gt(needed); - newbuffer = (char*)cJSON_malloc(newsize); - if (!newbuffer) - { - cJSON_free(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) - { - memcpy(newbuffer, p->buffer, p->length); - } - cJSON_free(p->buffer); - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer */ -static int update(const printbuffer *p) -{ - char *str = NULL; - if (!p || !p->buffer) - { - return 0; - } - str = p->buffer + p->offset; - - return p->offset + strlen(str); -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(const cJSON *item, printbuffer *p) -{ - char *str = NULL; - double d = item->valuedouble; - /* special case for 0. */ - if (d == 0) - { - if (p) - { - str = ensure(p, 2); - } - else - { - str = (char*)cJSON_malloc(2); - } - if (str) - { - strcpy(str,"0"); - } - } - /* value is an int */ - else if ((fabs(((double)item->valueint) - d) <= DBL_EPSILON) && (d <= INT_MAX) && (d >= INT_MIN)) - { - if (p) - { - str = ensure(p, 21); - } - else - { - /* 2^64+1 can be represented in 21 chars. */ - str = (char*)cJSON_malloc(21); - } - if (str) - { - sprintf(str, "%d", item->valueint); - } - } - /* value is a floating point number */ - else - { - if (p) - { - /* This is a nice tradeoff. */ - str = ensure(p, 64); - } - else - { - /* This is a nice tradeoff. */ - str=(char*)cJSON_malloc(64); - } - if (str) - { - /* This checks for NaN and Infinity */ - if ((d * 0) != 0) - { - sprintf(str, "null"); - } - else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60)) - { - sprintf(str, "%.0f", d); - } - else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9)) - { - sprintf(str, "%e", d); - } - else - { - sprintf(str, "%f", d); - } - } - } - return str; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const char *str) -{ - unsigned h = 0; - /* first digit */ - if ((*str >= '0') && (*str <= '9')) - { - h += (*str) - '0'; - } - else if ((*str >= 'A') && (*str <= 'F')) - { - h += 10 + (*str) - 'A'; - } - else if ((*str >= 'a') && (*str <= 'f')) - { - h += 10 + (*str) - 'a'; - } - else /* invalid */ - { - return 0; - } - - - /* second digit */ - h = h << 4; - str++; - if ((*str >= '0') && (*str <= '9')) - { - h += (*str) - '0'; - } - else if ((*str >= 'A') && (*str <= 'F')) - { - h += 10 + (*str) - 'A'; - } - else if ((*str >= 'a') && (*str <= 'f')) - { - h += 10 + (*str) - 'a'; - } - else /* invalid */ - { - return 0; - } - - /* third digit */ - h = h << 4; - str++; - if ((*str >= '0') && (*str <= '9')) - { - h += (*str) - '0'; - } - else if ((*str >= 'A') && (*str <= 'F')) - { - h += 10 + (*str) - 'A'; - } - else if ((*str >= 'a') && (*str <= 'f')) - { - h += 10 + (*str) - 'a'; - } - else /* invalid */ - { - return 0; - } - - /* fourth digit */ - h = h << 4; - str++; - if ((*str >= '0') && (*str <= '9')) - { - h += (*str) - '0'; - } - else if ((*str >= 'A') && (*str <= 'F')) - { - h += 10 + (*str) - 'A'; - } - else if ((*str >= 'a') && (*str <= 'f')) - { - h += 10 + (*str) - 'a'; - } - else /* invalid */ - { - return 0; - } - - return h; -} - -/* first bytes of UTF8 encoding for a given length in bytes */ -static const unsigned char firstByteMark[7] = -{ - 0x00, /* should never happen */ - 0x00, /* 0xxxxxxx */ - 0xC0, /* 110xxxxx */ - 0xE0, /* 1110xxxx */ - 0xF0, /* 11110xxx */ - 0xF8, - 0xFC -}; - -/* Parse the input text into an unescaped cstring, and populate item. */ -static const char *parse_string(cJSON *item, const char *str, const char **ep) -{ - const char *ptr = str + 1; - const char *end_ptr =str + 1; - char *ptr2 = NULL; - char *out = NULL; - int len = 0; - unsigned uc = 0; - unsigned uc2 = 0; - - /* not a string! */ - if (*str != '\"') - { - *ep = str; - return NULL; - } - - while ((*end_ptr != '\"') && *end_ptr && ++len) - { - if (*end_ptr++ == '\\') - { - if (*end_ptr == '\0') - { - /* prevent buffer overflow when last input character is a backslash */ - return NULL; - } - /* Skip escaped quotes. */ - end_ptr++; - } - } - - /* This is at most how long we need for the string, roughly. */ - out = (char*)cJSON_malloc(len + 1); - if (!out) - { - return NULL; - } - item->valuestring = out; /* assign here so out will be deleted during cJSON_Delete() later */ - item->type = cJSON_String; - - ptr = str + 1; - ptr2 = out; - /* loop through the string literal */ - while (ptr < end_ptr) - { - if (*ptr != '\\') - { - *ptr2++ = *ptr++; - } - /* escape sequence */ - else - { - ptr++; - switch (*ptr) - { - case 'b': - *ptr2++ = '\b'; - break; - case 'f': - *ptr2++ = '\f'; - break; - case 'n': - *ptr2++ = '\n'; - break; - case 'r': - *ptr2++ = '\r'; - break; - case 't': - *ptr2++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *ptr2++ = *ptr; - break; - case 'u': - /* transcode utf16 to utf8. See RFC2781 and RFC3629. */ - uc = parse_hex4(ptr + 1); /* get the unicode char. */ - ptr += 4; - if (ptr >= end_ptr) - { - /* invalid */ - *ep = str; - return NULL; - } - /* check for invalid. */ - if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0)) - { - *ep = str; - return NULL; - } - - /* UTF16 surrogate pairs. */ - if ((uc >= 0xD800) && (uc<=0xDBFF)) - { - if ((ptr + 6) > end_ptr) - { - /* invalid */ - *ep = str; - return NULL; - } - if ((ptr[1] != '\\') || (ptr[2] != 'u')) - { - /* missing second-half of surrogate. */ - *ep = str; - return NULL; - } - uc2 = parse_hex4(ptr + 3); - ptr += 6; /* \uXXXX */ - if ((uc2 < 0xDC00) || (uc2 > 0xDFFF)) - { - /* invalid second-half of surrogate. */ - *ep = str; - return NULL; - } - /* calculate unicode codepoint from the surrogate pair */ - uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); - } - - /* encode as UTF8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - len = 4; - if (uc < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - len = 1; - } - else if (uc < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - len = 2; - } - else if (uc < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - len = 3; - } - ptr2 += len; - - switch (len) { - case 4: - /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); - uc >>= 6; - case 3: - /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); - uc >>= 6; - case 2: - /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); - uc >>= 6; - case 1: - /* depending on the length in bytes this determines the - * encoding ofthe first UTF8 byte */ - *--ptr2 = (uc | firstByteMark[len]); - } - ptr2 += len; - break; - default: - *ep = str; - return NULL; - } - ptr++; - } - } - *ptr2 = '\0'; - if (*ptr == '\"') - { - ptr++; - } - - return ptr; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str, printbuffer *p) -{ - const char *ptr = NULL; - char *ptr2 = NULL; - char *out = NULL; - int len = 0; - bool flag = false; - unsigned char token = '\0'; - - /* empty string */ - if (!str) - { - if (p) - { - out = ensure(p, 3); - } - else - { - out = (char*)cJSON_malloc(3); - } - if (!out) - { - return NULL; - } - strcpy(out, "\"\""); - - return out; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (ptr = str; *ptr; ptr++) - { - flag |= (((*ptr > 0) && (*ptr < 32)) /* unprintable characters */ - || (*ptr == '\"') /* double quote */ - || (*ptr == '\\')) /* backslash */ - ? 1 - : 0; - } - /* no characters have to be escaped */ - if (!flag) - { - len = ptr - str; - if (p) - { - out = ensure(p, len + 3); - } - else - { - out = (char*)cJSON_malloc(len + 3); - } - if (!out) - { - return NULL; - } - - ptr2 = out; - *ptr2++ = '\"'; - strcpy(ptr2, str); - ptr2[len] = '\"'; - ptr2[len + 1] = '\0'; - - return out; - } - - ptr = str; - /* calculate additional space that is needed for escaping */ - while ((token = *ptr) && ++len) - { - if (strchr("\"\\\b\f\n\r\t", token)) - { - len++; /* +1 for the backslash */ - } - else if (token < 32) - { - len += 5; /* +5 for \uXXXX */ - } - ptr++; - } - - if (p) - { - out = ensure(p, len + 3); - } - else - { - out = (char*)cJSON_malloc(len + 3); - } - if (!out) - { - return NULL; - } - - ptr2 = out; - ptr = str; - *ptr2++ = '\"'; - /* copy the string */ - while (*ptr) - { - if (((unsigned char)*ptr > 31) && (*ptr != '\"') && (*ptr != '\\')) - { - /* normal character, copy */ - *ptr2++ = *ptr++; - } - else - { - /* character needs to be escaped */ - *ptr2++ = '\\'; - switch (token = *ptr++) - { - case '\\': - *ptr2++ = '\\'; - break; - case '\"': - *ptr2++ = '\"'; - break; - case '\b': - *ptr2++ = 'b'; - break; - case '\f': - *ptr2++ = 'f'; - break; - case '\n': - *ptr2++ = 'n'; - break; - case '\r': - *ptr2++ = 'r'; - break; - case '\t': - *ptr2++ = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf(ptr2, "u%04x", token); - ptr2 += 5; - break; - } - } - } - *ptr2++ = '\"'; - *ptr2++ = '\0'; - - return out; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static char *print_string(const cJSON *item, printbuffer *p) -{ - return print_string_ptr(item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item, const char *value, const char **ep); -static char *print_value(const cJSON *item, int depth, bool fmt, printbuffer *p); -static const char *parse_array(cJSON *item, const char *value, const char **ep); -static char *print_array(const cJSON *item, int depth, bool fmt, printbuffer *p); -static const char *parse_object(cJSON *item, const char *value, const char **ep); -static char *print_object(const cJSON *item, int depth, bool fmt, printbuffer *p); - -/* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) -{ - while (in && *in && ((unsigned char)*in<=32)) - { - in++; - } - - return in; -} - -/* Parse an object - create a new root, and populate. */ -cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, bool require_null_terminated) -{ - const char *end = NULL; - /* use global error pointer if no specific one was given */ - const char **ep = return_parse_end ? return_parse_end : &global_ep; - cJSON *c = cJSON_New_Item(); - *ep = NULL; - if (!c) /* memory fail */ - { - return NULL; - } - - end = parse_value(c, skip(value), ep); - if (!end) - { - /* parse failure. ep is set. */ - cJSON_Delete(c); - return NULL; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - end = skip(end); - if (*end) - { - cJSON_Delete(c); - *ep = end; - return NULL; - } - } - if (return_parse_end) - { - *return_parse_end = end; - } - - return c; -} - -/* Default options for cJSON_Parse */ -cJSON *cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -/* Render a cJSON item/entity/structure to text. */ -char *cJSON_Print(const cJSON *item) -{ - return print_value(item, 0, 1, 0); -} - -char *cJSON_PrintUnformatted(const cJSON *item) -{ - return print_value(item, 0, 0, 0); -} - -char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, bool fmt) -{ - printbuffer p; - p.buffer = (char*)cJSON_malloc(prebuffer); - if (!p.buffer) - { - return NULL; - } - p.length = prebuffer; - p.offset = 0; - - return print_value(item, 0, fmt, &p); -} - - -/* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item, const char *value, const char **ep) -{ - if (!value) - { - /* Fail on null. */ - return NULL; - } - - /* parse the different types of values */ - if (!strncmp(value, "null", 4)) - { - item->type = cJSON_NULL; - return value + 4; - } - if (!strncmp(value, "false", 5)) - { - item->type = cJSON_False; - return value + 5; - } - if (!strncmp(value, "true", 4)) - { - item->type = cJSON_True; - item->valueint = 1; - return value + 4; - } - if (*value == '\"') - { - return parse_string(item, value, ep); - } - if ((*value == '-') || ((*value >= '0') && (*value <= '9'))) - { - return parse_number(item, value); - } - if (*value == '[') - { - return parse_array(item, value, ep); - } - if (*value == '{') - { - return parse_object(item, value, ep); - } - - /* failure. */ - *ep = value; - return NULL; -} - -/* Render a value to text. */ -static char *print_value(const cJSON *item, int depth, bool fmt, printbuffer *p) -{ - char *out = NULL; - - if (!item) - { - return NULL; - } - if (p) - { - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - out = ensure(p, 5); - if (out) - { - strcpy(out, "null"); - } - break; - case cJSON_False: - out = ensure(p, 6); - if (out) - { - strcpy(out, "false"); - } - break; - case cJSON_True: - out = ensure(p, 5); - if (out) - { - strcpy(out, "true"); - } - break; - case cJSON_Number: - out = print_number(item, p); - break; - case cJSON_String: - out = print_string(item, p); - break; - case cJSON_Array: - out = print_array(item, depth, fmt, p); - break; - case cJSON_Object: - out = print_object(item, depth, fmt, p); - break; - } - } - else - { - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - out = cJSON_strdup("null"); - break; - case cJSON_False: - out = cJSON_strdup("false"); - break; - case cJSON_True: - out = cJSON_strdup("true"); - break; - case cJSON_Number: - out = print_number(item, 0); - break; - case cJSON_String: - out = print_string(item, 0); - break; - case cJSON_Array: - out = print_array(item, depth, fmt, 0); - break; - case cJSON_Object: - out = print_object(item, depth, fmt, 0); - break; - } - } - - return out; -} - -/* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value,const char **ep) -{ - cJSON *child = NULL; - if (*value != '[') - { - /* not an array! */ - *ep = value; - return NULL; - } - - item->type = cJSON_Array; - value = skip(value + 1); - if (*value == ']') - { - /* empty array. */ - return value + 1; - } - - item->child = child = cJSON_New_Item(); - if (!item->child) - { - /* memory fail */ - return NULL; - } - /* skip any spacing, get the value. */ - value = skip(parse_value(child, skip(value), ep)); - if (!value) - { - return NULL; - } - - /* loop through the comma separated array elements */ - while (*value == ',') - { - cJSON *new_item = NULL; - if (!(new_item = cJSON_New_Item())) - { - /* memory fail */ - return NULL; - } - /* add new item to end of the linked list */ - child->next = new_item; - new_item->prev = child; - child = new_item; - - /* go to the next comma */ - value = skip(parse_value(child, skip(value + 1), ep)); - if (!value) - { - /* memory fail */ - return NULL; - } - } - - if (*value == ']') - { - /* end of array */ - return value + 1; - } - - /* malformed. */ - *ep = value; - - return NULL; -} - -/* Render an array to text */ -static char *print_array(const cJSON *item, int depth, bool fmt, printbuffer *p) -{ - char **entries; - char *out = NULL; - char *ptr = NULL; - char *ret = NULL; - int len = 5; - cJSON *child = item->child; - int numentries = 0; - int i = 0; - bool fail = false; - size_t tmplen = 0; - - /* How many entries in the array? */ - while (child) - { - numentries++; - child = child->next; - } - - /* Explicitly handle numentries == 0 */ - if (!numentries) - { - if (p) - { - out = ensure(p, 3); - } - else - { - out = (char*)cJSON_malloc(3); - } - if (out) - { - strcpy(out,"[]"); - } - - return out; - } - - if (p) - { - /* Compose the output array. */ - /* opening square bracket */ - i = p->offset; - ptr = ensure(p, 1); - if (!ptr) - { - return NULL; - } - *ptr = '['; - p->offset++; - - child = item->child; - while (child && !fail) - { - print_value(child, depth + 1, fmt, p); - p->offset = update(p); - if (child->next) - { - len = fmt ? 2 : 1; - ptr = ensure(p, len + 1); - if (!ptr) - { - return NULL; - } - *ptr++ = ','; - if(fmt) - { - *ptr++ = ' '; - } - *ptr = '\0'; - p->offset += len; - } - child = child->next; - } - ptr = ensure(p, 2); - if (!ptr) - { - return NULL; - } - *ptr++ = ']'; - *ptr = '\0'; - out = (p->buffer) + i; - } - else - { - /* Allocate an array to hold the pointers to all printed values */ - entries = (char**)cJSON_malloc(numentries * sizeof(char*)); - if (!entries) - { - return NULL; - } - memset(entries, '\0', numentries * sizeof(char*)); - - /* Retrieve all the results: */ - child = item->child; - while (child && !fail) - { - ret = print_value(child, depth + 1, fmt, 0); - entries[i++] = ret; - if (ret) - { - len += strlen(ret) + 2 + (fmt ? 1 : 0); - } - else - { - fail = true; - } - child = child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) - { - out = (char*)cJSON_malloc(len); - } - /* If that fails, we fail. */ - if (!out) - { - fail = true; - } - - /* Handle failure. */ - if (fail) - { - /* free all the entries in the array */ - for (i = 0; i < numentries; i++) - { - if (entries[i]) - { - cJSON_free(entries[i]); - } - } - cJSON_free(entries); - return NULL; - } - - /* Compose the output array. */ - *out='['; - ptr = out + 1; - *ptr = '\0'; - for (i = 0; i < numentries; i++) - { - tmplen = strlen(entries[i]); - memcpy(ptr, entries[i], tmplen); - ptr += tmplen; - if (i != (numentries - 1)) - { - *ptr++ = ','; - if(fmt) - { - *ptr++ = ' '; - } - *ptr = '\0'; - } - cJSON_free(entries[i]); - } - cJSON_free(entries); - *ptr++ = ']'; - *ptr++ = '\0'; - } - - return out; -} - -/* Build an object from the text. */ -static const char *parse_object(cJSON *item, const char *value, const char **ep) -{ - cJSON *child = NULL; - if (*value != '{') - { - /* not an object! */ - *ep = value; - return NULL; - } - - item->type = cJSON_Object; - value = skip(value + 1); - if (*value == '}') - { - /* empty object. */ - return value + 1; - } - - child = cJSON_New_Item(); - item->child = child; - if (!item->child) - { - return NULL; - } - /* parse first key */ - value = skip(parse_string(child, skip(value), ep)); - if (!value) - { - return NULL; - } - /* use string as key, not value */ - child->string = child->valuestring; - child->valuestring = NULL; - - if (*value != ':') - { - /* invalid object. */ - *ep = value; - return NULL; - } - /* skip any spacing, get the value. */ - value = skip(parse_value(child, skip(value + 1), ep)); - if (!value) - { - return NULL; - } - - while (*value == ',') - { - cJSON *new_item = NULL; - if (!(new_item = cJSON_New_Item())) - { - /* memory fail */ - return NULL; - } - /* add to linked list */ - child->next = new_item; - new_item->prev = child; - - child = new_item; - value = skip(parse_string(child, skip(value + 1), ep)); - if (!value) - { - return NULL; - } - - /* use string as key, not value */ - child->string = child->valuestring; - child->valuestring = NULL; - - if (*value != ':') - { - /* invalid object. */ - *ep = value; - return NULL; - } - /* skip any spacing, get the value. */ - value = skip(parse_value(child, skip(value + 1), ep)); - if (!value) - { - return NULL; - } - } - /* end of object */ - if (*value == '}') - { - return value + 1; - } - - /* malformed */ - *ep = value; - return NULL; -} - -/* Render an object to text. */ -static char *print_object(const cJSON *item, int depth, bool fmt, printbuffer *p) -{ - char **entries = NULL; - char **names = NULL; - char *out = NULL; - char *ptr = NULL; - char *ret = NULL; - char *str = NULL; - int len = 7; - int i = 0; - int j = 0; - cJSON *child = item->child; - int numentries = 0; - bool fail = false; - size_t tmplen = 0; - - /* Count the number of entries. */ - while (child) - { - numentries++; - child = child->next; - } - - /* Explicitly handle empty object case */ - if (!numentries) - { - if (p) - { - out = ensure(p, fmt ? depth + 4 : 3); - } - else - { - out = (char*)cJSON_malloc(fmt ? depth + 4 : 3); - } - if (!out) - { - return NULL; - } - ptr = out; - *ptr++ = '{'; - if (fmt) { - *ptr++ = '\n'; - for (i = 0; i < depth; i++) - { - *ptr++ = '\t'; - } - } - *ptr++ = '}'; - *ptr++ = '\0'; - - return out; - } - - if (p) - { - /* Compose the output: */ - i = p->offset; - len = fmt ? 2 : 1; /* fmt: {\n */ - ptr = ensure(p, len + 1); - if (!ptr) - { - return NULL; - } - - *ptr++ = '{'; - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - p->offset += len; - - child = item->child; - depth++; - while (child) - { - if (fmt) - { - ptr = ensure(p, depth); - if (!ptr) - { - return NULL; - } - for (j = 0; j < depth; j++) - { - *ptr++ = '\t'; - } - p->offset += depth; - } - - /* print key */ - print_string_ptr(child->string, p); - p->offset = update(p); - - len = fmt ? 2 : 1; - ptr = ensure(p, len); - if (!ptr) - { - return NULL; - } - *ptr++ = ':'; - if (fmt) - { - *ptr++ = '\t'; - } - p->offset+=len; - - /* print value */ - print_value(child, depth, fmt, p); - p->offset = update(p); - - /* print comma if not last */ - len = (fmt ? 1 : 0) + (child->next ? 1 : 0); - ptr = ensure(p, len + 1); - if (!ptr) - { - return NULL; - } - if (child->next) - { - *ptr++ = ','; - } - - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - p->offset += len; - - child = child->next; - } - - ptr = ensure(p, fmt ? (depth + 1) : 2); - if (!ptr) - { - return NULL; - } - if (fmt) - { - for (i = 0; i < (depth - 1); i++) - { - *ptr++ = '\t'; - } - } - *ptr++ = '}'; - *ptr = '\0'; - out = (p->buffer) + i; - } - else - { - /* Allocate space for the names and the objects */ - entries = (char**)cJSON_malloc(numentries * sizeof(char*)); - if (!entries) - { - return NULL; - } - names = (char**)cJSON_malloc(numentries * sizeof(char*)); - if (!names) - { - cJSON_free(entries); - return NULL; - } - memset(entries, '\0', sizeof(char*) * numentries); - memset(names, '\0', sizeof(char*) * numentries); - - /* Collect all the results into our arrays: */ - child = item->child; - depth++; - if (fmt) - { - len += depth; - } - while (child && !fail) - { - names[i] = str = print_string_ptr(child->string, 0); /* print key */ - entries[i++] = ret = print_value(child, depth, fmt, 0); - if (str && ret) - { - len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0); - } - else - { - fail = true; - } - child = child->next; - } - - /* Try to allocate the output string */ - if (!fail) - { - out = (char*)cJSON_malloc(len); - } - if (!out) - { - fail = true; - } - - /* Handle failure */ - if (fail) - { - /* free all the printed keys and values */ - for (i = 0; i < numentries; i++) - { - if (names[i]) - { - cJSON_free(names[i]); - } - if (entries[i]) - { - cJSON_free(entries[i]); - } - } - cJSON_free(names); - cJSON_free(entries); - return NULL; - } - - /* Compose the output: */ - *out = '{'; - ptr = out + 1; - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - for (i = 0; i < numentries; i++) - { - if (fmt) - { - for (j = 0; j < depth; j++) - { - *ptr++='\t'; - } - } - tmplen = strlen(names[i]); - memcpy(ptr, names[i], tmplen); - ptr += tmplen; - *ptr++ = ':'; - if (fmt) - { - *ptr++ = '\t'; - } - strcpy(ptr, entries[i]); - ptr += strlen(entries[i]); - if (i != (numentries - 1)) - { - *ptr++ = ','; - } - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - cJSON_free(names[i]); - cJSON_free(entries[i]); - } - - cJSON_free(names); - cJSON_free(entries); - if (fmt) - { - for (i = 0; i < (depth - 1); i++) - { - *ptr++ = '\t'; - } - } - *ptr++ = '}'; - *ptr++ = '\0'; - } - - return out; -} - -/* Get Array size/item / object item. */ -int cJSON_GetArraySize(const cJSON *array) -{ - cJSON *c = array->child; - int i = 0; - while(c) - { - i++; - c = c->next; - } - return i; -} - -cJSON *cJSON_GetArrayItem(const cJSON *array, int item) -{ - cJSON *c = array ? array->child : NULL; - while (c && item > 0) - { - item--; - c = c->next; - } - - return c; -} - -cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string) -{ - cJSON *c = object ? object->child : NULL; - while (c && cJSON_strcasecmp(c->string, string)) - { - c = c->next; - } - return c; -} - -bool cJSON_HasObjectItem(const cJSON *object,const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item) -{ - cJSON *ref = cJSON_New_Item(); - if (!ref) - { - return NULL; - } - memcpy(ref, item, sizeof(cJSON)); - ref->string = NULL; - ref->type |= cJSON_IsReference; - ref->next = ref->prev = NULL; - return ref; -} - -/* Add item to array/object. */ -void cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - cJSON *c = array->child; - if (!item) - { - return; - } - if (!c) - { - /* list is empty, start new one */ - array->child = item; - } - else - { - /* append to the end */ - while (c->next) - { - c = c->next; - } - suffix_object(c, item); - } -} - -void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - if (!item) - { - return; - } - - /* free old key and set new one */ - if (item->string) - { - cJSON_free(item->string); - } - item->string = cJSON_strdup(string); - - cJSON_AddItemToArray(object,item); -} - -/* Add an item to an object with constant string as key */ -void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - if (!item) - { - return; - } - if (!(item->type & cJSON_StringIsConst) && item->string) - { - cJSON_free(item->string); - } - item->string = (char*)string; - item->type |= cJSON_StringIsConst; - cJSON_AddItemToArray(object, item); -} - -void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - cJSON_AddItemToArray(array, create_reference(item)); -} - -void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - cJSON_AddItemToObject(object, string, create_reference(item)); -} - -cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - /* item doesn't exist */ - return NULL; - } - if (c->prev) - { - /* not the first element */ - c->prev->next = c->next; - } - if (c->next) - { - c->next->prev = c->prev; - } - if (c==array->child) - { - array->child = c->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - c->prev = c->next = NULL; - - return c; -} - -void cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - int i = 0; - cJSON *c = object->child; - while (c && cJSON_strcasecmp(c->string,string)) - { - i++; - c = c->next; - } - if (c) - { - return cJSON_DetachItemFromArray(object, i); - } - - return NULL; -} - -void cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -/* Replace array/object items with new ones. */ -void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - cJSON_AddItemToArray(array, newitem); - return; - } - newitem->next = c; - newitem->prev = c->prev; - c->prev = newitem; - if (c == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } -} - -void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - return; - } - newitem->next = c->next; - newitem->prev = c->prev; - if (newitem->next) - { - newitem->next->prev = newitem; - } - if (c == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } - c->next = c->prev = NULL; - cJSON_Delete(c); -} - -void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - int i = 0; - cJSON *c = object->child; - while(c && cJSON_strcasecmp(c->string, string)) - { - i++; - c = c->next; - } - if(c) - { - /* free the old string if not const */ - if (!(newitem->type & cJSON_StringIsConst) && newitem->string) - { - cJSON_free(newitem->string); - } - - newitem->string = cJSON_strdup(string); - cJSON_ReplaceItemInArray(object, i, newitem); - } -} - -/* Create basic types: */ -cJSON *cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -cJSON *cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -cJSON *cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -cJSON *cJSON_CreateBool(bool b) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = b ? cJSON_True : cJSON_False; - } - - return item; -} - -cJSON *cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - item->valueint = (int)num; - } - - return item; -} - -cJSON *cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type = cJSON_String; - item->valuestring = cJSON_strdup(string); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -cJSON *cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -cJSON *cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -cJSON *cJSON_CreateIntArray(const int *numbers, int count) -{ - int i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0; a && (i < count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -cJSON *cJSON_CreateFloatArray(const float *numbers, int count) -{ - int i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0; a && (i < count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) -{ - int i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0;a && (i < count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -cJSON *cJSON_CreateStringArray(const char **strings, int count) -{ - int i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for (i = 0; a && (i < count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - return a; -} - -/* Duplication */ -cJSON *cJSON_Duplicate(const cJSON *item, bool recurse) -{ - cJSON *newitem = NULL; - cJSON *cptr = NULL; - cJSON *nptr = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - return NULL; - } - /* Create new item */ - newitem = cJSON_New_Item(); - if (!newitem) - { - return NULL; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = cJSON_strdup(item->valuestring); - if (!newitem->valuestring) - { - cJSON_Delete(newitem); - return NULL; - } - } - if (item->string) - { - newitem->string = cJSON_strdup(item->string); - if (!newitem->string) - { - cJSON_Delete(newitem); - return NULL; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - cptr = item->child; - while (cptr) - { - newchild = cJSON_Duplicate(cptr, 1); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - cJSON_Delete(newitem); - return NULL; - } - if (nptr) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - nptr->next = newchild; - newchild->prev = nptr; - nptr = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; nptr = newchild; - } - cptr = cptr->next; - } - - return newitem; -} - -void cJSON_Minify(char *json) -{ - char *into = json; - while (*json) - { - if (*json == ' ') - { - json++; - } - else if (*json == '\t') - { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') - { - json++; - } - else if (*json=='\n') - { - json++; - } - else if ((*json == '/') && (json[1] == '/')) - { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) - { - json++; - } - } - else if ((*json == '/') && (json[1] == '*')) - { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) - { - json++; - } - json += 2; - } - else if (*json == '\"') - { - /* string literals, which are \" sensitive. */ - *into++ = *json++; - while (*json && (*json != '\"')) - { - if (*json == '\\') - { - *into++=*json++; - } - *into++ = *json++; - } - *into++ = *json++; - } - else - { - /* All other characters. */ - *into++ = *json++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} diff --git a/cJSON.h b/cJSON.h deleted file mode 100644 index dbbb739..0000000 --- a/cJSON.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -/* cJSON Types: */ -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String */ - char *valuestring; - /* The item's number, if type==cJSON_Number */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks -{ - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -/* Supply malloc, realloc and free functions to cJSON */ -extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -extern cJSON *cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -extern char *cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -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); -/* Delete a cJSON entity and all subentities. */ -extern void cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -extern int cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -extern cJSON *cJSON_GetArrayItem(const cJSON *array, int item); -/* Get item "string" from object. Case insensitive. */ -extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string); -extern int cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -extern const char *cJSON_GetErrorPtr(void); - -/* These calls create a cJSON item of the appropriate type. */ -extern cJSON *cJSON_CreateNull(void); -extern cJSON *cJSON_CreateTrue(void); -extern cJSON *cJSON_CreateFalse(void); -extern cJSON *cJSON_CreateBool(int b); -extern cJSON *cJSON_CreateNumber(double num); -extern cJSON *cJSON_CreateString(const char *string); -extern cJSON *cJSON_CreateArray(void); -extern cJSON *cJSON_CreateObject(void); - -/* These utilities create an Array of count items. */ -extern cJSON *cJSON_CreateIntArray(const int *numbers, int count); -extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count); -extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count); -extern cJSON *cJSON_CreateStringArray(const char **strings, int count); - -/* Append item to the specified array/object. */ -extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which); -extern void cJSON_DeleteItemFromArray(cJSON *array, int which); -extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string); -extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string); - -/* Update array items. */ -extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -extern cJSON *cJSON_Duplicate(const cJSON *item, int recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ - -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */ -extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated); - -extern void cJSON_Minify(char *json); - -/* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val)) -#define cJSON_SetNumberValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val)) - -/* Macro for iterating over an array */ -#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/cJSONConfig.cmake.in b/cJSONConfig.cmake.in deleted file mode 100644 index 67e8325..0000000 --- a/cJSONConfig.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# Whether the utils lib was build. -set(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@) - -# The include directories used by cJSON -set(CJSON_INCLUDE_DIRS "@prefix@/@includedir@") -set(CJSON_INCLUDE_DIR "@prefix@/@includedir@") - -get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# The cJSON library -set(CJSON_LIBRARY "@CJSON_LIB@") -if(@ENABLE_TARGET_EXPORT@) - # Include the target - include("${_dir}/cjson.cmake") -endif() - -if(CJSON_UTILS_FOUND) - # The cJSON utils library - set(CJSON_UTILS_LIBRARY @CJSON_UTILS_LIB@) - # All cJSON libraries - set(CJSON_LIBRARIES "@CJSON_UTILS_LIB@" "@CJSON_LIB@") - if(@ENABLE_TARGET_EXPORT@) - # Include the target - include("${_dir}/cjson_utils.cmake") - endif() -else() - # All cJSON libraries - set(CJSON_LIBRARIES "@CJSON_LIB@") -endif() diff --git a/cJSONConfigVersion.cmake.in b/cJSONConfigVersion.cmake.in deleted file mode 100644 index 22ffec0..0000000 --- a/cJSONConfigVersion.cmake.in +++ /dev/null @@ -1,11 +0,0 @@ -set(PACKAGE_VERSION "@PROJECT_VERSION@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() diff --git a/cJSON_Utils.c b/cJSON_Utils.c deleted file mode 100644 index 71f3d84..0000000 --- a/cJSON_Utils.c +++ /dev/null @@ -1,828 +0,0 @@ -#include -#include -#include -#include -#include "cJSON_Utils.h" - -static char* cJSONUtils_strdup(const char* str) -{ - size_t len = 0; - char *copy = NULL; - - len = strlen(str) + 1; - if (!(copy = (char*)malloc(len))) - { - return NULL; - } - memcpy(copy, str, len); - - return copy; -} - -static int cJSONUtils_strcasecmp(const char *s1, const char *s2) -{ - if (!s1) - { - return (s1 == s2) ? 0 : 1; /* both NULL? */ - } - if (!s2) - { - return 1; - } - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) - { - if(*s1 == 0) - { - return 0; - } - } - - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -/* JSON Pointer implementation: */ -static int cJSONUtils_Pstrcasecmp(const char *a, const char *e) -{ - if (!a || !e) - { - return (a == e) ? 0 : 1; /* both NULL? */ - } - for (; *a && *e && (*e != '/'); a++, e++) /* compare until next '/' */ - { - if (*e == '~') - { - /* check for escaped '~' (~0) and '/' (~1) */ - if (!((e[1] == '0') && (*a == '~')) && !((e[1] == '1') && (*a == '/'))) - { - /* invalid escape sequence or wrong character in *a */ - return 1; - } - else - { - e++; - } - } - else if (tolower(*a) != tolower(*e)) - { - return 1; - } - } - if (((*e != 0) && (*e != '/')) != (*a != 0)) - { - /* one string has ended, the other not */ - return 1; - } - - return 0; -} - -static int cJSONUtils_PointerEncodedstrlen(const char *s) -{ - int l = 0; - for (; *s; s++, l++) - { - if ((*s == '~') || (*s == '/')) - { - l++; - } - } - - return l; -} - -static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s) -{ - for (; *s; s++) - { - if (*s == '/') - { - *d++ = '~'; - *d++ = '1'; - } - else if (*s == '~') - { - *d++ = '~'; - *d++ = '0'; - } - else - { - *d++ = *s; - } - } - - *d = '\0'; -} - -char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) -{ - int type = object->type; - int c = 0; - cJSON *obj = 0; - - if (object == target) - { - /* found */ - return cJSONUtils_strdup(""); - } - - /* recursively search all children of the object */ - for (obj = object->child; obj; obj = obj->next, c++) - { - char *found = cJSONUtils_FindPointerFromObjectTo(obj, target); - if (found) - { - if ((type & 0xFF) == cJSON_Array) - { - /* reserve enough memory for a 64 bit integer + '/' and '\0' */ - char *ret = (char*)malloc(strlen(found) + 23); - sprintf(ret, "/%d%s", c, found); /* / */ - free(found); - - return ret; - } - else if ((type & 0xFF) == cJSON_Object) - { - char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2); - *ret = '/'; - cJSONUtils_PointerEncodedstrcpy(ret + 1, obj->string); - strcat(ret, found); - free(found); - - return ret; - } - - /* reached leaf of the tree, found nothing */ - free(found); - return NULL; - } - } - - /* not found */ - return NULL; -} - -cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer) -{ - /* follow path of the pointer */ - while ((*pointer++ == '/') && object) - { - if ((object->type & 0xFF) == cJSON_Array) - { - int which = 0; - /* parse array index */ - while ((*pointer >= '0') && (*pointer <= '9')) - { - which = (10 * which) + (*pointer++ - '0'); - } - if (*pointer && (*pointer != '/')) - { - /* not end of string or new path token */ - return NULL; - } - object = cJSON_GetArrayItem(object, which); - } - else if ((object->type & 0xFF) == cJSON_Object) - { - object = object->child; - /* GetObjectItem. */ - while (object && cJSONUtils_Pstrcasecmp(object->string, pointer)) - { - object = object->next; - } - /* skip to the next path token or end of string */ - while (*pointer && (*pointer != '/')) - { - pointer++; - } - } - else - { - return NULL; - } - } - - return object; -} - -/* JSON Patch implementation. */ -static void cJSONUtils_InplaceDecodePointerString(char *string) -{ - char *s2 = string; - for (; *string; s2++, string++) - { - *s2 = (*string != '~') - ? (*string) - : ((*(++string) == '0') - ? '~' - : '/'); - } - - *s2 = '\0'; -} - -static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) -{ - char *parentptr = NULL; - char *childptr = NULL; - cJSON *parent = NULL; - cJSON *ret = NULL; - - /* copy path and split it in parent and child */ - parentptr = cJSONUtils_strdup(path); - childptr = strrchr(parentptr, '/'); /* last '/' */ - if (childptr) - { - /* split strings */ - *childptr++ = '\0'; - } - parent = cJSONUtils_GetPointer(object, parentptr); - cJSONUtils_InplaceDecodePointerString(childptr); - - if (!parent) - { - /* Couldn't find object to remove child from. */ - ret = NULL; - } - else if ((parent->type & 0xFF) == cJSON_Array) - { - ret = cJSON_DetachItemFromArray(parent, atoi(childptr)); - } - else if ((parent->type & 0xFF) == cJSON_Object) - { - ret = cJSON_DetachItemFromObject(parent, childptr); - } - free(parentptr); - - /* return the detachted item */ - return ret; -} - -static int cJSONUtils_Compare(cJSON *a, cJSON *b) -{ - if ((a->type & 0xFF) != (b->type & 0xFF)) - { - /* mismatched type. */ - return -1; - } - switch (a->type & 0xFF) - { - case cJSON_Number: - /* numeric mismatch. */ - return ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble)) ? -2 : 0; - case cJSON_String: - /* string mismatch. */ - return (strcmp(a->valuestring, b->valuestring) != 0) ? -3 : 0; - case cJSON_Array: - for (a = a->child, b = b->child; a && b; a = a->next, b = b->next) - { - int err = cJSONUtils_Compare(a, b); - if (err) - { - return err; - } - } - /* array size mismatch? (one of both children is not NULL) */ - return (a || b) ? -4 : 0; - case cJSON_Object: - cJSONUtils_SortObject(a); - cJSONUtils_SortObject(b); - a = a->child; - b = b->child; - while (a && b) - { - int err = 0; - /* compare object keys */ - if (cJSONUtils_strcasecmp(a->string, b->string)) - { - /* missing member */ - return -6; - } - err = cJSONUtils_Compare(a, b); - if (err) - { - return err; - } - a = a->next; - b = b->next; - } - /* object length mismatch (one of both children is not null) */ - return (a || b) ? -5 : 0; - - default: - break; - } - /* null, true or false */ - return 0; -} - -static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) -{ - cJSON *op = NULL; - cJSON *path = NULL; - cJSON *value = NULL; - cJSON *parent = NULL; - int opcode = 0; - char *parentptr = NULL; - char *childptr = NULL; - - op = cJSON_GetObjectItem(patch, "op"); - path = cJSON_GetObjectItem(patch, "path"); - if (!op || !path) - { - /* malformed patch. */ - return 2; - } - - /* decode operation */ - if (!strcmp(op->valuestring, "add")) - { - opcode = 0; - } - else if (!strcmp(op->valuestring, "remove")) - { - opcode = 1; - } - else if (!strcmp(op->valuestring, "replace")) - { - opcode = 2; - } - else if (!strcmp(op->valuestring, "move")) - { - opcode = 3; - } - else if (!strcmp(op->valuestring, "copy")) - { - opcode = 4; - } - else if (!strcmp(op->valuestring, "test")) - { - /* compare value: {...} with the given path */ - return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value")); - } - else - { - /* unknown opcode. */ - return 3; - } - - /* Remove/Replace */ - if ((opcode == 1) || (opcode == 2)) - { - /* Get rid of old. */ - cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring)); - if (opcode == 1) - { - /* For Remove, this is job done. */ - return 0; - } - } - - /* Copy/Move uses "from". */ - if ((opcode == 3) || (opcode == 4)) - { - cJSON *from = cJSON_GetObjectItem(patch, "from"); - if (!from) - { - /* missing "from" for copy/move. */ - return 4; - } - - if (opcode == 3) - { - /* move */ - value = cJSONUtils_PatchDetach(object, from->valuestring); - } - if (opcode == 4) - { - /* copy */ - value = cJSONUtils_GetPointer(object, from->valuestring); - } - if (!value) - { - /* missing "from" for copy/move. */ - return 5; - } - if (opcode == 4) - { - value = cJSON_Duplicate(value, 1); - } - if (!value) - { - /* out of memory for copy/move. */ - return 6; - } - } - else /* Add/Replace uses "value". */ - { - value = cJSON_GetObjectItem(patch, "value"); - if (!value) - { - /* missing "value" for add/replace. */ - return 7; - } - value = cJSON_Duplicate(value, 1); - if (!value) - { - /* out of memory for add/replace. */ - return 8; - } - } - - /* Now, just add "value" to "path". */ - - /* split pointer in parent and child */ - parentptr = cJSONUtils_strdup(path->valuestring); - childptr = strrchr(parentptr, '/'); - if (childptr) - { - *childptr++ = '\0'; - } - parent = cJSONUtils_GetPointer(object, parentptr); - cJSONUtils_InplaceDecodePointerString(childptr); - - /* add, remove, replace, move, copy, test. */ - if (!parent) - { - /* Couldn't find object to add to. */ - free(parentptr); - cJSON_Delete(value); - return 9; - } - else if ((parent->type & 0xFF) == cJSON_Array) - { - if (!strcmp(childptr, "-")) - { - cJSON_AddItemToArray(parent, value); - } - else - { - cJSON_InsertItemInArray(parent, atoi(childptr), value); - } - } - else if ((parent->type & 0xFF) == cJSON_Object) - { - cJSON_DeleteItemFromObject(parent, childptr); - cJSON_AddItemToObject(parent, childptr, value); - } - else - { - cJSON_Delete(value); - } - free(parentptr); - - return 0; -} - -int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches) -{ - int err = 0; - if ((patches->type & 0xFF) != cJSON_Array) - { - /* malformed patches. */ - return 1; - } - if (patches) - { - patches = patches->child; - } - while (patches) - { - if ((err = cJSONUtils_ApplyPatch(object, patches))) - { - return err; - } - patches = patches->next; - } - - return 0; -} - -static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char *path, const char *suffix, cJSON *val) -{ - cJSON *patch = cJSON_CreateObject(); - cJSON_AddItemToObject(patch, "op", cJSON_CreateString(op)); - if (suffix) - { - char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(suffix) + 2); - cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), suffix); - cJSON_AddItemToObject(patch, "path", cJSON_CreateString(newpath)); - free(newpath); - } - else - { - cJSON_AddItemToObject(patch, "path", cJSON_CreateString(path)); - } - if (val) - { - cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(val, 1)); - } - cJSON_AddItemToArray(patches, patch); -} - -void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val) -{ - cJSONUtils_GeneratePatch(array, op, path, 0, val); -} - -static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to) -{ - if ((from->type & 0xFF) != (to->type & 0xFF)) - { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); - return; - } - - switch ((from->type & 0xFF)) - { - case cJSON_Number: - if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble)) - { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); - } - return; - - case cJSON_String: - if (strcmp(from->valuestring, to->valuestring) != 0) - { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); - } - return; - - case cJSON_Array: - { - int c = 0; - char *newpath = (char*)malloc(strlen(path) + 23); /* Allow space for 64bit int. */ - /* generate patches for all array elements that exist in "from" and "to" */ - for (c = 0, from = from->child, to = to->child; from && to; from = from->next, to = to->next, c++) - { - sprintf(newpath, "%s/%d", path, c); /* path of the current array element */ - cJSONUtils_CompareToPatch(patches, newpath, from, to); - } - /* remove leftover elements from 'from' that are not in 'to' */ - for (; from; from = from->next, c++) - { - sprintf(newpath, "%d", c); - cJSONUtils_GeneratePatch(patches, "remove", path, newpath, 0); - } - /* add new elements in 'to' that were not in 'from' */ - for (; to; to = to->next, c++) - { - cJSONUtils_GeneratePatch(patches, "add", path, "-", to); - } - free(newpath); - return; - } - - case cJSON_Object: - { - cJSON *a = NULL; - cJSON *b = NULL; - cJSONUtils_SortObject(from); - cJSONUtils_SortObject(to); - - a = from->child; - b = to->child; - /* for all object values in the object with more of them */ - while (a || b) - { - int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp(a->string, b->string)); - if (!diff) - { - /* both object keys are the same */ - char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(a->string) + 2); - cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), a->string); - /* create a patch for the element */ - cJSONUtils_CompareToPatch(patches, newpath, a, b); - free(newpath); - a = a->next; - b = b->next; - } - else if (diff < 0) - { - /* object element doesn't exist in 'to' --> remove it */ - cJSONUtils_GeneratePatch(patches, "remove", path, a->string, 0); - a = a->next; - } - else - { - /* object element doesn't exist in 'from' --> add it */ - cJSONUtils_GeneratePatch(patches, "add", path, b->string, b); - b = b->next; - } - } - return; - } - - default: - break; - } -} - -cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to) -{ - cJSON *patches = cJSON_CreateArray(); - cJSONUtils_CompareToPatch(patches, "", from, to); - - return patches; -} - -/* sort lists using mergesort */ -static cJSON *cJSONUtils_SortList(cJSON *list) -{ - cJSON *first = list; - cJSON *second = list; - cJSON *ptr = list; - - if (!list || !list->next) - { - /* One entry is sorted already. */ - return list; - } - - while (ptr && ptr->next && (cJSONUtils_strcasecmp(ptr->string, ptr->next->string) < 0)) - { - /* Test for list sorted. */ - ptr = ptr->next; - } - if (!ptr || !ptr->next) - { - /* Leave sorted lists unmodified. */ - return list; - } - - /* reset ptr to the beginning */ - ptr = list; - while (ptr) - { - /* Walk two pointers to find the middle. */ - second = second->next; - ptr = ptr->next; - /* advances ptr two steps at a time */ - if (ptr) - { - ptr = ptr->next; - } - } - if (second && second->prev) - { - /* Split the lists */ - second->prev->next = NULL; - } - - /* Recursively sort the sub-lists. */ - first = cJSONUtils_SortList(first); - second = cJSONUtils_SortList(second); - list = ptr = NULL; - - while (first && second) /* Merge the sub-lists */ - { - if (cJSONUtils_strcasecmp(first->string, second->string) < 0) - { - if (!list) - { - /* start merged list with the first element of the first list */ - list = ptr = first; - } - else - { - /* add first element of first list to merged list */ - ptr->next = first; - first->prev = ptr; - ptr = first; - } - first = first->next; - } - else - { - if (!list) - { - /* start merged list with the first element of the second list */ - list = ptr = second; - } - else - { - /* add first element of second list to merged list */ - ptr->next = second; - second->prev = ptr; - ptr = second; - } - second = second->next; - } - } - if (first) - { - /* Append rest of first list. */ - if (!list) - { - return first; - } - ptr->next = first; - first->prev = ptr; - } - if (second) - { - /* Append rest of second list */ - if (!list) - { - return second; - } - ptr->next = second; - second->prev = ptr; - } - - return list; -} - -void cJSONUtils_SortObject(cJSON *object) -{ - object->child = cJSONUtils_SortList(object->child); -} - -cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch) -{ - if (!patch || ((patch->type & 0xFF) != cJSON_Object)) - { - /* scalar value, array or NULL, just duplicate */ - cJSON_Delete(target); - return cJSON_Duplicate(patch, 1); - } - - if (!target || ((target->type & 0xFF) != cJSON_Object)) - { - cJSON_Delete(target); - target = cJSON_CreateObject(); - } - - patch = patch->child; - while (patch) - { - if ((patch->type & 0xFF) == cJSON_NULL) - { - /* NULL is the indicator to remove a value, see RFC7396 */ - cJSON_DeleteItemFromObject(target, patch->string); - } - else - { - cJSON *replaceme = cJSON_DetachItemFromObject(target, patch->string); - cJSON_AddItemToObject(target, patch->string, cJSONUtils_MergePatch(replaceme, patch)); - } - patch = patch->next; - } - return target; -} - -cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to) -{ - cJSON *patch = NULL; - if (!to) - { - /* patch to delete everything */ - return cJSON_CreateNull(); - } - if (((to->type & 0xFF) != cJSON_Object) || !from || ((from->type & 0xFF) != cJSON_Object)) - { - return cJSON_Duplicate(to, 1); - } - - cJSONUtils_SortObject(from); - cJSONUtils_SortObject(to); - - from = from->child; - to = to->child; - patch = cJSON_CreateObject(); - while (from || to) - { - int compare = from ? (to ? strcmp(from->string, to->string) : -1) : 1; - if (compare < 0) - { - /* from has a value that to doesn't have -> remove */ - cJSON_AddItemToObject(patch, from->string, cJSON_CreateNull()); - from = from->next; - } - else if (compare > 0) - { - /* to has a value that from doesn't have -> add to patch */ - cJSON_AddItemToObject(patch, to->string, cJSON_Duplicate(to, 1)); - to = to->next; - } - else - { - /* object key exists in both objects */ - if (cJSONUtils_Compare(from, to)) - { - /* not identical --> generate a patch */ - cJSON_AddItemToObject(patch, to->string, cJSONUtils_GenerateMergePatch(from, to)); - } - /* next key in the object */ - from = from->next; - to = to->next; - } - } - if (!patch->child) - { - cJSON_Delete(patch); - return NULL; - } - - return patch; -} diff --git a/cJSON_Utils.h b/cJSON_Utils.h deleted file mode 100644 index cefda08..0000000 --- a/cJSON_Utils.h +++ /dev/null @@ -1,44 +0,0 @@ -#include "cJSON.h" - -/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ -cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer); - -/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ -cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to); -/* Utility for generating patch array entries. */ -void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val); -/* Returns 0 for success. */ -int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches); - -/* -// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: -//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches) -//{ -// cJSON *modme = cJSON_Duplicate(*object, 1); -// int error = cJSONUtils_ApplyPatches(modme, patches); -// if (!error) -// { -// cJSON_Delete(*object); -// *object = modme; -// } -// else -// { -// cJSON_Delete(modme); -// } -// -// return error; -//} -// Code not added to library since this strategy is a LOT slower. -*/ - -/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ -/* target will be modified by patch. return value is new ptr for target. */ -cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch); -/* generates a patch to move from -> to */ -cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to); - -/* Given a root object and a target object, construct a pointer from one to the other. */ -char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target); - -/* Sorts the members of the object into alphabetical order. */ -void cJSONUtils_SortObject(cJSON *object); diff --git a/libcjson.pc.in b/libcjson.pc.in deleted file mode 100644 index b3a5b40..0000000 --- a/libcjson.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -libdir=${prefix}/@libdir@ -includedir=${prefix}/@includedir@ - -Name: libcjson -Version: @version@ -Description: Ultralightweight JSON parser in ANSI C -URL: https://github.com/DaveGamble/cJSON -Libs: -L${libdir} -lcjson -Libs.Private: -lm -Cflags: -I${includedir} diff --git a/libcjson_utils.pc.in b/libcjson_utils.pc.in deleted file mode 100644 index 174ab60..0000000 --- a/libcjson_utils.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -libdir=${prefix}/@libdir@ -includedir=${prefix}/@includedir@ - -Name: libcjson_utils -Version: @version@ -Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON. -URL: https://github.com/DaveGamble/cJSON -Libs: -L${libdir} -lcjson_utils -Cflags: -I${includedir} -Requires: libcjson diff --git a/test.c b/test.c deleted file mode 100644 index 7706d97..0000000 --- a/test.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include "cJSON.h" - -/* Parse text to JSON, then render back to text, and print! */ -void doit(char *text) -{ - char *out = NULL; - cJSON *json = NULL; - - json = cJSON_Parse(text); - if (!json) - { - printf("Error before: [%s]\n", cJSON_GetErrorPtr()); - } - else - { - out = cJSON_Print(json); - cJSON_Delete(json); - printf("%s\n", out); - free(out); - } -} - -/* Read a file, parse, render back, etc. */ -void dofile(char *filename) -{ - FILE *f = NULL; - long len = 0; - char *data = NULL; - - /* open in read binary mode */ - f = fopen(filename,"rb"); - /* get the length */ - fseek(f, 0, SEEK_END); - len = ftell(f); - fseek(f, 0, SEEK_SET); - - data = (char*)malloc(len + 1); - - fread(data, 1, len, f); - data[len] = '\0'; - fclose(f); - - doit(data); - free(data); -} - -/* Used by some code below as an example datatype. */ -struct record -{ - const char *precision; - double lat; - double lon; - const char *address; - const char *city; - const char *state; - const char *zip; - const char *country; -}; - -/* Create a bunch of objects as demonstration. */ -void create_objects(void) -{ - /* declare a few. */ - cJSON *root = NULL; - cJSON *fmt = NULL; - cJSON *img = NULL; - cJSON *thm = NULL; - cJSON *fld = NULL; - char *out = NULL; - int i = 0; - - /* Our "days of the week" array: */ - const char *strings[7] = - { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - }; - /* Our matrix: */ - int numbers[3][3] = - { - {0, -1, 0}, - {1, 0, 0}, - {0 ,0, 1} - }; - /* Our "gallery" item: */ - int ids[4] = { 116, 943, 234, 38793 }; - /* Our array of "records": */ - struct record fields[2] = - { - { - "zip", - 37.7668, - -1.223959e+2, - "", - "SAN FRANCISCO", - "CA", - "94107", - "US" - }, - { - "zip", - 37.371991, - -1.22026e+2, - "", - "SUNNYVALE", - "CA", - "94085", - "US" - } - }; - volatile double zero = 0.0; - - /* Here we construct some JSON standards, from the JSON site. */ - - /* Our "Video" datatype: */ - root = cJSON_CreateObject(); - cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); - cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); - cJSON_AddStringToObject(fmt, "type", "rect"); - cJSON_AddNumberToObject(fmt, "width", 1920); - cJSON_AddNumberToObject(fmt, "height", 1080); - cJSON_AddFalseToObject (fmt, "interlace"); - cJSON_AddNumberToObject(fmt, "frame rate", 24); - - /* Print to text */ - out = cJSON_Print(root); - /* Delete the cJSON */ - 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); - cJSON_Delete(root); - printf("%s\n", out); - free(out); - - /* Our matrix: */ - root = cJSON_CreateArray(); - for (i = 0; i < 3; i++) - { - cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); - } - - /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ - - out = cJSON_Print(root); - cJSON_Delete(root); - printf("%s\n", out); - free(out); - - - /* Our "gallery" item: */ - root = cJSON_CreateObject(); - cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); - cJSON_AddNumberToObject(img, "Width", 800); - cJSON_AddNumberToObject(img, "Height", 600); - cJSON_AddStringToObject(img, "Title", "View from 15th Floor"); - cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject()); - cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); - cJSON_AddNumberToObject(thm, "Height", 125); - cJSON_AddStringToObject(thm, "Width", "100"); - cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4)); - - out = cJSON_Print(root); - cJSON_Delete(root); - printf("%s\n", out); - free(out); - - /* Our array of "records": */ - - root = cJSON_CreateArray(); - for (i = 0; i < 2; i++) - { - cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); - cJSON_AddStringToObject(fld, "precision", fields[i].precision); - cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); - cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); - cJSON_AddStringToObject(fld, "Address", fields[i].address); - cJSON_AddStringToObject(fld, "City", fields[i].city); - cJSON_AddStringToObject(fld, "State", fields[i].state); - cJSON_AddStringToObject(fld, "Zip", fields[i].zip); - cJSON_AddStringToObject(fld, "Country", fields[i].country); - } - - /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ - - out = cJSON_Print(root); - cJSON_Delete(root); - printf("%s\n", out); - free(out); - - root = cJSON_CreateObject(); - cJSON_AddNumberToObject(root, "number", 1.0 / zero); - out = cJSON_Print(root); - cJSON_Delete(root); - printf("%s\n", out); - free(out); -} - -int main(void) -{ - /* a bunch of json: */ - char text1[] = - "{\n" - "\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n" - "\"format\": {\"type\": \"rect\", \n" - "\"width\": 1920, \n" - "\"height\": 1080, \n" - "\"interlace\": false,\"frame rate\": 24\n" - "}\n" - "}"; - char text2[] = "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]"; - char text3[] = - "[\n" - " [0, -1, 0],\n" - " [1, 0, 0],\n" - " [0, 0, 1]\n" - "\t]\n"; - char text4[] = - "{\n" - "\t\t\"Image\": {\n" - "\t\t\t\"Width\": 800,\n" - "\t\t\t\"Height\": 600,\n" - "\t\t\t\"Title\": \"View from 15th Floor\",\n" - "\t\t\t\"Thumbnail\": {\n" - "\t\t\t\t\"Url\": \"http:/*www.example.com/image/481989943\",\n" - "\t\t\t\t\"Height\": 125,\n" - "\t\t\t\t\"Width\": \"100\"\n" - "\t\t\t},\n" - "\t\t\t\"IDs\": [116, 943, 234, 38793]\n" - "\t\t}\n" - "\t}"; - char text5[] = - "[\n" - "\t {\n" - "\t \"precision\": \"zip\",\n" - "\t \"Latitude\": 37.7668,\n" - "\t \"Longitude\": -122.3959,\n" - "\t \"Address\": \"\",\n" - "\t \"City\": \"SAN FRANCISCO\",\n" - "\t \"State\": \"CA\",\n" - "\t \"Zip\": \"94107\",\n" - "\t \"Country\": \"US\"\n" - "\t },\n" - "\t {\n" - "\t \"precision\": \"zip\",\n" - "\t \"Latitude\": 37.371991,\n" - "\t \"Longitude\": -122.026020,\n" - "\t \"Address\": \"\",\n" - "\t \"City\": \"SUNNYVALE\",\n" - "\t \"State\": \"CA\",\n" - "\t \"Zip\": \"94085\",\n" - "\t \"Country\": \"US\"\n" - "\t }\n" - "\t ]"; - - char text6[] = - "" - "\n" - "\n" - " \n" - " \n" - "Application Error\n" - "\n" - "\n" - " \n" - "\n" - "\n"; - - /* Process each json textblock by parsing, then rebuilding: */ - doit(text1); - doit(text2); - doit(text3); - doit(text4); - doit(text5); - doit(text6); - - /* Parse standard testfiles: */ - /* dofile("../../tests/test1"); */ - /* dofile("../../tests/test2"); */ - /* dofile("../../tests/test3"); */ - /* dofile("../../tests/test4"); */ - /* dofile("../../tests/test5"); */ - /* dofile("../../tests/test6"); */ - - /* Now some samplecode for building objects concisely: */ - create_objects(); - - return 0; -} diff --git a/test_utils.c b/test_utils.c deleted file mode 100644 index 961b84e..0000000 --- a/test_utils.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include -#include "cJSON_Utils.h" - -int main(void) -{ - /* Some variables */ - char *temp = NULL; - char *patchtext = NULL; - char *patchedtext = NULL; - - int i = 0; - /* JSON Pointer tests: */ - cJSON *root = NULL; - const char *json= - "{" - "\"foo\": [\"bar\", \"baz\"]," - "\"\": 0," - "\"a/b\": 1," - "\"c%d\": 2," - "\"e^f\": 3," - "\"g|h\": 4," - "\"i\\\\j\": 5," - "\"k\\\"l\": 6," - "\" \": 7," - "\"m~n\": 8" - "}"; - - const char *tests[12] = {"","/foo","/foo/0","/","/a~1b","/c%d","/e^f","/g|h","/i\\j","/k\"l","/ ","/m~0n"}; - - /* JSON Apply Patch tests: */ - const char *patches[15][3] = - { - {"{ \"foo\": \"bar\"}", "[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\" }]","{\"baz\": \"qux\",\"foo\": \"bar\"}"}, - {"{ \"foo\": [ \"bar\", \"baz\" ] }", "[{ \"op\": \"add\", \"path\": \"/foo/1\", \"value\": \"qux\" }]","{\"foo\": [ \"bar\", \"qux\", \"baz\" ] }"}, - {"{\"baz\": \"qux\",\"foo\": \"bar\"}"," [{ \"op\": \"remove\", \"path\": \"/baz\" }]","{\"foo\": \"bar\" }"}, - {"{ \"foo\": [ \"bar\", \"qux\", \"baz\" ] }","[{ \"op\": \"remove\", \"path\": \"/foo/1\" }]","{\"foo\": [ \"bar\", \"baz\" ] }"}, - {"{ \"baz\": \"qux\",\"foo\": \"bar\"}","[{ \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" }]","{\"baz\": \"boo\",\"foo\": \"bar\"}"}, - {"{\"foo\": {\"bar\": \"baz\",\"waldo\": \"fred\"},\"qux\": {\"corge\": \"grault\"}}","[{ \"op\": \"move\", \"from\": \"/foo/waldo\", \"path\": \"/qux/thud\" }]","{\"foo\": {\"bar\": \"baz\"},\"qux\": {\"corge\": \"grault\",\"thud\": \"fred\"}}"}, - {"{ \"foo\": [ \"all\", \"grass\", \"cows\", \"eat\" ] }","[ { \"op\": \"move\", \"from\": \"/foo/1\", \"path\": \"/foo/3\" }]","{ \"foo\": [ \"all\", \"cows\", \"eat\", \"grass\" ] }"}, - {"{\"baz\": \"qux\",\"foo\": [ \"a\", 2, \"c\" ]}","[{ \"op\": \"test\", \"path\": \"/baz\", \"value\": \"qux\" },{ \"op\": \"test\", \"path\": \"/foo/1\", \"value\": 2 }]",""}, - {"{ \"baz\": \"qux\" }","[ { \"op\": \"test\", \"path\": \"/baz\", \"value\": \"bar\" }]",""}, - {"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/child\", \"value\": { \"grandchild\": { } } }]","{\"foo\": \"bar\",\"child\": {\"grandchild\": {}}}"}, - {"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\", \"xyz\": 123 }]","{\"foo\": \"bar\",\"baz\": \"qux\"}"}, - {"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz/bat\", \"value\": \"qux\" }]",""}, - {"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": 10}]",""}, - {"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": \"10\"}]",""}, - {"{ \"foo\": [\"bar\"] }","[ { \"op\": \"add\", \"path\": \"/foo/-\", \"value\": [\"abc\", \"def\"] }]","{\"foo\": [\"bar\", [\"abc\", \"def\"]] }"} - }; - - /* JSON Apply Merge tests: */ - const char *merges[15][3] = - { - {"{\"a\":\"b\"}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"}, - {"{\"a\":\"b\"}", "{\"b\":\"c\"}", "{\"a\":\"b\",\"b\":\"c\"}"}, - {"{\"a\":\"b\"}", "{\"a\":null}", "{}"}, - {"{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":null}", "{\"b\":\"c\"}"}, - {"{\"a\":[\"b\"]}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"}, - {"{\"a\":\"c\"}", "{\"a\":[\"b\"]}", "{\"a\":[\"b\"]}"}, - {"{\"a\":{\"b\":\"c\"}}", "{\"a\":{\"b\":\"d\",\"c\":null}}", "{\"a\":{\"b\":\"d\"}}"}, - {"{\"a\":[{\"b\":\"c\"}]}", "{\"a\":[1]}", "{\"a\":[1]}"}, - {"[\"a\",\"b\"]", "[\"c\",\"d\"]", "[\"c\",\"d\"]"}, - {"{\"a\":\"b\"}", "[\"c\"]", "[\"c\"]"}, - {"{\"a\":\"foo\"}", "null", "null"}, - {"{\"a\":\"foo\"}", "\"bar\"", "\"bar\""}, - {"{\"e\":null}", "{\"a\":1}", "{\"e\":null,\"a\":1}"}, - {"[1,2]", "{\"a\":\"b\",\"c\":null}", "{\"a\":\"b\"}"}, - {"{}","{\"a\":{\"bb\":{\"ccc\":null}}}", "{\"a\":{\"bb\":{}}}"} - }; - - - /* Misc tests */ - int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const char *random = "QWERTYUIOPASDFGHJKLZXCVBNM"; - char buf[2] = {0,0}; - char *before = NULL; - char *after = NULL; - cJSON *object = NULL; - cJSON *nums = NULL; - cJSON *num6 = NULL; - cJSON *sortme = NULL; - - - printf("JSON Pointer Tests\n"); - root = cJSON_Parse(json); - for (i = 0; i < 12; i++) - { - char *output = cJSON_Print(cJSONUtils_GetPointer(root, tests[i])); - printf("Test %d:\n%s\n\n", i + 1, output); - free(output); - } - cJSON_Delete(root); - - - printf("JSON Apply Patch Tests\n"); - for (i = 0; i < 15; i++) - { - cJSON *object = cJSON_Parse(patches[i][0]); - cJSON *patch = cJSON_Parse(patches[i][1]); - int err = cJSONUtils_ApplyPatches(object, patch); - char *output = cJSON_Print(object); - printf("Test %d (err %d):\n%s\n\n", i + 1, err, output); - - free(output); - cJSON_Delete(object); - cJSON_Delete(patch); - } - - /* JSON Generate Patch tests: */ - printf("JSON Generate Patch Tests\n"); - for (i = 0; i < 15; i++) - { - cJSON *from; - cJSON *to; - cJSON *patch; - char *out; - if (!strlen(patches[i][2])) - { - continue; - } - from = cJSON_Parse(patches[i][0]); - to = cJSON_Parse(patches[i][2]); - patch = cJSONUtils_GeneratePatches(from, to); - out = cJSON_Print(patch); - printf("Test %d: (patch: %s):\n%s\n\n", i + 1, patches[i][1], out); - - free(out); - cJSON_Delete(from); - cJSON_Delete(to); - cJSON_Delete(patch); - } - - /* Misc tests: */ - printf("JSON Pointer construct\n"); - object = cJSON_CreateObject(); - nums = cJSON_CreateIntArray(numbers, 10); - num6 = cJSON_GetArrayItem(nums, 6); - cJSON_AddItemToObject(object, "numbers", nums); - temp = cJSONUtils_FindPointerFromObjectTo(object, num6); - printf("Pointer: [%s]\n", temp); - free(temp); - temp = cJSONUtils_FindPointerFromObjectTo(object, nums); - printf("Pointer: [%s]\n", temp); - free(temp); - temp = cJSONUtils_FindPointerFromObjectTo(object, object); - printf("Pointer: [%s]\n", temp); - free(temp); - cJSON_Delete(object); - - /* JSON Sort test: */ - sortme = cJSON_CreateObject(); - for (i = 0; i < 26; i++) - { - buf[0] = random[i]; - cJSON_AddItemToObject(sortme, buf, cJSON_CreateNumber(1)); - } - before = cJSON_PrintUnformatted(sortme); - cJSONUtils_SortObject(sortme); - after = cJSON_PrintUnformatted(sortme); - printf("Before: [%s]\nAfter: [%s]\n\n", before, after); - - free(before); - free(after); - cJSON_Delete(sortme); - - /* Merge tests: */ - printf("JSON Merge Patch tests\n"); - for (i = 0; i < 15; i++) - { - cJSON *object = cJSON_Parse(merges[i][0]); - cJSON *patch = cJSON_Parse(merges[i][1]); - char *before = cJSON_PrintUnformatted(object); - patchtext = cJSON_PrintUnformatted(patch); - printf("Before: [%s] -> [%s] = ", before, patchtext); - object = cJSONUtils_MergePatch(object, patch); - after = cJSON_PrintUnformatted(object); - printf("[%s] vs [%s] (%s)\n", after, merges[i][2], strcmp(after, merges[i][2]) ? "FAIL" : "OK"); - - free(before); - free(patchtext); - free(after); - cJSON_Delete(object); - cJSON_Delete(patch); - } - - /* Generate Merge tests: */ - for (i = 0; i < 15; i++) - { - cJSON *from = cJSON_Parse(merges[i][0]); - cJSON *to = cJSON_Parse(merges[i][2]); - cJSON *patch = cJSONUtils_GenerateMergePatch(from,to); - from = cJSONUtils_MergePatch(from,patch); - patchtext = cJSON_PrintUnformatted(patch); - patchedtext = cJSON_PrintUnformatted(from); - printf("Patch [%s] vs [%s] = [%s] vs [%s] (%s)\n", patchtext, merges[i][1], patchedtext, merges[i][2], strcmp(patchedtext, merges[i][2]) ? "FAIL" : "OK"); - - cJSON_Delete(from); - cJSON_Delete(to); - cJSON_Delete(patch); - free(patchtext); - free(patchedtext); - } - - return 0; -} diff --git a/tests/test1 b/tests/test1 deleted file mode 100644 index eacfbf5..0000000 --- a/tests/test1 +++ /dev/null @@ -1,22 +0,0 @@ -{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} diff --git a/tests/test2 b/tests/test2 deleted file mode 100644 index 5600991..0000000 --- a/tests/test2 +++ /dev/null @@ -1,11 +0,0 @@ -{"menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} diff --git a/tests/test3 b/tests/test3 deleted file mode 100644 index 5662b37..0000000 --- a/tests/test3 +++ /dev/null @@ -1,26 +0,0 @@ -{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} \ No newline at end of file diff --git a/tests/test4 b/tests/test4 deleted file mode 100644 index d540b57..0000000 --- a/tests/test4 +++ /dev/null @@ -1,88 +0,0 @@ -{"web-app": { - "servlet": [ - { - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500}}, - { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2"}}, - { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet"}, - - { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet"}, - { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true}}], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*"}, - - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} \ No newline at end of file diff --git a/tests/test5 b/tests/test5 deleted file mode 100644 index 49980ca..0000000 --- a/tests/test5 +++ /dev/null @@ -1,27 +0,0 @@ -{"menu": { - "header": "SVG Viewer", - "items": [ - {"id": "Open"}, - {"id": "OpenNew", "label": "Open New"}, - null, - {"id": "ZoomIn", "label": "Zoom In"}, - {"id": "ZoomOut", "label": "Zoom Out"}, - {"id": "OriginalView", "label": "Original View"}, - null, - {"id": "Quality"}, - {"id": "Pause"}, - {"id": "Mute"}, - null, - {"id": "Find", "label": "Find..."}, - {"id": "FindAgain", "label": "Find Again"}, - {"id": "Copy"}, - {"id": "CopyAgain", "label": "Copy Again"}, - {"id": "CopySVG", "label": "Copy SVG"}, - {"id": "ViewSVG", "label": "View SVG"}, - {"id": "ViewSource", "label": "View Source"}, - {"id": "SaveAs", "label": "Save As"}, - null, - {"id": "Help"}, - {"id": "About", "label": "About Adobe CVG Viewer..."} - ] -}} diff --git a/tests/test6 b/tests/test6 deleted file mode 100644 index d5cb28f..0000000 --- a/tests/test6 +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Application Error - - - - - \ No newline at end of file