Compare commits
38 Commits
master
...
configurat
Author | SHA1 | Date | |
---|---|---|---|
|
08738673be | ||
|
1b001ab047 | ||
|
409c2aaea7 | ||
|
e8f56bd194 | ||
|
064eec8208 | ||
|
050f982608 | ||
|
d2d19127d3 | ||
|
691a83a479 | ||
|
ae9dc3e7db | ||
|
eeaaaac63e | ||
|
78b5bed9a0 | ||
|
1a8f732749 | ||
|
88c39fa2e4 | ||
|
9d801d64ea | ||
|
877fac0f90 | ||
|
98e0b586ca | ||
|
dd1ba72ce2 | ||
|
515d11f55a | ||
|
ba8fe0f479 | ||
|
f02f79ecbb | ||
|
d4e81cfe57 | ||
|
7030dc7c5b | ||
|
27977adc93 | ||
|
677f0cb1bb | ||
|
3ebc06196a | ||
|
fd5281bdd8 | ||
|
1f4044a707 | ||
|
08a2ad3c59 | ||
|
b06fb10f94 | ||
|
ce5f31ac47 | ||
|
0715259635 | ||
|
f4cc4d7c63 | ||
|
952b1017ab | ||
|
0914640d79 | ||
|
5ed383a0d1 | ||
|
3e2c29528a | ||
|
b2bbc11d44 | ||
|
06f4152008 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -14,3 +14,5 @@ libcjson.so.*
|
||||
libcjson_utils.so.*
|
||||
*.orig
|
||||
.vscode
|
||||
.idea
|
||||
cmake-build-debug
|
||||
|
@ -64,7 +64,6 @@ if (ENABLE_SANITIZERS)
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize=address
|
||||
-fsanitize=undefined
|
||||
-fsanitize=float-divide-by-zero
|
||||
-fsanitize=float-cast-overflow
|
||||
-fsanitize-address-use-after-scope
|
||||
-fsanitize=integer
|
||||
|
55
cJSON.h
55
cJSON.h
@ -78,6 +78,14 @@ typedef struct cJSON_Hooks
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* new style allocators with userdata (e.g. for pool allocators) */
|
||||
typedef struct cJSON_Allocators
|
||||
{
|
||||
void *(*allocate)(size_t size, void *userdata);
|
||||
void (*deallocate)(void *pointer, void *userdata);
|
||||
void *(*reallocate)(void *pointer, size_t size, void *userdata); /* optional */
|
||||
} cJSON_Allocators;
|
||||
|
||||
typedef int cJSON_bool;
|
||||
|
||||
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||
@ -132,27 +140,64 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
|
||||
/* returns the version of cJSON as a string */
|
||||
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
typedef void* cJSON_Context;
|
||||
/*
|
||||
* Create a context object that can be passed to several functions
|
||||
* to configure their behavior and/or take their output. It will be set to the default values
|
||||
* initially, they can be changed later using the builder pattern by passing it to functions
|
||||
* that change one setting.
|
||||
*
|
||||
* A cJSON_Context object is dynamically allocated and you are responsible to free it
|
||||
* after use.
|
||||
*
|
||||
* If allocators is a NULL pointer, malloc and free are used.
|
||||
*
|
||||
* allocator_userdata can be used to pass custom data to your allocator (e.g. for pool allocators).
|
||||
* */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_CreateContext(const cJSON_Allocators * const allocators, void *allocator_userdata);
|
||||
/* Create a copy of an existing context */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_DuplicateContext(const cJSON_Context, const cJSON_Allocators * const allocators, void *allocator_userdata);
|
||||
|
||||
/* The following functions work on a context in order to set and retrieve data: */
|
||||
/* Change the allocators of a cJSON_Context and reset the userdata */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_SetAllocators(cJSON_Context context, const cJSON_Allocators allocators);
|
||||
/* Change the allocator userdata attached to a cJSON_Context */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_SetUserdata(cJSON_Context context, void *userdata);
|
||||
/* Get the position relative to the JSON where the parser stopped, return 0 if invalid. */
|
||||
CJSON_PUBLIC(size_t) cJSON_GetParseEnd(cJSON_Context context);
|
||||
/* Set how many bytes should be initially allocated for printing */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_SetPrebufferSize(cJSON_Context context, const size_t buffer_size);
|
||||
typedef enum { CJSON_FORMAT_MINIFIED = 0, CJSON_FORMAT_DEFAULT = 1 } cJSON_Format;
|
||||
/* Change the format for printing */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_SetFormat(cJSON_Context context, cJSON_Format format);
|
||||
/* Change the case sensitivity */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_MakeCaseSensitive(cJSON_Context context, cJSON_bool case_sensitive);
|
||||
/* Change if data is allowed after the JSON */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_AllowDataAfterJson(cJSON_Context context, cJSON_bool allow_data_after_json);
|
||||
/* Change if cJSON_Duplicate copies recursively */
|
||||
CJSON_PUBLIC(cJSON_Context) cJSON_MakeDuplicateRecursive(cJSON_Context context, cJSON_bool recursive);
|
||||
|
||||
/* Supply malloc and free functions to cJSON globally */
|
||||
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_Parse(const char *json);
|
||||
/* 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_ParseWithOpts(const char *json, 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);
|
||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool format);
|
||||
/* 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 *c);
|
||||
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);
|
||||
|
@ -57,6 +57,7 @@ if(ENABLE_CJSON_TEST)
|
||||
compare_tests
|
||||
cjson_add
|
||||
readme_examples
|
||||
context_tests
|
||||
)
|
||||
|
||||
option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.")
|
||||
|
@ -33,11 +33,11 @@ void reset(cJSON *item) {
|
||||
}
|
||||
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
|
||||
{
|
||||
global_hooks.deallocate(item->valuestring);
|
||||
global_context.allocators.deallocate(item->valuestring, global_context.userdata);
|
||||
}
|
||||
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
|
||||
{
|
||||
global_hooks.deallocate(item->string);
|
||||
global_context.allocators.deallocate(item->string, global_context.userdata);
|
||||
}
|
||||
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
278
tests/context_tests.c
Normal file
278
tests/context_tests.c
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unity/examples/unity_config.h"
|
||||
#include "unity/src/unity.h"
|
||||
#include "common.h"
|
||||
|
||||
static void create_context_should_create_a_context(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
|
||||
context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(context->buffer_size, 256, "buffer_size has an incorrect value.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->format, "format has an incorrect value.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->case_sensitive, "case_sensitive has an incorrect value.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->allow_data_after_json, "allow_data_after_json has an incorrect value.");
|
||||
TEST_ASSERT_NULL_MESSAGE(context->userdata, "Userdata should be NULL");
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->duplicate_recursive, "Duplicating is not recursive.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(malloc_wrapper == context->allocators.allocate, "Wrong malloc.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(realloc_wrapper == context->allocators.reallocate, "Wrong realloc.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(free_wrapper == context->allocators.deallocate, "Wrong free.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void* custom_allocator(size_t size, void *userdata)
|
||||
{
|
||||
*((size_t*)userdata) = size;
|
||||
return malloc(size);
|
||||
}
|
||||
static void custom_deallocator(void *pointer, void *userdata)
|
||||
{
|
||||
*((size_t*)userdata) = (size_t)pointer;
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
static void create_context_should_take_custom_allocators(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
cJSON_Allocators allocators = {custom_allocator, custom_deallocator, NULL};
|
||||
size_t userdata = 0;
|
||||
|
||||
context = (internal_context*)cJSON_CreateContext(&allocators, &userdata);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(userdata, sizeof(internal_context), "custom allocator wasn't run properly.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(global_default_context.allocators.allocate == context->allocators.allocate, "Wrong allocator.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(global_default_context.allocators.deallocate == context->allocators.deallocate, "Wrong deallocator.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(global_default_context.allocators.reallocate == context->allocators.reallocate, "Wrong reallocator.");
|
||||
|
||||
custom_deallocator(context, &userdata);
|
||||
}
|
||||
|
||||
static void create_context_should_not_take_incomplete_allocators(void)
|
||||
{
|
||||
cJSON_Allocators allocators1 = {custom_allocator, NULL, NULL};
|
||||
cJSON_Allocators allocators2 = {NULL, custom_deallocator, NULL};
|
||||
size_t userdata = 0;
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_CreateContext(&allocators1, &userdata));
|
||||
TEST_ASSERT_NULL(cJSON_CreateContext(&allocators2, &userdata));
|
||||
}
|
||||
|
||||
static void duplicate_context_should_duplicate_a_context(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
|
||||
context = (internal_context*)cJSON_DuplicateContext(&global_context, NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY(&global_context, context, sizeof(internal_context));
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void duplicate_context_should_take_custom_allocators(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
cJSON_Allocators allocators = {custom_allocator, custom_deallocator, NULL};
|
||||
size_t userdata = 0;
|
||||
|
||||
context = (internal_context*)cJSON_DuplicateContext(&global_context, &allocators, &userdata);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(userdata, sizeof(internal_context), "custom allocator wasn't run properly");
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY(&global_context, context, sizeof(internal_context));
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void duplicate_context_should_not_take_incomplete_allocators(void)
|
||||
{
|
||||
cJSON_Allocators allocators1 = {custom_allocator, NULL, NULL};
|
||||
cJSON_Allocators allocators2 = {NULL, custom_deallocator, NULL};
|
||||
size_t userdata = 0;
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_DuplicateContext(&global_context, &allocators1, &userdata));
|
||||
TEST_ASSERT_NULL(cJSON_DuplicateContext(&global_context, &allocators2, &userdata));
|
||||
}
|
||||
|
||||
static void set_allocators_should_set_allocators(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
cJSON_Allocators allocators = {custom_allocator, custom_deallocator, NULL};
|
||||
size_t userdata = 0;
|
||||
|
||||
context = (internal_context*)cJSON_CreateContext(&allocators, &userdata);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_SetAllocators(context, allocators);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_TRUE_MESSAGE(custom_allocator == context->allocators.allocate, "Wrong allocator.");
|
||||
TEST_ASSERT_TRUE_MESSAGE(custom_deallocator == context->allocators.deallocate, "Wrong deallocator.");
|
||||
TEST_ASSERT_NULL_MESSAGE(context->allocators.reallocate, "Reallocator is not null");
|
||||
|
||||
custom_deallocator(context, &userdata);
|
||||
}
|
||||
|
||||
static void set_allocators_should_not_set_incomplete_allocators(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
cJSON_Allocators allocators1 = {custom_allocator, NULL, NULL};
|
||||
cJSON_Allocators allocators2 = {NULL, custom_deallocator, NULL};
|
||||
|
||||
context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_SetAllocators(context, allocators1));
|
||||
TEST_ASSERT_NULL(cJSON_SetAllocators(context, allocators2));
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void set_userdata_should_set_userdata(void)
|
||||
{
|
||||
internal_context *context = NULL;
|
||||
size_t userdata = 0;
|
||||
context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_SetUserdata(context, &userdata);
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->userdata == &userdata, "Userdata is incorrect.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void get_parse_end_should_get_the_parse_end(void)
|
||||
{
|
||||
internal_context context = global_default_context;
|
||||
context.end_position = 42;
|
||||
|
||||
TEST_ASSERT_EQUAL_MESSAGE(cJSON_GetParseEnd(&context), 42, "Failed to get parse end.");
|
||||
}
|
||||
|
||||
static void set_prebuffer_size_should_set_buffer_size(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_SetPrebufferSize(context, 1024);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_EQUAL_MESSAGE(context->buffer_size, 1024, "Didn't set the buffer size correctly.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void set_prebuffer_size_should_not_allow_empty_sizes(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_SetPrebufferSize(context, 0));
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void set_format_should_set_format(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_SetFormat(context, CJSON_FORMAT_MINIFIED);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_FALSE_MESSAGE(context->format, "Failed to set CJSON_FORMAT_MINIFIED.");
|
||||
|
||||
context = (internal_context*)cJSON_SetFormat(context, CJSON_FORMAT_DEFAULT);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_TRUE_MESSAGE(context->format, "Failed to set CJSON_FORMAT_DEFAULT.");
|
||||
|
||||
TEST_ASSERT_NULL_MESSAGE(cJSON_SetFormat(context, (cJSON_Format)3), "Failed to detect invalid format.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void make_case_sensitive_should_change_case_sensitivity(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_MakeCaseSensitive(context, false);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_FALSE_MESSAGE(context->case_sensitive, "Didn't set the case sensitivity correctly.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void allow_data_after_json_should_change_allow_data_after_json(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_AllowDataAfterJson(context, false);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
TEST_ASSERT_FALSE_MESSAGE(context->allow_data_after_json, "Didn't set allow_data_after_json property correctly.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void make_duplicate_recursive_should_make_duplicate_recursive(void)
|
||||
{
|
||||
internal_context *context = (internal_context*)cJSON_CreateContext(NULL, NULL);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
|
||||
context = (internal_context*)cJSON_MakeDuplicateRecursive(context, false);
|
||||
TEST_ASSERT_NOT_NULL(context);
|
||||
TEST_ASSERT_FALSE_MESSAGE(context->duplicate_recursive, "Duplicating is not set correctly.");
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(create_context_should_create_a_context);
|
||||
RUN_TEST(create_context_should_take_custom_allocators);
|
||||
RUN_TEST(create_context_should_not_take_incomplete_allocators);
|
||||
RUN_TEST(duplicate_context_should_duplicate_a_context);
|
||||
RUN_TEST(duplicate_context_should_take_custom_allocators);
|
||||
RUN_TEST(duplicate_context_should_not_take_incomplete_allocators);
|
||||
RUN_TEST(set_allocators_should_set_allocators);
|
||||
RUN_TEST(set_allocators_should_not_set_incomplete_allocators);
|
||||
RUN_TEST(set_userdata_should_set_userdata);
|
||||
RUN_TEST(get_parse_end_should_get_the_parse_end);
|
||||
RUN_TEST(set_prebuffer_size_should_set_buffer_size);
|
||||
RUN_TEST(set_prebuffer_size_should_not_allow_empty_sizes);
|
||||
RUN_TEST(set_format_should_set_format);
|
||||
RUN_TEST(make_case_sensitive_should_change_case_sensitivity);
|
||||
RUN_TEST(allow_data_after_json_should_change_allow_data_after_json);
|
||||
RUN_TEST(make_duplicate_recursive_should_make_duplicate_recursive);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
@ -10,8 +10,7 @@
|
||||
|
||||
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
|
||||
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
|
||||
@ -410,16 +409,18 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
|
||||
cJSON_Delete(item);
|
||||
}
|
||||
|
||||
static void *failing_realloc(void *pointer, size_t size)
|
||||
static void *failing_realloc(void *pointer, size_t size, void *userdata)
|
||||
{
|
||||
(void)size;
|
||||
(void)pointer;
|
||||
(void)userdata;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ensure_should_fail_on_failed_realloc(void)
|
||||
{
|
||||
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
|
||||
printbuffer buffer = {NULL, 10, 0, 0, false, {256, 0, NULL, {malloc_wrapper, free_wrapper, failing_realloc}, false, true, true, true} };
|
||||
buffer.context.userdata = &buffer;
|
||||
buffer.buffer = (unsigned char*)malloc(100);
|
||||
TEST_ASSERT_NOT_NULL(buffer.buffer);
|
||||
|
||||
@ -429,10 +430,10 @@ static void ensure_should_fail_on_failed_realloc(void)
|
||||
static void skip_utf8_bom_should_skip_bom(void)
|
||||
{
|
||||
const unsigned char string[] = "\xEF\xBB\xBF{}";
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = string;
|
||||
buffer.length = sizeof(string);
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
|
||||
TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
|
||||
@ -441,10 +442,10 @@ static void skip_utf8_bom_should_skip_bom(void)
|
||||
static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
|
||||
{
|
||||
const unsigned char string[] = " \xEF\xBB\xBF{}";
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = string;
|
||||
buffer.length = sizeof(string);
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
buffer.offset = 1;
|
||||
|
||||
TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
|
||||
@ -512,7 +513,7 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
|
||||
{
|
||||
cJSON *object = cJSON_CreateObject();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
|
||||
char *name = (char*)custom_strdup((const unsigned char*)"number", &global_context);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(object);
|
||||
TEST_ASSERT_NOT_NULL(number);
|
||||
@ -527,6 +528,24 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
|
||||
cJSON_Delete(object);
|
||||
}
|
||||
|
||||
static void is_nan_should_detect_nan(void)
|
||||
{
|
||||
double nan = 0.0/0.0;
|
||||
|
||||
TEST_ASSERT_TRUE(is_nan(nan));
|
||||
TEST_ASSERT_FALSE(is_nan(1));
|
||||
}
|
||||
|
||||
static void is_infinity_should_detect_infinity(void)
|
||||
{
|
||||
double negative_infinity = -1.0/0.0;
|
||||
double positive_infinity = 1.0/0.0;
|
||||
|
||||
TEST_ASSERT_TRUE(is_infinity(negative_infinity));
|
||||
TEST_ASSERT_TRUE(is_infinity(positive_infinity));
|
||||
TEST_ASSERT_FALSE(is_infinity(1));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
@ -550,6 +569,8 @@ int main(void)
|
||||
RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
|
||||
RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
|
||||
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
|
||||
RUN_TEST(is_nan_should_detect_nan);
|
||||
RUN_TEST(is_infinity_should_detect_infinity);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
@ -44,10 +44,10 @@ static void assert_is_array(cJSON *array_item)
|
||||
|
||||
static void assert_not_array(const char *json)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*)json;
|
||||
buffer.length = strlen(json) + sizeof("");
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_FALSE(parse_array(item, &buffer));
|
||||
assert_is_invalid(item);
|
||||
@ -55,10 +55,10 @@ static void assert_not_array(const char *json)
|
||||
|
||||
static void assert_parse_array(const char *json)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*)json;
|
||||
buffer.length = strlen(json) + sizeof("");
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE(parse_array(item, &buffer));
|
||||
assert_is_array(item);
|
||||
|
@ -45,7 +45,7 @@ static void assert_is_number(cJSON *number_item)
|
||||
|
||||
static void assert_parse_number(const char *string, int integer, double real)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*)string;
|
||||
buffer.length = strlen(string) + sizeof("");
|
||||
|
||||
|
@ -52,10 +52,10 @@ static void assert_is_child(cJSON *child_item, const char *name, int type)
|
||||
|
||||
static void assert_not_object(const char *json)
|
||||
{
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, default_context };
|
||||
parsebuffer.content = (const unsigned char*)json;
|
||||
parsebuffer.length = strlen(json) + sizeof("");
|
||||
parsebuffer.hooks = global_hooks;
|
||||
parsebuffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_FALSE(parse_object(item, &parsebuffer));
|
||||
assert_is_invalid(item);
|
||||
@ -64,10 +64,10 @@ static void assert_not_object(const char *json)
|
||||
|
||||
static void assert_parse_object(const char *json)
|
||||
{
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, default_context };
|
||||
parsebuffer.content = (const unsigned char*)json;
|
||||
parsebuffer.length = strlen(json) + sizeof("");
|
||||
parsebuffer.hooks = global_hooks;
|
||||
parsebuffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE(parse_object(item, &parsebuffer));
|
||||
assert_is_object(item);
|
||||
|
@ -45,24 +45,24 @@ static void assert_is_string(cJSON *string_item)
|
||||
|
||||
static void assert_parse_string(const char *string, const char *expected)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*)string;
|
||||
buffer.length = strlen(string) + sizeof("");
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(parse_string(item, &buffer), "Couldn't parse string.");
|
||||
assert_is_string(item);
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected.");
|
||||
global_hooks.deallocate(item->valuestring);
|
||||
global_context.allocators.deallocate(item->valuestring, global_context.userdata);
|
||||
item->valuestring = NULL;
|
||||
}
|
||||
|
||||
static void assert_not_parse_string(const char * const string)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*)string;
|
||||
buffer.length = strlen(string) + sizeof("");
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_FALSE_MESSAGE(parse_string(item, &buffer), "Malformed string should not be accepted.");
|
||||
assert_is_invalid(item);
|
||||
|
@ -43,10 +43,10 @@ static void assert_is_value(cJSON *value_item, int type)
|
||||
|
||||
static void assert_parse_value(const char *string, int type)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer buffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.content = (const unsigned char*) string;
|
||||
buffer.length = strlen(string) + sizeof("");
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE(parse_value(item, &buffer));
|
||||
assert_is_value(item, type);
|
||||
|
@ -31,36 +31,36 @@ static void assert_print_array(const char * const expected, const char * const i
|
||||
|
||||
cJSON item[1];
|
||||
|
||||
printbuffer formatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer formatted_buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, default_context };
|
||||
parsebuffer.content = (const unsigned char*)input;
|
||||
parsebuffer.length = strlen(input) + sizeof("");
|
||||
parsebuffer.hooks = global_hooks;
|
||||
parsebuffer.context = global_context;
|
||||
|
||||
/* buffer for formatted printing */
|
||||
formatted_buffer.buffer = printed_formatted;
|
||||
formatted_buffer.length = sizeof(printed_formatted);
|
||||
formatted_buffer.offset = 0;
|
||||
formatted_buffer.noalloc = true;
|
||||
formatted_buffer.hooks = global_hooks;
|
||||
formatted_buffer.context = global_context;
|
||||
|
||||
/* buffer for unformatted printing */
|
||||
unformatted_buffer.buffer = printed_unformatted;
|
||||
unformatted_buffer.length = sizeof(printed_unformatted);
|
||||
unformatted_buffer.offset = 0;
|
||||
unformatted_buffer.noalloc = true;
|
||||
unformatted_buffer.hooks = global_hooks;
|
||||
unformatted_buffer.context = global_context;
|
||||
|
||||
memset(item, 0, sizeof(item));
|
||||
TEST_ASSERT_TRUE_MESSAGE(parse_array(item, &parsebuffer), "Failed to parse array.");
|
||||
|
||||
unformatted_buffer.format = false;
|
||||
unformatted_buffer.context.format = false;
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_array(item, &unformatted_buffer), "Failed to print unformatted string.");
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted array is not correct.");
|
||||
|
||||
formatted_buffer.format = true;
|
||||
formatted_buffer.context.format = true;
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_array(item, &formatted_buffer), "Failed to print formatted string.");
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted array is not correct.");
|
||||
|
||||
|
@ -28,12 +28,12 @@ static void assert_print_number(const char *expected, double input)
|
||||
{
|
||||
unsigned char printed[1024];
|
||||
cJSON item[1];
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
buffer.buffer = printed;
|
||||
buffer.length = sizeof(printed);
|
||||
buffer.offset = 0;
|
||||
buffer.noalloc = true;
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
memset(item, 0, sizeof(item));
|
||||
cJSON_SetNumberValue(item, input);
|
||||
|
@ -31,37 +31,37 @@ static void assert_print_object(const char * const expected, const char * const
|
||||
|
||||
cJSON item[1];
|
||||
|
||||
printbuffer formatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer formatted_buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, default_context };
|
||||
|
||||
/* buffer for parsing */
|
||||
parsebuffer.content = (const unsigned char*)input;
|
||||
parsebuffer.length = strlen(input) + sizeof("");
|
||||
parsebuffer.hooks = global_hooks;
|
||||
parsebuffer.context = global_context;
|
||||
|
||||
/* buffer for formatted printing */
|
||||
formatted_buffer.buffer = printed_formatted;
|
||||
formatted_buffer.length = sizeof(printed_formatted);
|
||||
formatted_buffer.offset = 0;
|
||||
formatted_buffer.noalloc = true;
|
||||
formatted_buffer.hooks = global_hooks;
|
||||
formatted_buffer.context = global_context;
|
||||
|
||||
/* buffer for unformatted printing */
|
||||
unformatted_buffer.buffer = printed_unformatted;
|
||||
unformatted_buffer.length = sizeof(printed_unformatted);
|
||||
unformatted_buffer.offset = 0;
|
||||
unformatted_buffer.noalloc = true;
|
||||
unformatted_buffer.hooks = global_hooks;
|
||||
unformatted_buffer.context = global_context;
|
||||
|
||||
memset(item, 0, sizeof(item));
|
||||
TEST_ASSERT_TRUE_MESSAGE(parse_object(item, &parsebuffer), "Failed to parse object.");
|
||||
|
||||
unformatted_buffer.format = false;
|
||||
unformatted_buffer.context.format = false;
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_object(item, &unformatted_buffer), "Failed to print unformatted string.");
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted object is not correct.");
|
||||
|
||||
formatted_buffer.format = true;
|
||||
formatted_buffer.context.format = true;
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_object(item, &formatted_buffer), "Failed to print formatted string.");
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted ojbect is not correct.");
|
||||
|
||||
|
@ -27,12 +27,12 @@
|
||||
static void assert_print_string(const char *expected, const char *input)
|
||||
{
|
||||
unsigned char printed[1024];
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
buffer.buffer = printed;
|
||||
buffer.length = sizeof(printed);
|
||||
buffer.offset = 0;
|
||||
buffer.noalloc = true;
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_string_ptr((const unsigned char*)input, &buffer), "Failed to print string.");
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed, "The printed string isn't as expected.");
|
||||
|
@ -32,17 +32,18 @@ static void assert_print_value(const char *input)
|
||||
{
|
||||
unsigned char printed[1024];
|
||||
cJSON item[1];
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, default_context };
|
||||
parse_buffer parsebuffer = { 0, 0, 0, 0, default_context };
|
||||
buffer.buffer = printed;
|
||||
buffer.length = sizeof(printed);
|
||||
buffer.offset = 0;
|
||||
buffer.noalloc = true;
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.context = global_context;
|
||||
buffer.context.format = false;
|
||||
|
||||
parsebuffer.content = (const unsigned char*)input;
|
||||
parsebuffer.length = strlen(input) + sizeof("");
|
||||
parsebuffer.hooks = global_hooks;
|
||||
parsebuffer.context = global_context;
|
||||
|
||||
memset(item, 0, sizeof(item));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user