From 3772981b8f8ccecda4c67b2c59b812eae12b6282 Mon Sep 17 00:00:00 2001 From: eugene-admin Date: Wed, 1 Apr 2026 20:32:34 +0300 Subject: [PATCH] Initial commit for ESP32 --- .gitignore | 6 +- esp32/.keep | 0 esp32/CMakeLists.txt | 7 + esp32/components/cjson/CMakeLists.txt | 4 + esp32/components/cjson/cJSON.c | 3206 ++++++++++++++++++++++++ esp32/components/cjson/include/cJSON.h | 306 +++ esp32/main/CMakeLists.txt | 7 + esp32/main/Kconfig | 27 + esp32/main/main.cpp | 83 + esp32/main/protocol.cpp | 52 + esp32/main/protocol.h | 18 + iot_skeleton.tar.gz | Bin 0 -> 132382 bytes 12 files changed, 3715 insertions(+), 1 deletion(-) delete mode 100644 esp32/.keep create mode 100644 esp32/CMakeLists.txt create mode 100644 esp32/components/cjson/CMakeLists.txt create mode 100644 esp32/components/cjson/cJSON.c create mode 100644 esp32/components/cjson/include/cJSON.h create mode 100644 esp32/main/CMakeLists.txt create mode 100644 esp32/main/Kconfig create mode 100644 esp32/main/main.cpp create mode 100644 esp32/main/protocol.cpp create mode 100644 esp32/main/protocol.h create mode 100644 iot_skeleton.tar.gz diff --git a/.gitignore b/.gitignore index 7dd2672..533428d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,8 @@ dist/ # Python (если будет) __pycache__/ -*.pyc \ No newline at end of file +*.pyc + +# gitignore for ESP-IDF +sdkconfig +build/ \ No newline at end of file diff --git a/esp32/.keep b/esp32/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/esp32/CMakeLists.txt b/esp32/CMakeLists.txt new file mode 100644 index 0000000..5cc9441 --- /dev/null +++ b/esp32/CMakeLists.txt @@ -0,0 +1,7 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.22) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp32) + diff --git a/esp32/components/cjson/CMakeLists.txt b/esp32/components/cjson/CMakeLists.txt new file mode 100644 index 0000000..34ed424 --- /dev/null +++ b/esp32/components/cjson/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRCS "cJSON.c" + INCLUDE_DIRS "include" +) \ No newline at end of file diff --git a/esp32/components/cjson/cJSON.c b/esp32/components/cjson/cJSON.c new file mode 100644 index 0000000..88c2d95 --- /dev/null +++ b/esp32/components/cjson/cJSON.c @@ -0,0 +1,3206 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0/0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +{ + if (!cJSON_IsString(item)) + { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +{ + if (!cJSON_IsNumber(item)) + { + return (double) NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(CJSON_CDECL *allocate)(size_t size); + void (CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void * CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + item->string = NULL; + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char *number_c_string; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + size_t number_string_length = 0; + cJSON_bool has_decimal_point = false; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_string_length++; + break; + + case '.': + number_string_length++; + has_decimal_point = true; + break; + + default: + goto loop_end; + } + } +loop_end: + /* malloc for temporary buffer, add 1 for '\0' */ + number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1); + if (number_c_string == NULL) + { + return false; /* allocation failure */ + } + + memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length); + number_c_string[number_string_length] = '\0'; + + if (has_decimal_point) + { + for (i = 0; i < number_string_length; i++) + { + if (number_c_string[i] == '.') + { + /* replace '.' with the decimal point of the current locale (for strtod) */ + number_c_string[i] = decimal_point; + } + } + } + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (object == NULL) + { + return (double)NAN; + } + + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + size_t v1_len; + size_t v2_len; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + { + return NULL; + } + /* return NULL if the object is corrupted or valuestring is NULL */ + if (object->valuestring == NULL || valuestring == NULL) + { + return NULL; + } + + v1_len = strlen(valuestring); + v2_len = strlen(object->valuestring); + + if (v1_len <= v2_len) + { + /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */ + if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring )) + { + return NULL; + } + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); + if (copy == NULL) + { + return NULL; + } + if (object->valuestring != NULL) + { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) + { + return false; + } + + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) + { + length = sprintf((char*)number_buffer, "null"); + } + else if(d == (double)item->valueint) + { + length = sprintf((char*)number_buffer, "%d", item->valueint); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + output = NULL; + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) + { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) + { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + if (printed != NULL) + { + hooks->deallocate(printed); + printed = NULL; + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + p.buffer = NULL; + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((length < 0) || (buffer == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + if (output_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* nesting is too deep */ + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + if (cannot_access_at_index(input_buffer, 1)) + { + goto fail; /* nothing comes after the comma */ + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + if (output_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* nesting is too deep */ + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_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, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) + { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else + { + /* append to the end */ + if (child->prev) + { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL)) + { + return NULL; + } + + if (item != parent->child) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) + { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0 || newitem == NULL) + { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + return add_item_to_array(array, newitem); + } + + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (parent->child == item) + { + if (parent->child->prev == parent->child) + { + replacement->prev = replacement; + } + parent->child = replacement; + } + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) + { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if (replacement->string == NULL) + { + return false; + } + + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = boolean ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)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; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)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; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)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; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse); + +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + return cJSON_Duplicate_rec(item, 0, recurse ); +} + +cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + if(depth >= CJSON_CIRCULAR_LIMIT) { + goto fail; + } + newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) + { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if (((*input)[0] == '*') && ((*input)[1] == '/')) + { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) { + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) + { + return; + } + + while (json[0] != '\0') + { + switch (json[0]) + { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') + { + skip_oneline_comment(&json); + } + else if (json[1] == '*') + { + skip_multiline_comment(&json); + } else { + json++; + } + break; + + case '\"': + minify_string(&json, (char**)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); + object = NULL; +} diff --git a/esp32/components/cjson/include/cJSON.h b/esp32/components/cjson/include/cJSON.h new file mode 100644 index 0000000..cab5feb --- /dev/null +++ b/esp32/components/cjson/include/cJSON.h @@ -0,0 +1,306 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 19 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#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_Raw (1 << 7) /* raw json */ + +#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 and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + 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 +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* Limits the length of circular references can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_CIRCULAR_LIMIT +#define CJSON_CIRCULAR_LIMIT 10000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* 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 so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(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 */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) 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. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(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. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* 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. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool 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. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) ( \ + (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \ + (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \ + cJSON_Invalid\ +) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/esp32/main/CMakeLists.txt b/esp32/main/CMakeLists.txt new file mode 100644 index 0000000..417eac7 --- /dev/null +++ b/esp32/main/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + SRCS "main.cpp" "protocol.cpp" + INCLUDE_DIRS "." + REQUIRES nvs_flash esp_wifi esp_netif freertos log cjson +) +# добавляем кастомный Kconfig +set(COMPONENT_KCONFIG "Kconfig") \ No newline at end of file diff --git a/esp32/main/Kconfig b/esp32/main/Kconfig new file mode 100644 index 0000000..e5a803e --- /dev/null +++ b/esp32/main/Kconfig @@ -0,0 +1,27 @@ +menu "IoT Fish Config" + +config WIFI_SSID + string "Wi-Fi SSID" + default "your_wifi_ssid" + +config WIFI_PASS + string "Wi-Fi Password" + default "your_wifi_password" + +config SERVER_HOST + string "Backend Host" + default "192.168.1.100" + +config SERVER_PORT + int "Backend Port" + default 8080 + +config DEVICE_ID + string "Device ID" + default "esp32_fish_01" + +config PROTOCOL_VERSION + int "Protocol Version" + default 1 + +endmenu \ No newline at end of file diff --git a/esp32/main/main.cpp b/esp32/main/main.cpp new file mode 100644 index 0000000..2d024c6 --- /dev/null +++ b/esp32/main/main.cpp @@ -0,0 +1,83 @@ +#include "protocol.h" +#include "cJSON.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "sdkconfig.h" // Kconfig значения +#include + +static const char* TAG = "iot_fish"; + +// forward declarations +void init(); +void doTests(); +void finalize(); + +extern "C" void app_main(void) { + init(); + doTests(); + finalize(); +} + +// --- Реализация --- +void init() { + ESP_LOGI(TAG, "Initializing system..."); + + // NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + // TCP/IP stack + default event loop + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Wi-Fi init + esp_netif_create_default_wifi_sta(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + // Настройки Wi-Fi через Kconfig (menuconfig) + wifi_config_t wifi_config = {}; + strncpy((char*)wifi_config.sta.ssid, CONFIG_WIFI_SSID, sizeof(wifi_config.sta.ssid)); + strncpy((char*)wifi_config.sta.password, CONFIG_WIFI_PASS, sizeof(wifi_config.sta.password)); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "Wi-Fi started, connecting to %s...", CONFIG_WIFI_SSID); +} + +void doTests() { + ESP_LOGI(TAG, "Running protocol test..."); + + // пример ProtocolMessage + ProtocolMessage msg; + msg.v = 1; + msg.id = "msg-001"; + msg.type = "command"; + msg.ts = 1234567890; + msg.deviceId = "esp32-01"; + msg.payload = cJSON_CreateObject(); + cJSON_AddStringToObject(msg.payload, "command", "ping"); + + cJSON* json = protocol_message_to_json(&msg); + char* json_str = cJSON_Print(json); + ESP_LOGI(TAG, "ProtocolMessage JSON:\n%s", json_str); + + // Очистка + cJSON_Delete(json); + free(json_str); + cJSON_Delete(msg.payload); +} + +void finalize() { + ESP_LOGI(TAG, "Finalizing..."); + // здесь можно закрыть WebSocket, остановить таймеры, освободить память и т.д. +} \ No newline at end of file diff --git a/esp32/main/protocol.cpp b/esp32/main/protocol.cpp new file mode 100644 index 0000000..61ebe0d --- /dev/null +++ b/esp32/main/protocol.cpp @@ -0,0 +1,52 @@ +#include "protocol.h" +#include "cJSON.h" + +cJSON* protocol_message_to_json(const ProtocolMessage* msg) { + cJSON* root = cJSON_CreateObject(); + + cJSON_AddNumberToObject(root, "v", msg->v); + cJSON_AddStringToObject(root, "id", msg->id.c_str()); + cJSON_AddStringToObject(root, "type", msg->type.c_str()); + cJSON_AddNumberToObject(root, "ts", msg->ts); + cJSON_AddStringToObject(root, "deviceId", msg->deviceId.c_str()); + + cJSON* payload_obj = nullptr; + if (msg->payload) { + payload_obj = cJSON_Duplicate(msg->payload, 1); // deep copy + } else { + payload_obj = cJSON_CreateObject(); + } + cJSON_AddItemToObject(root, "payload", payload_obj); + + return root; +} + +ProtocolMessage protocol_message_from_json(const cJSON* root) { + ProtocolMessage msg; + + const cJSON* item = nullptr; + + item = cJSON_GetObjectItem(root, "v"); + if (item && cJSON_IsNumber(item)) msg.v = item->valueint; + + item = cJSON_GetObjectItem(root, "id"); + if (item && cJSON_IsString(item)) msg.id = item->valuestring; + + item = cJSON_GetObjectItem(root, "type"); + if (item && cJSON_IsString(item)) msg.type = item->valuestring; + + item = cJSON_GetObjectItem(root, "ts"); + if (item && cJSON_IsNumber(item)) msg.ts = item->valuedouble; // uint64_t + + item = cJSON_GetObjectItem(root, "deviceId"); + if (item && cJSON_IsString(item)) msg.deviceId = item->valuestring; + + item = cJSON_GetObjectItem(root, "payload"); + if (item && cJSON_IsObject(item)) { + msg.payload = cJSON_Duplicate(item, 1); // deep copy + } else { + msg.payload = cJSON_CreateObject(); + } + + return msg; +} \ No newline at end of file diff --git a/esp32/main/protocol.h b/esp32/main/protocol.h new file mode 100644 index 0000000..4d91d40 --- /dev/null +++ b/esp32/main/protocol.h @@ -0,0 +1,18 @@ +#pragma once +#include "cJSON.h" +#include + +struct ProtocolMessage { + int v; + std::string id; + std::string type; + uint64_t ts; + std::string deviceId; // C++ строка + cJSON* payload; +}; + +// Создание JSON из структуры +cJSON* protocol_message_to_json(const ProtocolMessage *msg); + +// Разбор JSON в структуру +int protocol_json_to_message(const char *json_str, ProtocolMessage *msg); \ No newline at end of file diff --git a/iot_skeleton.tar.gz b/iot_skeleton.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b186a70beae147bbb303adcf9bf9f0ba33f719f9 GIT binary patch literal 132382 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 literal 0 HcmV?d00001