summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid McCann <mccannd@uk.ibm.com>2021-05-13 06:34:10 +0100
committerDavid McCann <mccannd@uk.ibm.com>2021-05-13 06:34:10 +0100
commit00098efc966ee4551255ab5841d83e2e5345a3ad (patch)
treef26ead399be5306a7a19c7ca39e02e6ecaf06ce8
parent9b53c92ea398c479f59f77b2cbd24d2ccf1fc29a (diff)
parentcd7109f767a6d9f20caa9d10fbf4eab9c5262e7a (diff)
downloadjson-c-00098efc966ee4551255ab5841d83e2e5345a3ad.tar.gz
Merge branch 'json-c:master' into master
-rw-r--r--.gitignore3
-rw-r--r--AUTHORS11
-rw-r--r--CMakeLists.txt142
-rw-r--r--ChangeLog73
-rw-r--r--README.md65
-rw-r--r--RELEASE_CHECKLIST.txt37
-rw-r--r--apps/json_parse.c3
-rw-r--r--arraylist.c62
-rw-r--r--arraylist.h25
-rwxr-xr-xcmake-configure4
-rw-r--r--cmake/config.h.in18
-rw-r--r--config.h.win32207
-rw-r--r--debug.h2
-rw-r--r--doc/CMakeLists.txt16
-rw-r--r--doc/Doxyfile.in (renamed from Doxyfile)24
-rwxr-xr-xdoc/fixup_markdown.sh6
-rw-r--r--issues_closed_for_0.13.md504
-rw-r--r--issues_closed_for_0.14.md372
-rw-r--r--issues_closed_for_0.15.md85
-rw-r--r--json-c.sym170
-rw-r--r--json.h.cmakein (renamed from json.h)2
-rw-r--r--json_c_version.h6
-rw-r--r--json_object.c620
-rw-r--r--json_object.h101
-rw-r--r--json_object_iterator.c1
-rw-r--r--json_object_private.h88
-rw-r--r--json_tokener.c450
-rw-r--r--json_tokener.h52
-rw-r--r--json_types.h2
-rw-r--r--json_util.c3
-rw-r--r--json_util.h3
-rw-r--r--linkhash.h6
-rw-r--r--printbuf.h2
-rw-r--r--random_seed.c148
-rw-r--r--strerror_override.c8
-rw-r--r--tests/CMakeLists.txt56
-rw-r--r--tests/test1.c26
-rwxr-xr-xtests/test_basic.test2
-rw-r--r--tests/test_cast.c10
-rw-r--r--tests/test_cast.expected35
-rw-r--r--tests/test_deep_copy.c2
-rw-r--r--tests/test_double_serializer.c1
-rw-r--r--tests/test_json_pointer.c5
-rw-r--r--tests/test_parse.c232
-rw-r--r--tests/test_parse.expected71
-rw-r--r--tests/test_set_value.c10
-rw-r--r--tests/test_strerror.c11
-rw-r--r--tests/test_strerror.expected2
l---------tests/test_strerror.test1
-rw-r--r--tests/test_util_file.c2
50 files changed, 2427 insertions, 1360 deletions
diff --git a/.gitignore b/.gitignore
index 958ace3..8d2cb62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@
# It's not good practice to build directly in the source tree
# but ignore cmake auto-generated files anyway:
/json_config.h
+/json.h
/config.h
/json-c.pc
/Makefile
@@ -83,7 +84,7 @@
/Testing/
# ...and build artifacts.
-/doc
+/doc/html
/libjson-c.a
/libjson-c.so
/libjson-c.so.*
diff --git a/AUTHORS b/AUTHORS
index fce4dd8..33ff568 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,8 +7,13 @@ Christopher Head <chead@chead.ca>
Chris Wolfe <chriswwolfe@gmail.com>
C. Watford (christopher.watford@gmail.com)
Darjan Krijan <darjan_krijan@gmx.de>
+David McCann <mccannd@uk.ibm.com>
+dota17 <chenguopingdota@163.com>
+Eric Haszlakiewicz <erh+git@nimenees.com>
Eric Hawicz <erh+git@nimenees.com>
+Gianluigi Tiesi <sherpya@netfarm.it>
grdowns <grdowns@microsoft.com>
+hofnarr <hofnarr@hofnarr.fi>
Ivan Romanov <drizt@land.ru>
Jaap Keuter <jaap.keuter@xs4all.nl>
janczer <menshikov.ivn@gmail.com>
@@ -18,13 +23,19 @@ Jonathan Wiens <j.wiens@teles.com>
Jose Bollo <jose.bollo@iot.bzh>
Keith Holman <keith.holman@windriver.com>
Liang, Gao <liang.gao@intel.com>
+Marc <34656315+MarcT512@users.noreply.github.com>
max <mpano91@gmail.com>
+Micah Snyder <micasnyd@cisco.com>
Michael Clark <michael@metaparadigm.com>
myd7349 <myd7349@gmail.com>
+Pascal Cuoq <cuoq@trust-in-soft.com>
Pierce Lopez <pierce.lopez@gmail.com>
Po-Chuan Hsieh <sunpoet@sunpoet.net>
Ramiro Polla <ramiro.polla@gmail.com>
Rikard Falkeborn <rikard.falkeborn@gmail.com>
Robert <roby_p97@yahoo.com>
Rubasri Kalidas <rubasri.kalidas@intel.com>
+Simon McVittie <smcv@collabora.com>
+Tobias Stoeckmann <tobias@stoeckmann.org>
+Tudor Brindus <me@tbrindus.ca>
Unmanned Player <36690541+unmanned-player@users.noreply.github.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 254d324..e870cca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,15 @@ if(POLICY CMP0048)
endif()
# JSON-C library is C only project.
-project(json-c LANGUAGES C VERSION 0.14.99)
+if (CMAKE_VERSION VERSION_LESS 3.0)
+ project(json-c)
+ set(PROJECT_VERSION_MAJOR "0")
+ set(PROJECT_VERSION_MINOR "15")
+ set(PROJECT_VERSION_PATCH "99")
+ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+else()
+ project(json-c LANGUAGES C VERSION 0.15.99)
+endif()
# If we've got 3.0 then it's good, let's provide support. Otherwise, leave it be.
if(POLICY CMP0038)
@@ -71,6 +79,10 @@ include(CMakePackageConfigHelpers)
option(BUILD_SHARED_LIBS "Default to building shared libraries" ON)
option(BUILD_STATIC_LIBS "Default to building static libraries" ON)
+if (BUILD_SHARED_LIBS)
+ add_definitions(-D JSON_C_DLL)
+endif()
+
# Generate a release merge and test it to verify the correctness of republishing the package.
ADD_CUSTOM_TARGET(distcheck
COMMAND make package_source
@@ -83,10 +95,15 @@ COMMAND make package_source
)
# Enable or disable features. By default, all features are turned off.
-option(ENABLE_RDRAND "Enable RDRAND Hardware RNG Hash Seed" OFF)
-option(ENABLE_THREADING "Enable partial threading support." OFF)
-option(DISABLE_WERROR "Avoid treating compiler warnings as fatal errors" OFF)
-option(DISABLE_BSYMBOLIC "Avoid linking with -Bsymbolic-function" OFF)
+option(DISABLE_BSYMBOLIC "Avoid linking with -Bsymbolic-function." OFF)
+option(DISABLE_THREAD_LOCAL_STORAGE "Disable using Thread-Local Storage (HAVE___THREAD)." OFF)
+option(DISABLE_WERROR "Avoid treating compiler warnings as fatal errors." OFF)
+option(ENABLE_RDRAND "Enable RDRAND Hardware RNG Hash Seed." OFF)
+option(ENABLE_THREADING "Enable partial threading support." OFF)
+option(OVERRIDE_GET_RANDOM_SEED "Override json_c_get_random_seed() with custom code." OFF)
+option(DISABLE_EXTRA_LIBS "Avoid linking against extra libraries, such as libbsd." OFF)
+option(DISABLE_JSON_POINTER "Disable JSON pointer (RFC6901) support." OFF)
+
if (UNIX OR MINGW OR CYGWIN)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
@@ -101,6 +118,14 @@ if (MSVC)
list(APPEND CMAKE_REQUIRED_FLAGS /wd4996)
endif()
+if (NOT DISABLE_STATIC_FPIC)
+ # Use '-fPIC'/'-fPIE' option.
+ # This will allow other libraries to statically link in libjson-c.a
+ # which in turn prevents crashes in downstream apps that may use
+ # a different JSON library with identical symbol names.
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+endif()
+
check_include_file("fcntl.h" HAVE_FCNTL_H)
check_include_file("inttypes.h" HAVE_INTTYPES_H)
check_include_file(stdarg.h HAVE_STDARG_H)
@@ -125,6 +150,7 @@ check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stdlib.h HAVE_STDLIB_H)
check_include_file(sys/cdefs.h HAVE_SYS_CDEFS_H)
check_include_file(sys/param.h HAVE_SYS_PARAM_H)
+check_include_file(sys/random.h HAVE_SYS_RANDOM_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(xlocale.h HAVE_XLOCALE_H)
@@ -150,6 +176,17 @@ check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_symbol_exists(vprintf "stdio.h" HAVE_VPRINTF)
+check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM)
+if (NOT HAVE_ARC4RANDOM AND DISABLE_EXTRA_LIBS STREQUAL "OFF")
+ check_include_file(bsd/stdlib.h HAVE_BSD_STDLIB_H)
+ if (HAVE_BSD_STDLIB_H)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "-lbsd")
+ link_libraries(bsd)
+ unset(HAVE_ARC4RANDOM CACHE)
+ check_symbol_exists(arc4random "bsd/stdlib.h" HAVE_ARC4RANDOM)
+ endif()
+endif()
+
if (HAVE_FCNTL_H)
check_symbol_exists(open "fcntl.h" HAVE_OPEN)
endif()
@@ -171,6 +208,9 @@ endif()
if (HAVE_SYSLOG_H)
check_symbol_exists(vsyslog "syslog.h" HAVE_VSYSLOG)
endif()
+if (HAVE_SYS_RANDOM_H)
+ check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM)
+endif()
if (HAVE_SYS_RESOURCE_H)
check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE)
endif()
@@ -204,27 +244,35 @@ check_type_size(int64_t SIZEOF_INT64_T)
check_type_size(long SIZEOF_LONG)
check_type_size("long long" SIZEOF_LONG_LONG)
check_type_size("size_t" SIZEOF_SIZE_T)
+if (MSVC)
+list(APPEND CMAKE_EXTRA_INCLUDE_FILES BaseTsd.h)
+check_type_size("SSIZE_T" SIZEOF_SSIZE_T)
+else()
+check_type_size("ssize_t" SIZEOF_SSIZE_T)
+endif()
check_c_source_compiles(
-[=[
+"
extern void json_object_get();
-__asm__(".section .gnu.json_object_get\\n\\t.ascii \\"Please link against libjson-c instead of libjson\\"\\n\\t.text");
+__asm__(\".section .gnu.json_object_get\\n\\t.ascii \\\"Please link against libjson-c instead of libjson\\\"\\n\\t.text\");
int main(int c, char *v) { return 0;}
-]=]
+"
HAS_GNU_WARNING_LONG)
check_c_source_compiles(
"int main() { int i, x = 0; i = __sync_add_and_fetch(&x,1); return x; }"
HAVE_ATOMIC_BUILTINS)
-check_c_source_compiles(
- "__thread int x = 0; int main() { return 0; }"
- HAVE___THREAD)
+if (NOT DISABLE_THREAD_LOCAL_STORAGE)
+ check_c_source_compiles(
+ "__thread int x = 0; int main() { return 0; }"
+ HAVE___THREAD)
-if (HAVE___THREAD)
- set(SPEC___THREAD __thread)
-elseif (MSVC)
- set(SPEC___THREAD __declspec(thread))
+ if (HAVE___THREAD)
+ set(SPEC___THREAD __thread)
+ elseif (MSVC)
+ set(SPEC___THREAD __declspec(thread))
+ endif()
endif()
# Hardware random number is not available on Windows? Says, config.h.win32. Best to preserve compatibility.
@@ -234,11 +282,11 @@ endif()
# Once we've done basic symbol/header searches let's add them in.
configure_file(${PROJECT_SOURCE_DIR}/cmake/config.h.in ${PROJECT_BINARY_DIR}/config.h)
-message(STATUS "Written ${PROJECT_BINARY_DIR}/config.h")
+message(STATUS "Wrote ${PROJECT_BINARY_DIR}/config.h")
configure_file(${PROJECT_SOURCE_DIR}/cmake/json_config.h.in ${PROJECT_BINARY_DIR}/json_config.h)
-message(STATUS "Written ${PROJECT_BINARY_DIR}/json_config.h")
+message(STATUS "Wrote ${PROJECT_BINARY_DIR}/json_config.h")
-if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
+if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
if ("${DISABLE_WERROR}" STREQUAL "OFF")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
@@ -267,7 +315,7 @@ endif()
if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
check_c_source_compiles(
- [=[
+ "
/* uClibc toolchains without threading barf when _REENTRANT is defined */
#define _REENTRANT 1
#include <sys/types.h>
@@ -275,7 +323,7 @@ if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
{
return 0;
}
- ]=]
+ "
REENTRANT_WORKS
)
if (REENTRANT_WORKS)
@@ -286,12 +334,12 @@ if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
# Others may not support it, too.
list(APPEND CMAKE_REQUIRED_LIBRARIES "-Wl,-Bsymbolic-functions")
check_c_source_compiles(
- [=[
+ "
int main (void)
{
return 0;
}
- ]=]
+ "
BSYMBOLIC_WORKS
)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,-Bsymbolic-functions")
@@ -300,6 +348,22 @@ if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
# XXX need cmake>=3.13 for this:
#add_link_options("-Wl,-Bsymbolic-functions")
endif()
+
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym" "TEST { global: *; };")
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
+ check_c_source_compiles(
+ "
+ int main (void)
+ {
+ return 0;
+ }
+ "
+ VERSION_SCRIPT_WORKS
+ )
+ list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
+ if (VERSION_SCRIPT_WORKS)
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/json-c.sym")
+ endif()
endif()
if ($ENV{VALGRIND})
@@ -311,14 +375,13 @@ set(JSON_C_PUBLIC_HEADERS
# Note: config.h is _not_ included here
${PROJECT_BINARY_DIR}/json_config.h
- ${PROJECT_SOURCE_DIR}/json.h
+ ${PROJECT_BINARY_DIR}/json.h
${PROJECT_SOURCE_DIR}/arraylist.h
${PROJECT_SOURCE_DIR}/debug.h
${PROJECT_SOURCE_DIR}/json_c_version.h
${PROJECT_SOURCE_DIR}/json_inttypes.h
${PROJECT_SOURCE_DIR}/json_object.h
${PROJECT_SOURCE_DIR}/json_object_iterator.h
- ${PROJECT_SOURCE_DIR}/json_pointer.h
${PROJECT_SOURCE_DIR}/json_tokener.h
${PROJECT_SOURCE_DIR}/json_types.h
${PROJECT_SOURCE_DIR}/json_util.h
@@ -345,7 +408,6 @@ set(JSON_C_SOURCES
${PROJECT_SOURCE_DIR}/json_c_version.c
${PROJECT_SOURCE_DIR}/json_object.c
${PROJECT_SOURCE_DIR}/json_object_iterator.c
- ${PROJECT_SOURCE_DIR}/json_pointer.c
${PROJECT_SOURCE_DIR}/json_tokener.c
${PROJECT_SOURCE_DIR}/json_util.c
${PROJECT_SOURCE_DIR}/json_visit.c
@@ -355,26 +417,20 @@ set(JSON_C_SOURCES
${PROJECT_SOURCE_DIR}/strerror_override.c
)
-include_directories(${PROJECT_SOURCE_DIR})
-include_directories(${PROJECT_BINARY_DIR})
-
-# generate doxygen documentation for json-c API
-
-find_package(Doxygen)
-option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation(requires Doxygen)" ${DOXYGEN_FOUND})
-
-if (DOXYGEN_FOUND)
+if (NOT DISABLE_JSON_POINTER)
+ set(JSON_C_PUBLIC_HEADERS ${JSON_C_PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/json_pointer.h)
+ set(JSON_C_SOURCES ${JSON_C_SOURCES} ${PROJECT_SOURCE_DIR}/json_pointer.c)
+ set(JSON_H_JSON_POINTER "#include \"json_pointer.h\"")
+else()
+ set(JSON_H_JSON_POINTER "")
+endif()
- add_custom_target(doc
- COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_SOURCE_DIR}/Doxyfile
- WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
+configure_file(json.h.cmakein ${PROJECT_BINARY_DIR}/json.h @ONLY)
- # request to configure the file
- configure_file(Doxyfile Doxyfile)
+include_directories(${PROJECT_SOURCE_DIR})
+include_directories(${PROJECT_BINARY_DIR})
-else (DOXYGEN_FOUND)
- message("Warning: doxygen not found, the 'doc' target will not be included")
-endif(DOXYGEN_FOUND)
+add_subdirectory(doc)
# uninstall
add_custom_target(uninstall
@@ -390,7 +446,7 @@ add_library(${PROJECT_NAME}
${JSON_C_HEADERS}
)
set_target_properties(${PROJECT_NAME} PROPERTIES
- VERSION 5.0.0
+ VERSION 5.1.0
SOVERSION 5)
list(APPEND CMAKE_TARGETS ${PROJECT_NAME})
# If json-c is used as subroject it set to target correct interface -I flags and allow
diff --git a/ChangeLog b/ChangeLog
index 8a58d19..b63a443 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,17 +1,76 @@
-Next Release 0.15
+Next Release 0.16
=====================
+...no changes yet...
+
+
+***
+
+0.15 (up to commit 870965e, 2020/07/26)
+========================================
+
Deprecated and removed features:
--------------------------------
-...none yet...
+* Deprecate `array_list_new()` in favor of `array_list_new2()`
+* Remove the THIS_FUNCTION_IS_DEPRECATED define.
+* Remove config.h.win32
+
+New features
+------------
+* Add a `JSON_TOKENER_ALLOW_TRAILING_CHARS` flag to allow multiple objects
+ to be parsed even when `JSON_TOKENER_STRICT` is set.
+* Add `json_object_new_array_ext(int)` and `array_list_new_2(int)` to allow
+ arrays to be allocated with the exact size needed, when known.
+* Add `json_object_array_shrink()` (and `array_list_shrink()`) and use it in
+ json_tokener to minimize the amount of memory used.
+* Add a json_parse binary, for use in testing changes (not installed, but
+ available in the apps directory).
+
+Build changes
+-------------
+* #639/#621 - Add symbol versions to all exported symbols
+* #508/#634 - Always enable -fPIC to allow use of the json-c static library in
+ other libraries
+* Build both static and shared libraries at the same time.
+* #626 - Restore compatibility with cmake 2.8
+* #471 - Always create directories with mode 0755, regardless of umask.
+* #606/#604 - Improve support for OSes like AIX and IBM i, as well as for
+ MINGW32 and old versions of MSVC
+* #451/#617 - Add a DISABLE_THREAD_LOCAL_STORAGE cmake option to disable
+ the use of thread-local storage.
+
+Significant changes and bug fixes
+---------------------------------
+* Split the internal json_object structure into several sub-types, one for
+ each json_type (json_object_object, json_object_string, etc...).
+ This improves memory usage and speed, with the benchmark under
+ bench/ report 5.8% faster test time and 6%(max RSS)-12%(peak heap)
+ less memory usage.
+ Memory used just for json_object structures decreased 27%, so use cases
+ with fewer arrays and/or strings would benefit more.
+* Minimize memory usage in array handling in json_tokener by shrinking
+ arrays to the exact number of elements parsed. On bench/ benchmark:
+ 9% faster test time, 39%(max RSS)-50%(peak heap) less memory usage.
+ Add json_object_array_shrink() and array_list_shrink() functions.
+* #616 - Parsing of surrogate pairs in unicode escapes now properly handles
+ incremental parsing.
+* Fix incremental parsing of numbers, especially those with exponents, e.g.
+ so parsing "[0", "e+", "-]" now properly returns an error.
+ Strict mode now rejects missing exponents ("0e").
+* Successfully return number objects at the top level even when they are
+ followed by a "-", "." or "e". This makes parsing things like "123-45"
+ behave consistently with things like "123xyz".
Other changes
---------------
-* Add a json_parse binary, for use in testing changes (not installed).
-* Issue #471: always create directories with mode 0755, regardless of umask.
-* Added a JSON_TOKENER_ALLOW_TRAILING_CHARS flag to allow multiple objects
- to be parsed even when JSON_TOKENER_STRICT is set.
+-------------
+* #589 - Detect broken RDRAND during initialization; also, fix segfault
+ in the CPUID check.
+* #592 - Fix integer overflows to prevert out of bounds write on large input.
+* Protect against division by zero in linkhash, when creaed with zero size.
+* #602 - Fix json_parse_uint64() internal error checking, leaving the retval
+ untouched in more failure cases.
+* #614 - Prevent truncation when custom double formatters insert extra \0's
***
diff --git a/README.md b/README.md
index f5a7ee3..d2373fc 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+\mainpage
+
`json-c`
========
@@ -35,7 +37,7 @@ Home page for json-c: https://github.com/json-c/json-c/wiki
- `gcc`, `clang`, or another C compiler
- - cmake>=2.8, >=3.16 recommended
+ - `cmake>=2.8`, `>=3.16` recommended
To generate docs you'll also need:
- `doxygen>=1.8.13`
@@ -78,7 +80,7 @@ $ make install
### Generating documentation with Doxygen:
-The libray documentation can be generated directly from the source codes using Doxygen tool:
+The library documentation can be generated directly from the source code using Doxygen tool:
```sh
# in build directory
@@ -93,16 +95,19 @@ CMake Options <a name="CMake"></a>
The json-c library is built with [CMake](https://cmake.org/cmake-tutorial/),
which can take a few options.
-Variable | Type | Description
----------------------|--------|--------------
-CMAKE_INSTALL_PREFIX | String | The install location.
-CMAKE_BUILD_TYPE | String | Defaults to "debug"
-BUILD_SHARED_LIBS | Bool | The default build generates a dynamic (dll/so) library. Set this to OFF to create a static library only.
-BUILD_STATIC_LIBS | Bool | The default build generates a static (lib/a) library. Set this to OFF to create a shared library only.
-ENABLE_RDRAND | Bool | Enable RDRAND Hardware RNG Hash Seed
-ENABLE_THREADING | Bool | Enable partial threading support
-DISABLE_WERROR | Bool | Disable use of -Werror
-DISABLE_BSYMBOLIC | Bool | Disable use of -Bsymbolic-functions
+Variable | Type | Description
+-----------------------------|--------|--------------
+CMAKE_INSTALL_PREFIX | String | The install location.
+CMAKE_BUILD_TYPE | String | Defaults to "debug".
+BUILD_SHARED_LIBS | Bool | The default build generates a dynamic (dll/so) library. Set this to OFF to create a static library only.
+BUILD_STATIC_LIBS | Bool | The default build generates a static (lib/a) library. Set this to OFF to create a shared library only.
+DISABLE_STATIC_FPIC | Bool | The default builds position independent code. Set this to OFF to create a shared library only.
+DISABLE_BSYMBOLIC | Bool | Disable use of -Bsymbolic-functions.
+DISABLE_THREAD_LOCAL_STORAGE | Bool | Disable use of Thread-Local Storage (HAVE___THREAD).
+DISABLE_WERROR | Bool | Disable use of -Werror.
+ENABLE_RDRAND | Bool | Enable RDRAND Hardware RNG Hash Seed.
+ENABLE_THREADING | Bool | Enable partial threading support.
+OVERRIDE_GET_RANDOM_SEED | String | A block of code to use instead of the default implementation of json_c_get_random_seed(), e.g. on embedded platforms where not even the fallback to time() works. Must be a single line.
Pass these options as `-D` on CMake's command-line.
@@ -234,8 +239,38 @@ following more specific header files:
* json_tokener.h - Methods for parsing and serializing json-c object trees.
* json_pointer.h - JSON Pointer (RFC 6901) implementation for retrieving
objects from a json-c object tree.
-* json_object_iterator.h - Methods for iterating over single json_object instances.
+* json_object_iterator.h - Methods for iterating over single json_object instances. (See also `json_object_object_foreach()` in json_object.h)
* json_visit.h - Methods for walking a tree of json-c objects.
-* json_util.h - Miscelleanous utility functions.
+* json_util.h - Miscellaneous utility functions.
+
+For a full list of headers see [files.html](http://json-c.github.io/json-c/json-c-current-release/doc/html/files.html)
+
+The primary type in json-c is json_object. It describes a reference counted
+tree of json objects which are created by either parsing text with a
+json_tokener (i.e. `json_tokener_parse_ex()`), or by creating
+(with `json_object_new_object()`, `json_object_new_int()`, etc...) and adding
+(with `json_object_object_add()`, `json_object_array_add()`, etc...) them
+individually.
+Typically, every object in the tree will have one reference, from its parent.
+When you are done with the tree of objects, you call json_object_put() on just
+the root object to free it, which recurses down through any child objects
+calling json_object_put() on each one of those in turn.
+
+You can get a reference to a single child
+(`json_object_object_get()` or `json_object_array_get_idx()`)
+and use that object as long as its parent is valid.
+If you need a child object to live longer than its parent, you can
+increment the child's refcount (`json_object_get()`) to allow it to survive
+the parent being freed or it being removed from its parent
+(`json_object_object_del()` or `json_object_array_del_idx()`)
+
+When parsing text, the json_tokener object is independent from the json_object
+that it returns. It can be allocated (`json_tokener_new()`)
+used one or multiple times (`json_tokener_parse_ex()`, and
+freed (`json_tokener_free()`) while the json_object objects live on.
+
+A json_object tree can be serialized back into a string with
+`json_object_to_json_string_ext()`. The string that is returned
+is only valid until the next "to_json_string" call on that same object.
+Also, it is freed when the json_object is freed.
-For a full list of headers see [files.html](http://json-c.github.io/json-c/json-c-0.13.1/doc/html/files.html)
diff --git a/RELEASE_CHECKLIST.txt b/RELEASE_CHECKLIST.txt
index 94f5307..9f6b6db 100644
--- a/RELEASE_CHECKLIST.txt
+++ b/RELEASE_CHECKLIST.txt
@@ -18,7 +18,15 @@
* https://github.com/lvc/abi-compliance-checker
* If the new release is not backwards compatible, then this is a MAJOR release.
* Mention removed features in ChangeLog
+ * Consider re-adding backwards compatible support, through symbol
+ aliases and appropriate entries in json-c.sym
+ * Be sure any new symbols are listed in json-c.sym as part of
+ the _new_ release version.
* Update the AUTHORS file
+
+ git log -r 31ab57ca..HEAD | grep Author: | sed -e's/Author: //' ; cat AUTHORS ) | sort -u > A1
+ mv A1 AUTHORS
+
* Exclude mentioning changes that have already been included in a point
release of the previous release branch.
@@ -31,14 +39,14 @@
## Release creation
Start creating the new release:
- release=0.15
+ release=0.16
git clone https://github.com/json-c/json-c json-c-${release}
mkdir distcheck
cd distcheck
# Note, the build directory *must* be entirely separate from
# the source tree for distcheck to work properly.
- cmake ../json-c-${release}
+ cmake -DCMAKE_BUILD_TYPE=Release ../json-c-${release}
make distcheck
cd ..
@@ -52,9 +60,7 @@ Make any fixes/changes *before* branching.
Using ${release}:
Update the version in json_c_version.h
- Update the version in Doxyfile (PROJECT_NUMBER)
Update the version in CMakeLists.txt (VERSION in the project(...) line)
- Update the version in config.h.win32 (several places)
Update the set_target_properties() line in CmakeLists.txt to set the shared
library version. Generally, unless we're doing a major release, change:
@@ -64,13 +70,20 @@ to
git commit -a -m "Bump version to ${release}"
+If we're doing a major release (SONAME bump), also bump the version
+ of ALL symbols in json-c.sym.
+ See explanation at https://github.com/json-c/json-c/issues/621
+ More info at: https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
+
------------
Generate the doxygen documentation:
- doxygen
+ (cd ../distcheck && make doc)
+ cp -r -p ../distcheck/doc/{html,Doxyfile} doc/.
+ rm doc/Doxyfile # Remove generated file w/ hardcoded paths
git add -f doc
- git commit doc
+ git commit doc -m "Generate docs for the ${release} release"
------------
@@ -80,7 +93,7 @@ Create the release tarballs:
echo .git > excludes
tar -czf json-c-${release}.tar.gz -X excludes json-c-${release}
- echo doc >> excludes
+ echo 'doc/*' >> excludes
tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release}
------------
@@ -98,7 +111,7 @@ Tag the branch:
Go to Amazon S3 service at:
https://console.aws.amazon.com/s3/
-Upload the two tarballs in the json-c_releases folder.
+Upload the two tarballs in the json-c_releases/releases folder.
When uploading, use "Standard" storage class, and make the uploaded files publicly accessible.
Logout of Amazon S3, and verify that the files are visible.
@@ -114,15 +127,15 @@ Add new section to ChangeLog for ${release}+1
Use ${release}.99 to indicate a version "newer" than anything on the branch:
Update the version in json_c_version.h
- Update the version in Doxyfile
Update the version in CMakeLists.txt
- Update the version in config.h.win32
Update RELEASE_CHECKLIST.txt, set release=${release}+1
+Add a new empty section to the json-c.sym file, for ${release}+1
+
Update the set_target_properties() line in CmakeLists.txt to match the release branch.
- git commit -a -m "Update the master branch to version 0.${release}.99"
+ git commit -a -m "Update the master branch to version ${release}.99"
git push
------------
@@ -138,6 +151,8 @@ Update the gh-pages branch with new docs:
mkdir json-c-${release}
cp -R ../json-c-${release}/doc json-c-${release}/.
git add json-c-${release}
+ rm json-c-current-release
+ ln -s json-c-${release} json-c-current-release
git commit -a -m "Add the ${release} docs."
vi index.html
diff --git a/apps/json_parse.c b/apps/json_parse.c
index bba4622..72b31a8 100644
--- a/apps/json_parse.c
+++ b/apps/json_parse.c
@@ -82,7 +82,8 @@ static int parseit(int fd, int (*callback)(struct json_object *))
int parse_end = json_tokener_get_parse_end(tok);
if (obj == NULL && jerr != json_tokener_continue)
{
- char *aterr = &buf[start_pos + parse_end];
+ char *aterr = (start_pos + parse_end < sizeof(buf)) ?
+ &buf[start_pos + parse_end] : "";
fflush(stdout);
int fail_offset = total_read - ret + start_pos + parse_end;
fprintf(stderr, "Failed at offset %d: %s %c\n", fail_offset,
diff --git a/arraylist.c b/arraylist.c
index e5524ac..d8e12d1 100644
--- a/arraylist.c
+++ b/arraylist.c
@@ -38,15 +38,22 @@
struct array_list *array_list_new(array_list_free_fn *free_fn)
{
+ return array_list_new2(free_fn, ARRAY_LIST_DEFAULT_SIZE);
+}
+
+struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size)
+{
struct array_list *arr;
- arr = (struct array_list *)calloc(1, sizeof(struct array_list));
+ if (initial_size < 0 || (size_t)initial_size >= SIZE_T_MAX / sizeof(void *))
+ return NULL;
+ arr = (struct array_list *)malloc(sizeof(struct array_list));
if (!arr)
return NULL;
- arr->size = ARRAY_LIST_DEFAULT_SIZE;
+ arr->size = initial_size;
arr->length = 0;
arr->free_fn = free_fn;
- if (!(arr->array = (void **)calloc(arr->size, sizeof(void *))))
+ if (!(arr->array = (void **)malloc(arr->size * sizeof(void *))))
{
free(arr);
return NULL;
@@ -92,11 +99,33 @@ static int array_list_expand_internal(struct array_list *arr, size_t max)
if (!(t = realloc(arr->array, new_size * sizeof(void *))))
return -1;
arr->array = (void **)t;
- (void)memset(arr->array + arr->size, 0, (new_size - arr->size) * sizeof(void *));
arr->size = new_size;
return 0;
}
+int array_list_shrink(struct array_list *arr, size_t empty_slots)
+{
+ void *t;
+ size_t new_size;
+
+ if (empty_slots >= SIZE_T_MAX / sizeof(void *) - arr->length)
+ return -1;
+ new_size = arr->length + empty_slots;
+ if (new_size == arr->size)
+ return 0;
+ if (new_size > arr->size)
+ return array_list_expand_internal(arr, new_size);
+ if (new_size == 0)
+ new_size = 1;
+
+ if (!(t = realloc(arr->array, new_size * sizeof(void *))))
+ return -1;
+ arr->array = (void **)t;
+ arr->size = new_size;
+ return 0;
+}
+
+//static inline int _array_list_put_idx(struct array_list *arr, size_t idx, void *data)
int array_list_put_idx(struct array_list *arr, size_t idx, void *data)
{
if (idx > SIZE_T_MAX - 1)
@@ -106,6 +135,17 @@ int array_list_put_idx(struct array_list *arr, size_t idx, void *data)
if (idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
+ if (idx > arr->length)
+ {
+ /* Zero out the arraylist slots in between the old length
+ and the newly added entry so we know those entries are
+ empty.
+ e.g. when setting array[7] in an array that used to be
+ only 5 elements longs, array[5] and array[6] need to be
+ set to 0.
+ */
+ memset(arr->array + arr->length, 0, (idx - arr->length) * sizeof(void *));
+ }
if (arr->length <= idx)
arr->length = idx + 1;
return 0;
@@ -113,7 +153,17 @@ int array_list_put_idx(struct array_list *arr, size_t idx, void *data)
int array_list_add(struct array_list *arr, void *data)
{
- return array_list_put_idx(arr, arr->length, data);
+ /* Repeat some of array_list_put_idx() so we can skip several
+ checks that we know are unnecessary when appending at the end
+ */
+ size_t idx = arr->length;
+ if (idx > SIZE_T_MAX - 1)
+ return -1;
+ if (array_list_expand_internal(arr, idx + 1))
+ return -1;
+ arr->array[idx] = data;
+ arr->length++;
+ return 0;
}
void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *))
@@ -144,6 +194,8 @@ int array_list_del_idx(struct array_list *arr, size_t idx, size_t count)
return -1;
for (i = idx; i < stop; ++i)
{
+ // Because put_idx can skip entries, we need to check if
+ // there's actually anything in each slot we're erasing.
if (arr->array[i])
arr->free_fn(arr->array[i]);
}
diff --git a/arraylist.h b/arraylist.h
index 3c4b1b2..1b18756 100644
--- a/arraylist.h
+++ b/arraylist.h
@@ -37,8 +37,27 @@ struct array_list
};
typedef struct array_list array_list;
+/**
+ * Allocate an array_list of the default size (32).
+ * @deprecated Use array_list_new2() instead.
+ */
extern struct array_list *array_list_new(array_list_free_fn *free_fn);
+/**
+ * Allocate an array_list of the desired size.
+ *
+ * If possible, the size should be chosen to closely match
+ * the actual number of elements expected to be used.
+ * If the exact size is unknown, there are tradeoffs to be made:
+ * - too small - the array_list code will need to call realloc() more
+ * often (which might incur an additional memory copy).
+ * - too large - will waste memory, but that can be mitigated
+ * by calling array_list_shrink() once the final size is known.
+ *
+ * @see array_list_shrink
+ */
+extern struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size);
+
extern void array_list_free(struct array_list *al);
extern void *array_list_get_idx(struct array_list *al, size_t i);
@@ -56,6 +75,12 @@ extern void *array_list_bsearch(const void **key, struct array_list *arr,
extern int array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
+/**
+ * Shrink the array list to just enough to fit the number of elements in it,
+ * plus empty_slots.
+ */
+extern int array_list_shrink(struct array_list *arr, size_t empty_slots);
+
#ifdef __cplusplus
}
#endif
diff --git a/cmake-configure b/cmake-configure
index c8e44ae..dc695e5 100755
--- a/cmake-configure
+++ b/cmake-configure
@@ -30,6 +30,7 @@ $0 [<configure_options>] [-- [<cmake options>]]
--enable-static build static libraries [default=yes]
--disable-Bsymbolic Avoid linking with -Bsymbolic-function
--disable-werror Avoid treating compiler warnings as fatal errors
+ --disable-extra-libs Avoid linking against extra libraries, such as libbsd
EOF
exit
@@ -73,6 +74,9 @@ while [ $# -gt 0 ] ; do
--disable-werror)
FLAGS+=(-DDISABLE_WERROR=ON)
;;
+ --disable-extra-libs)
+ FLAGS+=(-DDISABLE_EXTRA_LIBS=ON)
+ ;;
--)
shift
break
diff --git a/cmake/config.h.in b/cmake/config.h.in
index 456c26a..be0202a 100644
--- a/cmake/config.h.in
+++ b/cmake/config.h.in
@@ -2,6 +2,9 @@
/* Enable RDRAND Hardware RNG Hash Seed */
#cmakedefine ENABLE_RDRAND "@ENABLE_RDRAND@"
+/* Override json_c_get_random_seed() with custom code */
+#cmakedefine OVERRIDE_GET_RANDOM_SEED @OVERRIDE_GET_RANDOM_SEED@
+
/* Enable partial threading support */
#cmakedefine ENABLE_THREADING "@@"
@@ -53,6 +56,9 @@
/* Define to 1 if you have the <sys/param.h> header file. */
#cmakedefine HAVE_SYS_PARAM_H @HAVE_SYS_PARAM_H@
+/* Define to 1 if you have the <sys/random.h> header file. */
+#cmakedefine HAVE_SYS_RANDOM_H
+
/* Define to 1 if you have the <sys/resource.h> header file. */
#cmakedefine HAVE_SYS_RESOURCE_H
@@ -68,6 +74,12 @@
/* Define to 1 if you have the <xlocale.h> header file. */
#cmakedefine HAVE_XLOCALE_H
+/* Define to 1 if you have the <bsd/stdlib.h> header file. */
+#cmakedefine HAVE_BSD_STDLIB_H
+
+/* Define to 1 if you have `arc4random' */
+#cmakedefine HAVE_ARC4RANDOM
+
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#cmakedefine HAVE_DOPRNT
@@ -137,6 +149,9 @@
/* Define to 1 if you have the `vsyslog' function. */
#cmakedefine HAVE_VSYSLOG @HAVE_VSYSLOG@
+/* Define if you have the `getrandom' function. */
+#cmakedefine HAVE_GETRANDOM
+
/* Define if you have the `getrusage' function. */
#cmakedefine HAVE_GETRUSAGE
@@ -194,6 +209,9 @@
/* The number of bytes in type size_t */
#cmakedefine SIZEOF_SIZE_T @SIZEOF_SIZE_T@
+/* The number of bytes in type ssize_t */
+#cmakedefine SIZEOF_SSIZE_T @SIZEOF_SSIZE_T@
+
/* Specifier for __thread */
#cmakedefine SPEC___THREAD @SPEC___THREAD@
diff --git a/config.h.win32 b/config.h.win32
deleted file mode 100644
index 130378e..0000000
--- a/config.h.win32
+++ /dev/null
@@ -1,207 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Enable RDRANR Hardware RNG Hash Seed */
-#undef ENABLE_RDRAND
-
-/* Define if .gnu.warning accepts long strings. */
-#undef HAS_GNU_WARNING_LONG
-
-/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
- don't. */
-#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
-#define HAVE_DECL_INFINITY 1
-#endif
-
-/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
- */
-#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
-#define HAVE_DECL_ISINF 1
-#endif
-
-/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
- */
-#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
-#define HAVE_DECL_ISNAN 1
-#endif
-
-/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
-#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
-#define HAVE_DECL_NAN 1
-#endif
-
-/* Define to 1 if you have the declaration of `_finite', and to 0 if you
- don't. */
-#define HAVE_DECL__FINITE 1
-
-/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
- */
-#define HAVE_DECL__ISNAN 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#define HAVE_DOPRNT 1
-
-/* Define to 1 if you have the <endian.h> header file. */
-#undef HAVE_ENDIAN_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#define HAVE_MALLOC 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `open' function. */
-#define HAVE_OPEN 1
-
-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
- and to 0 otherwise. */
-#define HAVE_REALLOC 1
-
-/* Define to 1 if you have the `setlocale' function. */
-#define HAVE_SETLOCALE 1
-
-/* Define to 1 if you have the `snprintf' function. */
-#if defined(__MINGW32__)
-#define HAVE_SNPRINTF 1
-#else
-#undef HAVE_SNPRINTF
-#endif
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 0
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncasecmp' function. */
-#if defined(__MINGW32__)
-#define HAVE_STRNCASECMP 1
-#else
-#undef HAVE_STRNCASECMP
-#endif
-
-#cmakedefine HAVE_STRTOLL
-#cmakedefine strtoll @cmake_strtoll@
-#cmakedefine HAVE_STRTOULL
-#cmakedefine strtoull @cmake_strtoull@
-
-/* Define to 1 if you have the <syslog.h> header file. */
-#undef HAVE_SYSLOG_H
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#if defined(__MINGW32__)
-#define HAVE_SYS_PARAM_H 1
-#else
-#undef HAVE_SYS_PARAM_H
-#endif
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#if defined(__MINGW32__)
-#define HAVE_UNISTD_H 1
-#else
-#undef HAVE_UNISTD_H
-#endif
-
-/* Define to 1 if you have the `vasprintf' function. */
-#if defined(__MINGW32__)
-#define HAVE_VASPRINTF 1
-#else
-#undef HAVE_VASPRINTF
-#endif
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the `vsnprintf' function. */
-#define HAVE_VSNPRINTF 1
-
-/* Define to 1 if you have the `vsyslog' function. */
-#undef HAVE_VSYSLOG
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#undef LT_OBJDIR
-
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-/* #undef NO_MINUS_C_MINUS_O */
-
-/* Name of package */
-#define PACKAGE "json-c"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "JSON C Library"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "JSON C Library 0.14.99"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "json-c"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL "https://github.com/json-c/json-c"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.14.99"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.14.99"
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to rpl_malloc if the replacement function should be used. */
-/* #undef malloc */
-
-/* Define to rpl_realloc if the replacement function should be used. */
-/* #undef realloc */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
diff --git a/debug.h b/debug.h
index a24136b..7463f86 100644
--- a/debug.h
+++ b/debug.h
@@ -24,7 +24,7 @@ extern "C" {
#endif
#ifndef JSON_EXPORT
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && defined(JSON_C_DLL)
#define JSON_EXPORT __declspec(dllexport)
#else
#define JSON_EXPORT extern
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 0000000..4872d8e
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,16 @@
+# generate doxygen documentation for json-c API
+
+find_package(Doxygen)
+
+if (DOXYGEN_FOUND)
+
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+ message(STATUS "Wrote ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
+
+ add_custom_target(doc
+ COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+else (DOXYGEN_FOUND)
+ message("Warning: doxygen not found, the 'doc' target will not be included")
+endif(DOXYGEN_FOUND)
diff --git a/Doxyfile b/doc/Doxyfile.in
index 06d54e6..e411023 100644
--- a/Doxyfile
+++ b/doc/Doxyfile.in
@@ -38,7 +38,7 @@ PROJECT_NAME = json-c
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 0.14.99
+PROJECT_NUMBER = @PROJECT_VERSION@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = doc
+OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -753,7 +753,7 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
-INPUT =
+INPUT = @CMAKE_SOURCE_DIR@ @CMAKE_BINARY_DIR@
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -805,7 +805,13 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS = \
+ */json_object_private.h \
+ */debug.h \
+ */*config.h \
+ */random_seed.h \
+ */strerror_*h \
+ */*compat.h
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -816,7 +822,11 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS = \
+ _json_c_* \
+ _LH_* \
+ _printbuf_* \
+ __STRING
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
@@ -859,7 +869,7 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
-INPUT_FILTER =
+INPUT_FILTER = @CMAKE_CURRENT_SOURCE_DIR@/fixup_markdown.sh
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
diff --git a/doc/fixup_markdown.sh b/doc/fixup_markdown.sh
new file mode 100755
index 0000000..452eb78
--- /dev/null
+++ b/doc/fixup_markdown.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+# Doxygen markdown doesn't support triple-backticks like github does.
+# Convert all of those to space-prefixed blocks instead.
+#
+awk '/```/ { prefix=!prefix; print ""; next; } { if (prefix) { printf " "; } print $0; } ' "$@"
diff --git a/issues_closed_for_0.13.md b/issues_closed_for_0.13.md
index c2b8f2d..f3e932c 100644
--- a/issues_closed_for_0.13.md
+++ b/issues_closed_for_0.13.md
@@ -16,255 +16,255 @@ Issues and Pull Requests closed for the 0.13 release
(since commit f84d9c, the 0.12 branch point, 2014-04-10)
-[Issue #61](https://github.com/json-c/json-c/issues/61) - Make json_object_object_add() indicate success or failure, test fix \
-[Issue #113](https://github.com/json-c/json-c/issues/113) - Build fixes (make dist and make distcheck) \
-[Issue #124](https://github.com/json-c/json-c/issues/124) - Fixing build \
-[Issue #125](https://github.com/json-c/json-c/issues/125) - Fix compile error(variable size set but not used) on g++4.6 \
-[Issue #126](https://github.com/json-c/json-c/issues/126) - Removed unused size variable. \
-[Issue #127](https://github.com/json-c/json-c/issues/127) - remove unused `size` variable \
-[Issue #128](https://github.com/json-c/json-c/issues/128) - Remove unused variable from json_tokenizer.c \
-[Issue #130](https://github.com/json-c/json-c/issues/130) - Failed to compile under Ubuntu 13.10 32bit \
-[Issue #131](https://github.com/json-c/json-c/issues/131) - undefined symbol: __sync_val_compare_and_swap_4 \
-[Issue #132](https://github.com/json-c/json-c/issues/132) - Remove unused variable 'size' \
-[Issue #133](https://github.com/json-c/json-c/issues/133) - Update and rename README to README.md \
-[Issue #134](https://github.com/json-c/json-c/issues/134) - Must remove variable size... \
-[Issue #135](https://github.com/json-c/json-c/issues/135) - bits.h uses removed json_tokener_errors\[error\] \
-[Issue #136](https://github.com/json-c/json-c/issues/136) - Error when running make check \
-[Issue #137](https://github.com/json-c/json-c/issues/137) - config.h.in should not be in git \
-[Issue #138](https://github.com/json-c/json-c/issues/138) - Can't build on RHEL 6.5 due to dependency on automake-1.14 \
-[Issue #140](https://github.com/json-c/json-c/issues/140) - Code bug in random_test.c evaluating same expression twice \
-[Issue #141](https://github.com/json-c/json-c/issues/141) - Removed duplicate check in random_seed test - bug #140 \
-[Issue #142](https://github.com/json-c/json-c/issues/142) - Please undeprecate json_object_object_get \
-[Issue #144](https://github.com/json-c/json-c/issues/144) - Introduce json_object_from_fd \
-[Issue #145](https://github.com/json-c/json-c/issues/145) - Handle % character properly \
-[Issue #146](https://github.com/json-c/json-c/issues/146) - TAGS rename \
-[Issue #148](https://github.com/json-c/json-c/issues/148) - Bump the soname \
-[Issue #149](https://github.com/json-c/json-c/issues/149) - SONAME bump \
-[Issue #150](https://github.com/json-c/json-c/issues/150) - Fix build using MinGW. \
-[Issue #151](https://github.com/json-c/json-c/issues/151) - Remove json_type enum trailing comma \
-[Issue #152](https://github.com/json-c/json-c/issues/152) - error while compiling json-c library version 0.11 \
-[Issue #153](https://github.com/json-c/json-c/issues/153) - improve doc for json_object_to_json_string() \
-[Issue #154](https://github.com/json-c/json-c/issues/154) - double precision \
-[Issue #155](https://github.com/json-c/json-c/issues/155) - add bsearch for arrays \
-[Issue #156](https://github.com/json-c/json-c/issues/156) - Remove trailing whitespaces \
-[Issue #157](https://github.com/json-c/json-c/issues/157) - JSON-C shall not exit on calloc fail. \
-[Issue #158](https://github.com/json-c/json-c/issues/158) - while using json-c 0.11, I am facing strange crash issue in json_object_put. \
-[Issue #159](https://github.com/json-c/json-c/issues/159) - json_tokener.c compile error \
-[Issue #160](https://github.com/json-c/json-c/issues/160) - missing header file on windows?? \
-[Issue #161](https://github.com/json-c/json-c/issues/161) - Is there a way to append to file? \
-[Issue #162](https://github.com/json-c/json-c/issues/162) - json_util: add directory check for POSIX distros \
-[Issue #163](https://github.com/json-c/json-c/issues/163) - Fix Win32 build problems \
-[Issue #164](https://github.com/json-c/json-c/issues/164) - made it compile and link on Widnows (as static library) \
-[Issue #165](https://github.com/json-c/json-c/issues/165) - json_object_to_json_string_ext length \
-[Issue #167](https://github.com/json-c/json-c/issues/167) - Can't build on Windows with Visual Studio 2010 \
-[Issue #168](https://github.com/json-c/json-c/issues/168) - Tightening the number parsing algorithm \
-[Issue #169](https://github.com/json-c/json-c/issues/169) - Doesn't compile on ubuntu 14.04, 64bit \
-[Issue #170](https://github.com/json-c/json-c/issues/170) - Generated files in repository \
-[Issue #171](https://github.com/json-c/json-c/issues/171) - Update configuration for VS2010 and win64 \
-[Issue #172](https://github.com/json-c/json-c/issues/172) - Adding support for parsing octal numbers \
-[Issue #173](https://github.com/json-c/json-c/issues/173) - json_parse_int64 doesn't work correctly at illumos \
-[Issue #174](https://github.com/json-c/json-c/issues/174) - Adding JSON_C_TO_STRING_PRETTY_TAB flag \
-[Issue #175](https://github.com/json-c/json-c/issues/175) - make check fails 4 tests with overflows when built with ASAN \
-[Issue #176](https://github.com/json-c/json-c/issues/176) - Possible to delete an array element at a given idx ? \
-[Issue #177](https://github.com/json-c/json-c/issues/177) - Fix compiler warnings \
-[Issue #178](https://github.com/json-c/json-c/issues/178) - Unable to compile on CentOS5 \
-[Issue #179](https://github.com/json-c/json-c/issues/179) - Added array_list_del_idx and json_object_array_del_idx \
-[Issue #180](https://github.com/json-c/json-c/issues/180) - Enable silent build by default \
-[Issue #181](https://github.com/json-c/json-c/issues/181) - json_tokener_parse_ex accepts invalid JSON \
-[Issue #182](https://github.com/json-c/json-c/issues/182) - Link against libm when needed \
-[Issue #183](https://github.com/json-c/json-c/issues/183) - Apply compile warning fix to master branch \
-[Issue #184](https://github.com/json-c/json-c/issues/184) - Use only GCC-specific flags when compiling with GCC \
-[Issue #185](https://github.com/json-c/json-c/issues/185) - compile error \
-[Issue #186](https://github.com/json-c/json-c/issues/186) - Syntax error \
-[Issue #187](https://github.com/json-c/json-c/issues/187) - array_list_get_idx and negative indexes. \
-[Issue #188](https://github.com/json-c/json-c/issues/188) - json_object_object_foreach warnings \
-[Issue #189](https://github.com/json-c/json-c/issues/189) - noisy json_object_from_file: error opening file \
-[Issue #190](https://github.com/json-c/json-c/issues/190) - warning: initialization discards const qualifier from pointer target type \[enabled by default\] \
-[Issue #192](https://github.com/json-c/json-c/issues/192) - json_tokener_parse accepts invalid JSON {"key": "value" , } \
-[Issue #193](https://github.com/json-c/json-c/issues/193) - Make serialization format of doubles configurable \
-[Issue #194](https://github.com/json-c/json-c/issues/194) - Add utility function for comparing json_objects \
-[Issue #195](https://github.com/json-c/json-c/issues/195) - Call uselocale instead of setlocale \
-[Issue #196](https://github.com/json-c/json-c/issues/196) - Performance improvements \
-[Issue #197](https://github.com/json-c/json-c/issues/197) - Time for a new release? \
-[Issue #198](https://github.com/json-c/json-c/issues/198) - Fix possible memory leak and remove superfluous NULL checks before free() \
-[Issue #199](https://github.com/json-c/json-c/issues/199) - Fix build in Visual Studio \
-[Issue #200](https://github.com/json-c/json-c/issues/200) - Add build scripts for CI platforms \
-[Issue #201](https://github.com/json-c/json-c/issues/201) - disable forward-slash escaping? \
-[Issue #202](https://github.com/json-c/json-c/issues/202) - Array with objects support \
-[Issue #203](https://github.com/json-c/json-c/issues/203) - Add source position/coordinates to API \
-[Issue #204](https://github.com/json-c/json-c/issues/204) - json-c/json.h not found \
-[Issue #205](https://github.com/json-c/json-c/issues/205) - json-c Compiled with Visual Studios \
-[Issue #206](https://github.com/json-c/json-c/issues/206) - what do i use in place of json_object_object_get? \
-[Issue #207](https://github.com/json-c/json-c/issues/207) - Add support for property pairs directly added to arrays \
-[Issue #208](https://github.com/json-c/json-c/issues/208) - Performance enhancements (mainly) to json_object_to_json_string() \
-[Issue #209](https://github.com/json-c/json-c/issues/209) - fix regression from 2d549662be832da838aa063da2efa78ee3b99668 \
-[Issue #210](https://github.com/json-c/json-c/issues/210) - Use size_t for arrays \
-[Issue #211](https://github.com/json-c/json-c/issues/211) - Atomic updates for the refcount \
-[Issue #212](https://github.com/json-c/json-c/issues/212) - Refcount doesn't work between threads \
-[Issue #213](https://github.com/json-c/json-c/issues/213) - fix to compile with microsoft visual c++ 2010 \
-[Issue #214](https://github.com/json-c/json-c/issues/214) - Some non-GNU systems support __sync_val_compare_and_swap \
-[Issue #215](https://github.com/json-c/json-c/issues/215) - Build json-c for window 64 bit. \
-[Issue #216](https://github.com/json-c/json-c/issues/216) - configure: check realloc with AC_CHECK_FUNCS() to fix cross-compilation. \
-[Issue #217](https://github.com/json-c/json-c/issues/217) - Checking for functions in float.h \
-[Issue #218](https://github.com/json-c/json-c/issues/218) - Use a macro to indicate C99 to the compiler \
-[Issue #219](https://github.com/json-c/json-c/issues/219) - Fix various potential null ptr deref and int32 overflows \
-[Issue #220](https://github.com/json-c/json-c/issues/220) - Add utility function for comparing json_objects \
-[Issue #221](https://github.com/json-c/json-c/issues/221) - JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \
-[Issue #222](https://github.com/json-c/json-c/issues/222) - Fix issue #221: JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \
-[Issue #223](https://github.com/json-c/json-c/issues/223) - Clarify json_object_get_string documentation of NULL handling & return \
-[Issue #224](https://github.com/json-c/json-c/issues/224) - json_tokener.c - all warnings being treated as errors \
-[Issue #225](https://github.com/json-c/json-c/issues/225) - Hi, will you support clib as a "registry"? \
-[Issue #227](https://github.com/json-c/json-c/issues/227) - Bump SOVERSION to 3 \
-[Issue #228](https://github.com/json-c/json-c/issues/228) - avoid double slashes from json \
-[Issue #229](https://github.com/json-c/json-c/issues/229) - configure fails: checking size of size_t... configure: error: cannot determine a size for size_t \
-[Issue #230](https://github.com/json-c/json-c/issues/230) - Use stdint.h to check for size_t size \
-[Issue #231](https://github.com/json-c/json-c/issues/231) - Fix size_t size check for first-time builds \
-[Issue #232](https://github.com/json-c/json-c/issues/232) - tests/tests1: fix printf format for size_t arguments \
-[Issue #233](https://github.com/json-c/json-c/issues/233) - Include stddef.h in json_object.h \
-[Issue #234](https://github.com/json-c/json-c/issues/234) - Add public API to use userdata independently of custom serializer \
-[Issue #235](https://github.com/json-c/json-c/issues/235) - Undefined symbols Error for architecture x86_64 on Mac \
-[Issue #236](https://github.com/json-c/json-c/issues/236) - Building a project which uses json-c with flag -Wcast-qual causes compilation errors \
-[Issue #237](https://github.com/json-c/json-c/issues/237) - handle escaped utf-8 \
-[Issue #238](https://github.com/json-c/json-c/issues/238) - linkhash.c: optimised the table_free path \
-[Issue #239](https://github.com/json-c/json-c/issues/239) - initialize null terminator of new printbuf \
-[Issue #240](https://github.com/json-c/json-c/issues/240) - Compile error: Variable set but not used \
-[Issue #241](https://github.com/json-c/json-c/issues/241) - getting error in date string 19\/07\/2016, fixed for error 19/07/2016 \
-[Issue #242](https://github.com/json-c/json-c/issues/242) - json_tokener_parse error \
-[Issue #243](https://github.com/json-c/json-c/issues/243) - Fix #165 \
-[Issue #244](https://github.com/json-c/json-c/issues/244) - Error while compiling source from RHEL5, could you please help me to fix this \
-[Issue #245](https://github.com/json-c/json-c/issues/245) - json-c compile in window xp \
-[Issue #246](https://github.com/json-c/json-c/issues/246) - Mac: uselocale failed to build \
-[Issue #247](https://github.com/json-c/json-c/issues/247) - json_object_array_del_idx function has segment fault error? \
-[Issue #248](https://github.com/json-c/json-c/issues/248) - Minor changes in C source code \
-[Issue #249](https://github.com/json-c/json-c/issues/249) - Improving README \
-[Issue #250](https://github.com/json-c/json-c/issues/250) - Improving .gitignore \
-[Issue #251](https://github.com/json-c/json-c/issues/251) - Adding a file for EditorConfig \
-[Issue #252](https://github.com/json-c/json-c/issues/252) - Very minor changes not related to C source code \
-[Issue #253](https://github.com/json-c/json-c/issues/253) - Adding a test with cppcheck for Travis CI \
-[Issue #254](https://github.com/json-c/json-c/issues/254) - Very minor changes to some tests \
-[Issue #255](https://github.com/json-c/json-c/issues/255) - Minor changes in C source code \
-[Issue #256](https://github.com/json-c/json-c/issues/256) - Mailing list dead? \
-[Issue #257](https://github.com/json-c/json-c/issues/257) - Defining a coding style \
-[Issue #258](https://github.com/json-c/json-c/issues/258) - Enable CI services \
-[Issue #259](https://github.com/json-c/json-c/issues/259) - Fails to parse valid json \
-[Issue #260](https://github.com/json-c/json-c/issues/260) - Adding an object to itself \
-[Issue #261](https://github.com/json-c/json-c/issues/261) - Lack of proper documentation \
-[Issue #262](https://github.com/json-c/json-c/issues/262) - Add Cmakefile and fix compiler warning. \
-[Issue #263](https://github.com/json-c/json-c/issues/263) - Compiler Warnings with VS2015 \
-[Issue #264](https://github.com/json-c/json-c/issues/264) - successed in simple test while failed in my project \
-[Issue #265](https://github.com/json-c/json-c/issues/265) - Conformance report for reference \
-[Issue #266](https://github.com/json-c/json-c/issues/266) - crash perhaps related to reference counting \
-[Issue #267](https://github.com/json-c/json-c/issues/267) - Removes me as Win32 maintainer, because I'm not. \
-[Issue #268](https://github.com/json-c/json-c/issues/268) - Documentation of json_object_to_json_string gives no information about memory management \
-[Issue #269](https://github.com/json-c/json-c/issues/269) - json_object_<type>_set(json_object *o,<type> value) API for value setting in json object private structure \
-[Issue #270](https://github.com/json-c/json-c/issues/270) - new API json_object_new_double_f(doubel d,const char * fmt); \
-[Issue #271](https://github.com/json-c/json-c/issues/271) - Cannot compile using CMake on macOS \
-[Issue #273](https://github.com/json-c/json-c/issues/273) - fixed wrong object name in json_object_all_values_equal \
-[Issue #274](https://github.com/json-c/json-c/issues/274) - Support for 64 bit pointers on Windows \
-[Issue #275](https://github.com/json-c/json-c/issues/275) - Out-of-bounds read in json_tokener_parse_ex \
-[Issue #276](https://github.com/json-c/json-c/issues/276) - ./configure for centos release 6.7(final) failure \
-[Issue #277](https://github.com/json-c/json-c/issues/277) - Json object set xxx \
-[Issue #278](https://github.com/json-c/json-c/issues/278) - Serialization of double with no fractional component drops trailing zero \
-[Issue #279](https://github.com/json-c/json-c/issues/279) - Segmentation fault in array_list_length() \
-[Issue #280](https://github.com/json-c/json-c/issues/280) - Should json_object_array_get_idx check whether input obj is array? \
-[Issue #281](https://github.com/json-c/json-c/issues/281) - how to pretty print json-c? \
-[Issue #282](https://github.com/json-c/json-c/issues/282) - ignore temporary files \
-[Issue #283](https://github.com/json-c/json-c/issues/283) - json_pointer: add first revision based on RFC 6901 \
-[Issue #284](https://github.com/json-c/json-c/issues/284) - Resusing json_tokener object \
-[Issue #285](https://github.com/json-c/json-c/issues/285) - Revert "compat/strdup.h: move common compat check for strdup() to own \
-[Issue #286](https://github.com/json-c/json-c/issues/286) - json_tokener_parse_ex() returns json_tokener_continue on zero-length string \
-[Issue #287](https://github.com/json-c/json-c/issues/287) - json_pointer: extend setter & getter with printf() style arguments \
-[Issue #288](https://github.com/json-c/json-c/issues/288) - Fix _GNU_SOURCE define for vasprintf \
-[Issue #289](https://github.com/json-c/json-c/issues/289) - bugfix: floating point representaion without fractional part \
-[Issue #290](https://github.com/json-c/json-c/issues/290) - duplicate an json_object \
-[Issue #291](https://github.com/json-c/json-c/issues/291) - isspace assert error \
-[Issue #292](https://github.com/json-c/json-c/issues/292) - configure error "./configure: line 13121: syntax error near unexpected token `-Wall'" \
-[Issue #293](https://github.com/json-c/json-c/issues/293) - how to make with bitcode for ios \
-[Issue #294](https://github.com/json-c/json-c/issues/294) - Adding UTF-8 validation. Fixes #122 \
-[Issue #295](https://github.com/json-c/json-c/issues/295) - cross compile w/ mingw \
-[Issue #296](https://github.com/json-c/json-c/issues/296) - Missing functions header in json_object.h \
-[Issue #297](https://github.com/json-c/json-c/issues/297) - could not parse string to Json object? Like string str=\"helloworld;E\\test\\log\\;end\" \
-[Issue #298](https://github.com/json-c/json-c/issues/298) - Building using CMake doesn't work \
-[Issue #299](https://github.com/json-c/json-c/issues/299) - Improve json_object -> string performance \
-[Issue #300](https://github.com/json-c/json-c/issues/300) - Running tests with MinGW build \
-[Issue #301](https://github.com/json-c/json-c/issues/301) - How to deep copy json_object in C++ ? \
-[Issue #302](https://github.com/json-c/json-c/issues/302) - json_tokener_parse_ex doesn't parse JSON values \
-[Issue #303](https://github.com/json-c/json-c/issues/303) - fix doc in tokener header file \
-[Issue #304](https://github.com/json-c/json-c/issues/304) - (.text+0x72846): undefined reference to `is_error' \
-[Issue #305](https://github.com/json-c/json-c/issues/305) - Fix compilation without C-99 option \
-[Issue #306](https://github.com/json-c/json-c/issues/306) - ./configure: line 12748 -error=deprecated-declarations \
-[Issue #307](https://github.com/json-c/json-c/issues/307) - Memory leak in json_tokener_parse \
-[Issue #308](https://github.com/json-c/json-c/issues/308) - AM_PROG_LIBTOOL not found on Linux \
-[Issue #309](https://github.com/json-c/json-c/issues/309) - GCC 7 reports various -Wimplicit-fallthrough= errors \
-[Issue #310](https://github.com/json-c/json-c/issues/310) - Add FALLTHRU comment to handle GCC7 warnings. \
-[Issue #311](https://github.com/json-c/json-c/issues/311) - Fix error C3688 when compiling on Visual Studio 2015 \
-[Issue #312](https://github.com/json-c/json-c/issues/312) - Fix CMake Build process improved for MinGW and MSYS2 \
-[Issue #313](https://github.com/json-c/json-c/issues/313) - VERBOSE=1 make check; tests/test_util_file.test.c and tests/test_util_file.expected out of sync \
-[Issue #315](https://github.com/json-c/json-c/issues/315) - Passing -1 to json_tokener_parse_ex is possibly unsafe \
-[Issue #316](https://github.com/json-c/json-c/issues/316) - Memory Returned by json_object_to_json_string not freed \
-[Issue #317](https://github.com/json-c/json-c/issues/317) - json_object_get_string gives segmentation error \
-[Issue #318](https://github.com/json-c/json-c/issues/318) - PVS-Studio static analyzer analyze results \
-[Issue #319](https://github.com/json-c/json-c/issues/319) - Windows: Fix dynamic library build with Visual Studio \
-[Issue #320](https://github.com/json-c/json-c/issues/320) - Can't compile in Mac OS X El Capitan \
-[Issue #321](https://github.com/json-c/json-c/issues/321) - build,cmake: fix vasprintf implicit definition and generate both static & shared libs \
-[Issue #322](https://github.com/json-c/json-c/issues/322) - can not link with libjson-c.a \
-[Issue #323](https://github.com/json-c/json-c/issues/323) - implicit fallthrough detected by gcc 7.1 \
-[Issue #324](https://github.com/json-c/json-c/issues/324) - JsonPath like function? \
-[Issue #325](https://github.com/json-c/json-c/issues/325) - Fix stack buffer overflow in json_object_double_to_json_string_format() \
-[Issue #327](https://github.com/json-c/json-c/issues/327) - why json-c so hard to compile \
-[Issue #328](https://github.com/json-c/json-c/issues/328) - json_object: implement json_object_deep_copy() function \
-[Issue #329](https://github.com/json-c/json-c/issues/329) - build,cmake: build,cmake: rename libjson-c-static.a to libjson-c.a \
-[Issue #330](https://github.com/json-c/json-c/issues/330) - tests: symlink basic tests to a single file that has the common code \
-[Issue #331](https://github.com/json-c/json-c/issues/331) - Safe use of snprintf() / vsnprintf() for Visual studio, and thread-safety fix \
-[Issue #332](https://github.com/json-c/json-c/issues/332) - Valgrind: invalid read after json_object_array_del_idx. \
-[Issue #333](https://github.com/json-c/json-c/issues/333) - Replace obsolete AM_PROG_LIBTOOL \
-[Issue #335](https://github.com/json-c/json-c/issues/335) - README.md: show build status tag from travis-ci.org \
-[Issue #336](https://github.com/json-c/json-c/issues/336) - tests: fix tests in travis-ci.org \
-[Issue #337](https://github.com/json-c/json-c/issues/337) - Synchronize "potentially racy" random seed in lh_char_hash() \
-[Issue #338](https://github.com/json-c/json-c/issues/338) - implement json_object_int_inc(json_object *, int64_t) \
-[Issue #339](https://github.com/json-c/json-c/issues/339) - Json schema validation \
-[Issue #340](https://github.com/json-c/json-c/issues/340) - strerror_override: add extern "C" and JSON_EXPORT specifiers for Visual C++ compilers \
-[Issue #341](https://github.com/json-c/json-c/issues/341) - character "/" parse as "\/" \
-[Issue #342](https://github.com/json-c/json-c/issues/342) - No such file or directory "/usr/include/json.h" \
-[Issue #343](https://github.com/json-c/json-c/issues/343) - Can't parse json \
-[Issue #344](https://github.com/json-c/json-c/issues/344) - Fix Mingw build \
-[Issue #345](https://github.com/json-c/json-c/issues/345) - Fix make dist and make distcheck \
-[Issue #346](https://github.com/json-c/json-c/issues/346) - Clamp double to int32 when narrowing in json_object_get_int. \
-[Issue #347](https://github.com/json-c/json-c/issues/347) - MSVC linker error json_c_strerror \
-[Issue #348](https://github.com/json-c/json-c/issues/348) - why \
-[Issue #349](https://github.com/json-c/json-c/issues/349) - `missing` is missing? \
-[Issue #350](https://github.com/json-c/json-c/issues/350) - stderror-override and disable-shared \
-[Issue #351](https://github.com/json-c/json-c/issues/351) - SIZE_T_MAX redefined from limits.h \
-[Issue #352](https://github.com/json-c/json-c/issues/352) - `INSTALL` overrides an automake script. \
-[Issue #353](https://github.com/json-c/json-c/issues/353) - Documentation issues \
-[Issue #354](https://github.com/json-c/json-c/issues/354) - Fixes #351 #352 #353 \
-[Issue #355](https://github.com/json-c/json-c/issues/355) - 1.make it can been compiled with Visual Studio 2010 by modify the CMakeList.txt and others \
-[Issue #356](https://github.com/json-c/json-c/issues/356) - VS2008 test test_util_file.cpp err! \
-[Issue #357](https://github.com/json-c/json-c/issues/357) - __json_c_strerror incompatibility with link-time optimization \
-[Issue #358](https://github.com/json-c/json-c/issues/358) - make issue \
-[Issue #359](https://github.com/json-c/json-c/issues/359) - update CMakeLists.txt for compile with visual studio at least 2010 \
-[Issue #360](https://github.com/json-c/json-c/issues/360) - Use strtoll() to parse ints \
-[Issue #361](https://github.com/json-c/json-c/issues/361) - Fix double to int cast overflow in json_object_get_int64. \
-[Issue #362](https://github.com/json-c/json-c/issues/362) - CMake Package Config \
-[Issue #363](https://github.com/json-c/json-c/issues/363) - Issue #338, add json_object_add_int functions \
-[Issue #364](https://github.com/json-c/json-c/issues/364) - Cmake is Errir \
-[Issue #365](https://github.com/json-c/json-c/issues/365) - added fallthrough for gcc7 \
-[Issue #366](https://github.com/json-c/json-c/issues/366) - how to check the json string,crash! \
-[Issue #367](https://github.com/json-c/json-c/issues/367) - Is json-c support "redirect" semantic? \
-[Issue #368](https://github.com/json-c/json-c/issues/368) - Add examples \
-[Issue #369](https://github.com/json-c/json-c/issues/369) - How to build json-c library for android? \
-[Issue #370](https://github.com/json-c/json-c/issues/370) - Compiling using clang-cl \
-[Issue #371](https://github.com/json-c/json-c/issues/371) - Invalid parsing for Infinity with json-c 0.12 \
-[Issue #372](https://github.com/json-c/json-c/issues/372) - Json-c 0.12: Fixed Infinity bug \
-[Issue #373](https://github.com/json-c/json-c/issues/373) - build: fix build on appveyor CI \
-[Issue #374](https://github.com/json-c/json-c/issues/374) - Undefined symbols for architecture x86_64: \
-[Issue #375](https://github.com/json-c/json-c/issues/375) - what would happened when json_object_object_add add the same key \
-[Issue #376](https://github.com/json-c/json-c/issues/376) - Eclipse error \
-[Issue #377](https://github.com/json-c/json-c/issues/377) - on gcc 7.2.0 on my linux distribution with json-c 2013-04-02 source \
-[Issue #378](https://github.com/json-c/json-c/issues/378) - Eclipse: library (libjson-c) not found, but configured \
-[Issue #379](https://github.com/json-c/json-c/issues/379) - error: this statement may fall through \[-Werror=implicit-fallthrough=\] \
-[Issue #380](https://github.com/json-c/json-c/issues/380) - Build on Windows \
-[Issue #381](https://github.com/json-c/json-c/issues/381) - Fix makedist \
-[Issue #382](https://github.com/json-c/json-c/issues/382) - Memory leak for json_tokener_parse_ex for version 0.12.1 \
-[Issue #383](https://github.com/json-c/json-c/issues/383) - Fix a compiler warning. \
-[Issue #384](https://github.com/json-c/json-c/issues/384) - Fix a VS 2015 compiler warnings. \
+* [Issue #61](https://github.com/json-c/json-c/issues/61) - Make json_object_object_add() indicate success or failure, test fix \
+* [Issue #113](https://github.com/json-c/json-c/issues/113) - Build fixes (make dist and make distcheck) \
+* [Issue #124](https://github.com/json-c/json-c/issues/124) - Fixing build \
+* [Issue #125](https://github.com/json-c/json-c/issues/125) - Fix compile error(variable size set but not used) on g++4.6 \
+* [Issue #126](https://github.com/json-c/json-c/issues/126) - Removed unused size variable. \
+* [Issue #127](https://github.com/json-c/json-c/issues/127) - remove unused `size` variable \
+* [Issue #128](https://github.com/json-c/json-c/issues/128) - Remove unused variable from json_tokenizer.c \
+* [Issue #130](https://github.com/json-c/json-c/issues/130) - Failed to compile under Ubuntu 13.10 32bit \
+* [Issue #131](https://github.com/json-c/json-c/issues/131) - undefined symbol: __sync_val_compare_and_swap_4 \
+* [Issue #132](https://github.com/json-c/json-c/issues/132) - Remove unused variable 'size' \
+* [Issue #133](https://github.com/json-c/json-c/issues/133) - Update and rename README to README.md \
+* [Issue #134](https://github.com/json-c/json-c/issues/134) - Must remove variable size... \
+* [Issue #135](https://github.com/json-c/json-c/issues/135) - bits.h uses removed json_tokener_errors\[error\] \
+* [Issue #136](https://github.com/json-c/json-c/issues/136) - Error when running make check \
+* [Issue #137](https://github.com/json-c/json-c/issues/137) - config.h.in should not be in git \
+* [Issue #138](https://github.com/json-c/json-c/issues/138) - Can't build on RHEL 6.5 due to dependency on automake-1.14 \
+* [Issue #140](https://github.com/json-c/json-c/issues/140) - Code bug in random_test.c evaluating same expression twice \
+* [Issue #141](https://github.com/json-c/json-c/issues/141) - Removed duplicate check in random_seed test - bug #140 \
+* [Issue #142](https://github.com/json-c/json-c/issues/142) - Please undeprecate json_object_object_get \
+* [Issue #144](https://github.com/json-c/json-c/issues/144) - Introduce json_object_from_fd \
+* [Issue #145](https://github.com/json-c/json-c/issues/145) - Handle % character properly \
+* [Issue #146](https://github.com/json-c/json-c/issues/146) - TAGS rename \
+* [Issue #148](https://github.com/json-c/json-c/issues/148) - Bump the soname \
+* [Issue #149](https://github.com/json-c/json-c/issues/149) - SONAME bump \
+* [Issue #150](https://github.com/json-c/json-c/issues/150) - Fix build using MinGW. \
+* [Issue #151](https://github.com/json-c/json-c/issues/151) - Remove json_type enum trailing comma \
+* [Issue #152](https://github.com/json-c/json-c/issues/152) - error while compiling json-c library version 0.11 \
+* [Issue #153](https://github.com/json-c/json-c/issues/153) - improve doc for json_object_to_json_string() \
+* [Issue #154](https://github.com/json-c/json-c/issues/154) - double precision \
+* [Issue #155](https://github.com/json-c/json-c/issues/155) - add bsearch for arrays \
+* [Issue #156](https://github.com/json-c/json-c/issues/156) - Remove trailing whitespaces \
+* [Issue #157](https://github.com/json-c/json-c/issues/157) - JSON-C shall not exit on calloc fail. \
+* [Issue #158](https://github.com/json-c/json-c/issues/158) - while using json-c 0.11, I am facing strange crash issue in json_object_put. \
+* [Issue #159](https://github.com/json-c/json-c/issues/159) - json_tokener.c compile error \
+* [Issue #160](https://github.com/json-c/json-c/issues/160) - missing header file on windows?? \
+* [Issue #161](https://github.com/json-c/json-c/issues/161) - Is there a way to append to file? \
+* [Issue #162](https://github.com/json-c/json-c/issues/162) - json_util: add directory check for POSIX distros \
+* [Issue #163](https://github.com/json-c/json-c/issues/163) - Fix Win32 build problems \
+* [Issue #164](https://github.com/json-c/json-c/issues/164) - made it compile and link on Widnows (as static library) \
+* [Issue #165](https://github.com/json-c/json-c/issues/165) - json_object_to_json_string_ext length \
+* [Issue #167](https://github.com/json-c/json-c/issues/167) - Can't build on Windows with Visual Studio 2010 \
+* [Issue #168](https://github.com/json-c/json-c/issues/168) - Tightening the number parsing algorithm \
+* [Issue #169](https://github.com/json-c/json-c/issues/169) - Doesn't compile on ubuntu 14.04, 64bit \
+* [Issue #170](https://github.com/json-c/json-c/issues/170) - Generated files in repository \
+* [Issue #171](https://github.com/json-c/json-c/issues/171) - Update configuration for VS2010 and win64 \
+* [Issue #172](https://github.com/json-c/json-c/issues/172) - Adding support for parsing octal numbers \
+* [Issue #173](https://github.com/json-c/json-c/issues/173) - json_parse_int64 doesn't work correctly at illumos \
+* [Issue #174](https://github.com/json-c/json-c/issues/174) - Adding JSON_C_TO_STRING_PRETTY_TAB flag \
+* [Issue #175](https://github.com/json-c/json-c/issues/175) - make check fails 4 tests with overflows when built with ASAN \
+* [Issue #176](https://github.com/json-c/json-c/issues/176) - Possible to delete an array element at a given idx ? \
+* [Issue #177](https://github.com/json-c/json-c/issues/177) - Fix compiler warnings \
+* [Issue #178](https://github.com/json-c/json-c/issues/178) - Unable to compile on CentOS5 \
+* [Issue #179](https://github.com/json-c/json-c/issues/179) - Added array_list_del_idx and json_object_array_del_idx \
+* [Issue #180](https://github.com/json-c/json-c/issues/180) - Enable silent build by default \
+* [Issue #181](https://github.com/json-c/json-c/issues/181) - json_tokener_parse_ex accepts invalid JSON \
+* [Issue #182](https://github.com/json-c/json-c/issues/182) - Link against libm when needed \
+* [Issue #183](https://github.com/json-c/json-c/issues/183) - Apply compile warning fix to master branch \
+* [Issue #184](https://github.com/json-c/json-c/issues/184) - Use only GCC-specific flags when compiling with GCC \
+* [Issue #185](https://github.com/json-c/json-c/issues/185) - compile error \
+* [Issue #186](https://github.com/json-c/json-c/issues/186) - Syntax error \
+* [Issue #187](https://github.com/json-c/json-c/issues/187) - array_list_get_idx and negative indexes. \
+* [Issue #188](https://github.com/json-c/json-c/issues/188) - json_object_object_foreach warnings \
+* [Issue #189](https://github.com/json-c/json-c/issues/189) - noisy json_object_from_file: error opening file \
+* [Issue #190](https://github.com/json-c/json-c/issues/190) - warning: initialization discards const qualifier from pointer target type \[enabled by default\] \
+* [Issue #192](https://github.com/json-c/json-c/issues/192) - json_tokener_parse accepts invalid JSON {"key": "value" , } \
+* [Issue #193](https://github.com/json-c/json-c/issues/193) - Make serialization format of doubles configurable \
+* [Issue #194](https://github.com/json-c/json-c/issues/194) - Add utility function for comparing json_objects \
+* [Issue #195](https://github.com/json-c/json-c/issues/195) - Call uselocale instead of setlocale \
+* [Issue #196](https://github.com/json-c/json-c/issues/196) - Performance improvements \
+* [Issue #197](https://github.com/json-c/json-c/issues/197) - Time for a new release? \
+* [Issue #198](https://github.com/json-c/json-c/issues/198) - Fix possible memory leak and remove superfluous NULL checks before free() \
+* [Issue #199](https://github.com/json-c/json-c/issues/199) - Fix build in Visual Studio \
+* [Issue #200](https://github.com/json-c/json-c/issues/200) - Add build scripts for CI platforms \
+* [Issue #201](https://github.com/json-c/json-c/issues/201) - disable forward-slash escaping? \
+* [Issue #202](https://github.com/json-c/json-c/issues/202) - Array with objects support \
+* [Issue #203](https://github.com/json-c/json-c/issues/203) - Add source position/coordinates to API \
+* [Issue #204](https://github.com/json-c/json-c/issues/204) - json-c/json.h not found \
+* [Issue #205](https://github.com/json-c/json-c/issues/205) - json-c Compiled with Visual Studios \
+* [Issue #206](https://github.com/json-c/json-c/issues/206) - what do i use in place of json_object_object_get? \
+* [Issue #207](https://github.com/json-c/json-c/issues/207) - Add support for property pairs directly added to arrays \
+* [Issue #208](https://github.com/json-c/json-c/issues/208) - Performance enhancements (mainly) to json_object_to_json_string() \
+* [Issue #209](https://github.com/json-c/json-c/issues/209) - fix regression from 2d549662be832da838aa063da2efa78ee3b99668 \
+* [Issue #210](https://github.com/json-c/json-c/issues/210) - Use size_t for arrays \
+* [Issue #211](https://github.com/json-c/json-c/issues/211) - Atomic updates for the refcount \
+* [Issue #212](https://github.com/json-c/json-c/issues/212) - Refcount doesn't work between threads \
+* [Issue #213](https://github.com/json-c/json-c/issues/213) - fix to compile with microsoft visual c++ 2010 \
+* [Issue #214](https://github.com/json-c/json-c/issues/214) - Some non-GNU systems support __sync_val_compare_and_swap \
+* [Issue #215](https://github.com/json-c/json-c/issues/215) - Build json-c for window 64 bit. \
+* [Issue #216](https://github.com/json-c/json-c/issues/216) - configure: check realloc with AC_CHECK_FUNCS() to fix cross-compilation. \
+* [Issue #217](https://github.com/json-c/json-c/issues/217) - Checking for functions in float.h \
+* [Issue #218](https://github.com/json-c/json-c/issues/218) - Use a macro to indicate C99 to the compiler \
+* [Issue #219](https://github.com/json-c/json-c/issues/219) - Fix various potential null ptr deref and int32 overflows \
+* [Issue #220](https://github.com/json-c/json-c/issues/220) - Add utility function for comparing json_objects \
+* [Issue #221](https://github.com/json-c/json-c/issues/221) - JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \
+* [Issue #222](https://github.com/json-c/json-c/issues/222) - Fix issue #221: JSON_C_TO_STRING_NOSLASHESCAPE works incorrectly \
+* [Issue #223](https://github.com/json-c/json-c/issues/223) - Clarify json_object_get_string documentation of NULL handling & return \
+* [Issue #224](https://github.com/json-c/json-c/issues/224) - json_tokener.c - all warnings being treated as errors \
+* [Issue #225](https://github.com/json-c/json-c/issues/225) - Hi, will you support clib as a "registry"? \
+* [Issue #227](https://github.com/json-c/json-c/issues/227) - Bump SOVERSION to 3 \
+* [Issue #228](https://github.com/json-c/json-c/issues/228) - avoid double slashes from json \
+* [Issue #229](https://github.com/json-c/json-c/issues/229) - configure fails: checking size of size_t... configure: error: cannot determine a size for size_t \
+* [Issue #230](https://github.com/json-c/json-c/issues/230) - Use stdint.h to check for size_t size \
+* [Issue #231](https://github.com/json-c/json-c/issues/231) - Fix size_t size check for first-time builds \
+* [Issue #232](https://github.com/json-c/json-c/issues/232) - tests/tests1: fix printf format for size_t arguments \
+* [Issue #233](https://github.com/json-c/json-c/issues/233) - Include stddef.h in json_object.h \
+* [Issue #234](https://github.com/json-c/json-c/issues/234) - Add public API to use userdata independently of custom serializer \
+* [Issue #235](https://github.com/json-c/json-c/issues/235) - Undefined symbols Error for architecture x86_64 on Mac \
+* [Issue #236](https://github.com/json-c/json-c/issues/236) - Building a project which uses json-c with flag -Wcast-qual causes compilation errors \
+* [Issue #237](https://github.com/json-c/json-c/issues/237) - handle escaped utf-8 \
+* [Issue #238](https://github.com/json-c/json-c/issues/238) - linkhash.c: optimised the table_free path \
+* [Issue #239](https://github.com/json-c/json-c/issues/239) - initialize null terminator of new printbuf \
+* [Issue #240](https://github.com/json-c/json-c/issues/240) - Compile error: Variable set but not used \
+* [Issue #241](https://github.com/json-c/json-c/issues/241) - getting error in date string 19\/07\/2016, fixed for error 19/07/2016 \
+* [Issue #242](https://github.com/json-c/json-c/issues/242) - json_tokener_parse error \
+* [Issue #243](https://github.com/json-c/json-c/issues/243) - Fix #165 \
+* [Issue #244](https://github.com/json-c/json-c/issues/244) - Error while compiling source from RHEL5, could you please help me to fix this \
+* [Issue #245](https://github.com/json-c/json-c/issues/245) - json-c compile in window xp \
+* [Issue #246](https://github.com/json-c/json-c/issues/246) - Mac: uselocale failed to build \
+* [Issue #247](https://github.com/json-c/json-c/issues/247) - json_object_array_del_idx function has segment fault error? \
+* [Issue #248](https://github.com/json-c/json-c/issues/248) - Minor changes in C source code \
+* [Issue #249](https://github.com/json-c/json-c/issues/249) - Improving README \
+* [Issue #250](https://github.com/json-c/json-c/issues/250) - Improving .gitignore \
+* [Issue #251](https://github.com/json-c/json-c/issues/251) - Adding a file for EditorConfig \
+* [Issue #252](https://github.com/json-c/json-c/issues/252) - Very minor changes not related to C source code \
+* [Issue #253](https://github.com/json-c/json-c/issues/253) - Adding a test with cppcheck for Travis CI \
+* [Issue #254](https://github.com/json-c/json-c/issues/254) - Very minor changes to some tests \
+* [Issue #255](https://github.com/json-c/json-c/issues/255) - Minor changes in C source code \
+* [Issue #256](https://github.com/json-c/json-c/issues/256) - Mailing list dead? \
+* [Issue #257](https://github.com/json-c/json-c/issues/257) - Defining a coding style \
+* [Issue #258](https://github.com/json-c/json-c/issues/258) - Enable CI services \
+* [Issue #259](https://github.com/json-c/json-c/issues/259) - Fails to parse valid json \
+* [Issue #260](https://github.com/json-c/json-c/issues/260) - Adding an object to itself \
+* [Issue #261](https://github.com/json-c/json-c/issues/261) - Lack of proper documentation \
+* [Issue #262](https://github.com/json-c/json-c/issues/262) - Add Cmakefile and fix compiler warning. \
+* [Issue #263](https://github.com/json-c/json-c/issues/263) - Compiler Warnings with VS2015 \
+* [Issue #264](https://github.com/json-c/json-c/issues/264) - successed in simple test while failed in my project \
+* [Issue #265](https://github.com/json-c/json-c/issues/265) - Conformance report for reference \
+* [Issue #266](https://github.com/json-c/json-c/issues/266) - crash perhaps related to reference counting \
+* [Issue #267](https://github.com/json-c/json-c/issues/267) - Removes me as Win32 maintainer, because I'm not. \
+* [Issue #268](https://github.com/json-c/json-c/issues/268) - Documentation of json_object_to_json_string gives no information about memory management \
+* [Issue #269](https://github.com/json-c/json-c/issues/269) - json_object_<type>_set(json_object *o,<type> value) API for value setting in json object private structure \
+* [Issue #270](https://github.com/json-c/json-c/issues/270) - new API json_object_new_double_f(doubel d,const char * fmt); \
+* [Issue #271](https://github.com/json-c/json-c/issues/271) - Cannot compile using CMake on macOS \
+* [Issue #273](https://github.com/json-c/json-c/issues/273) - fixed wrong object name in json_object_all_values_equal \
+* [Issue #274](https://github.com/json-c/json-c/issues/274) - Support for 64 bit pointers on Windows \
+* [Issue #275](https://github.com/json-c/json-c/issues/275) - Out-of-bounds read in json_tokener_parse_ex \
+* [Issue #276](https://github.com/json-c/json-c/issues/276) - ./configure for centos release 6.7(final) failure \
+* [Issue #277](https://github.com/json-c/json-c/issues/277) - Json object set xxx \
+* [Issue #278](https://github.com/json-c/json-c/issues/278) - Serialization of double with no fractional component drops trailing zero \
+* [Issue #279](https://github.com/json-c/json-c/issues/279) - Segmentation fault in array_list_length() \
+* [Issue #280](https://github.com/json-c/json-c/issues/280) - Should json_object_array_get_idx check whether input obj is array? \
+* [Issue #281](https://github.com/json-c/json-c/issues/281) - how to pretty print json-c? \
+* [Issue #282](https://github.com/json-c/json-c/issues/282) - ignore temporary files \
+* [Issue #283](https://github.com/json-c/json-c/issues/283) - json_pointer: add first revision based on RFC 6901 \
+* [Issue #284](https://github.com/json-c/json-c/issues/284) - Resusing json_tokener object \
+* [Issue #285](https://github.com/json-c/json-c/issues/285) - Revert "compat/strdup.h: move common compat check for strdup() to own \
+* [Issue #286](https://github.com/json-c/json-c/issues/286) - json_tokener_parse_ex() returns json_tokener_continue on zero-length string \
+* [Issue #287](https://github.com/json-c/json-c/issues/287) - json_pointer: extend setter & getter with printf() style arguments \
+* [Issue #288](https://github.com/json-c/json-c/issues/288) - Fix _GNU_SOURCE define for vasprintf \
+* [Issue #289](https://github.com/json-c/json-c/issues/289) - bugfix: floating point representaion without fractional part \
+* [Issue #290](https://github.com/json-c/json-c/issues/290) - duplicate an json_object \
+* [Issue #291](https://github.com/json-c/json-c/issues/291) - isspace assert error \
+* [Issue #292](https://github.com/json-c/json-c/issues/292) - configure error "./configure: line 13121: syntax error near unexpected token `-Wall'" \
+* [Issue #293](https://github.com/json-c/json-c/issues/293) - how to make with bitcode for ios \
+* [Issue #294](https://github.com/json-c/json-c/issues/294) - Adding UTF-8 validation. Fixes #122 \
+* [Issue #295](https://github.com/json-c/json-c/issues/295) - cross compile w/ mingw \
+* [Issue #296](https://github.com/json-c/json-c/issues/296) - Missing functions header in json_object.h \
+* [Issue #297](https://github.com/json-c/json-c/issues/297) - could not parse string to Json object? Like string str=\"helloworld;E\\test\\log\\;end\" \
+* [Issue #298](https://github.com/json-c/json-c/issues/298) - Building using CMake doesn't work \
+* [Issue #299](https://github.com/json-c/json-c/issues/299) - Improve json_object -> string performance \
+* [Issue #300](https://github.com/json-c/json-c/issues/300) - Running tests with MinGW build \
+* [Issue #301](https://github.com/json-c/json-c/issues/301) - How to deep copy json_object in C++ ? \
+* [Issue #302](https://github.com/json-c/json-c/issues/302) - json_tokener_parse_ex doesn't parse JSON values \
+* [Issue #303](https://github.com/json-c/json-c/issues/303) - fix doc in tokener header file \
+* [Issue #304](https://github.com/json-c/json-c/issues/304) - (.text+0x72846): undefined reference to `is_error' \
+* [Issue #305](https://github.com/json-c/json-c/issues/305) - Fix compilation without C-99 option \
+* [Issue #306](https://github.com/json-c/json-c/issues/306) - ./configure: line 12748 -error=deprecated-declarations \
+* [Issue #307](https://github.com/json-c/json-c/issues/307) - Memory leak in json_tokener_parse \
+* [Issue #308](https://github.com/json-c/json-c/issues/308) - AM_PROG_LIBTOOL not found on Linux \
+* [Issue #309](https://github.com/json-c/json-c/issues/309) - GCC 7 reports various -Wimplicit-fallthrough= errors \
+* [Issue #310](https://github.com/json-c/json-c/issues/310) - Add FALLTHRU comment to handle GCC7 warnings. \
+* [Issue #311](https://github.com/json-c/json-c/issues/311) - Fix error C3688 when compiling on Visual Studio 2015 \
+* [Issue #312](https://github.com/json-c/json-c/issues/312) - Fix CMake Build process improved for MinGW and MSYS2 \
+* [Issue #313](https://github.com/json-c/json-c/issues/313) - VERBOSE=1 make check; tests/test_util_file.test.c and tests/test_util_file.expected out of sync \
+* [Issue #315](https://github.com/json-c/json-c/issues/315) - Passing -1 to json_tokener_parse_ex is possibly unsafe \
+* [Issue #316](https://github.com/json-c/json-c/issues/316) - Memory Returned by json_object_to_json_string not freed \
+* [Issue #317](https://github.com/json-c/json-c/issues/317) - json_object_get_string gives segmentation error \
+* [Issue #318](https://github.com/json-c/json-c/issues/318) - PVS-Studio static analyzer analyze results \
+* [Issue #319](https://github.com/json-c/json-c/issues/319) - Windows: Fix dynamic library build with Visual Studio \
+* [Issue #320](https://github.com/json-c/json-c/issues/320) - Can't compile in Mac OS X El Capitan \
+* [Issue #321](https://github.com/json-c/json-c/issues/321) - build,cmake: fix vasprintf implicit definition and generate both static & shared libs \
+* [Issue #322](https://github.com/json-c/json-c/issues/322) - can not link with libjson-c.a \
+* [Issue #323](https://github.com/json-c/json-c/issues/323) - implicit fallthrough detected by gcc 7.1 \
+* [Issue #324](https://github.com/json-c/json-c/issues/324) - JsonPath like function? \
+* [Issue #325](https://github.com/json-c/json-c/issues/325) - Fix stack buffer overflow in json_object_double_to_json_string_format() \
+* [Issue #327](https://github.com/json-c/json-c/issues/327) - why json-c so hard to compile \
+* [Issue #328](https://github.com/json-c/json-c/issues/328) - json_object: implement json_object_deep_copy() function \
+* [Issue #329](https://github.com/json-c/json-c/issues/329) - build,cmake: build,cmake: rename libjson-c-static.a to libjson-c.a \
+* [Issue #330](https://github.com/json-c/json-c/issues/330) - tests: symlink basic tests to a single file that has the common code \
+* [Issue #331](https://github.com/json-c/json-c/issues/331) - Safe use of snprintf() / vsnprintf() for Visual studio, and thread-safety fix \
+* [Issue #332](https://github.com/json-c/json-c/issues/332) - Valgrind: invalid read after json_object_array_del_idx. \
+* [Issue #333](https://github.com/json-c/json-c/issues/333) - Replace obsolete AM_PROG_LIBTOOL \
+* [Issue #335](https://github.com/json-c/json-c/issues/335) - README.md: show build status tag from travis-ci.org \
+* [Issue #336](https://github.com/json-c/json-c/issues/336) - tests: fix tests in travis-ci.org \
+* [Issue #337](https://github.com/json-c/json-c/issues/337) - Synchronize "potentially racy" random seed in lh_char_hash() \
+* [Issue #338](https://github.com/json-c/json-c/issues/338) - implement json_object_int_inc(json_object *, int64_t) \
+* [Issue #339](https://github.com/json-c/json-c/issues/339) - Json schema validation \
+* [Issue #340](https://github.com/json-c/json-c/issues/340) - strerror_override: add extern "C" and JSON_EXPORT specifiers for Visual C++ compilers \
+* [Issue #341](https://github.com/json-c/json-c/issues/341) - character "/" parse as "\/" \
+* [Issue #342](https://github.com/json-c/json-c/issues/342) - No such file or directory "/usr/include/json.h" \
+* [Issue #343](https://github.com/json-c/json-c/issues/343) - Can't parse json \
+* [Issue #344](https://github.com/json-c/json-c/issues/344) - Fix Mingw build \
+* [Issue #345](https://github.com/json-c/json-c/issues/345) - Fix make dist and make distcheck \
+* [Issue #346](https://github.com/json-c/json-c/issues/346) - Clamp double to int32 when narrowing in json_object_get_int. \
+* [Issue #347](https://github.com/json-c/json-c/issues/347) - MSVC linker error json_c_strerror \
+* [Issue #348](https://github.com/json-c/json-c/issues/348) - why \
+* [Issue #349](https://github.com/json-c/json-c/issues/349) - `missing` is missing? \
+* [Issue #350](https://github.com/json-c/json-c/issues/350) - stderror-override and disable-shared \
+* [Issue #351](https://github.com/json-c/json-c/issues/351) - SIZE_T_MAX redefined from limits.h \
+* [Issue #352](https://github.com/json-c/json-c/issues/352) - `INSTALL` overrides an automake script. \
+* [Issue #353](https://github.com/json-c/json-c/issues/353) - Documentation issues \
+* [Issue #354](https://github.com/json-c/json-c/issues/354) - Fixes #351 #352 #353 \
+* [Issue #355](https://github.com/json-c/json-c/issues/355) - 1.make it can been compiled with Visual Studio 2010 by modify the CMakeList.txt and others \
+* [Issue #356](https://github.com/json-c/json-c/issues/356) - VS2008 test test_util_file.cpp err! \
+* [Issue #357](https://github.com/json-c/json-c/issues/357) - __json_c_strerror incompatibility with link-time optimization \
+* [Issue #358](https://github.com/json-c/json-c/issues/358) - make issue \
+* [Issue #359](https://github.com/json-c/json-c/issues/359) - update CMakeLists.txt for compile with visual studio at least 2010 \
+* [Issue #360](https://github.com/json-c/json-c/issues/360) - Use strtoll() to parse ints \
+* [Issue #361](https://github.com/json-c/json-c/issues/361) - Fix double to int cast overflow in json_object_get_int64. \
+* [Issue #362](https://github.com/json-c/json-c/issues/362) - CMake Package Config \
+* [Issue #363](https://github.com/json-c/json-c/issues/363) - Issue #338, add json_object_add_int functions \
+* [Issue #364](https://github.com/json-c/json-c/issues/364) - Cmake is Errir \
+* [Issue #365](https://github.com/json-c/json-c/issues/365) - added fallthrough for gcc7 \
+* [Issue #366](https://github.com/json-c/json-c/issues/366) - how to check the json string,crash! \
+* [Issue #367](https://github.com/json-c/json-c/issues/367) - Is json-c support "redirect" semantic? \
+* [Issue #368](https://github.com/json-c/json-c/issues/368) - Add examples \
+* [Issue #369](https://github.com/json-c/json-c/issues/369) - How to build json-c library for android? \
+* [Issue #370](https://github.com/json-c/json-c/issues/370) - Compiling using clang-cl \
+* [Issue #371](https://github.com/json-c/json-c/issues/371) - Invalid parsing for Infinity with json-c 0.12 \
+* [Issue #372](https://github.com/json-c/json-c/issues/372) - Json-c 0.12: Fixed Infinity bug \
+* [Issue #373](https://github.com/json-c/json-c/issues/373) - build: fix build on appveyor CI \
+* [Issue #374](https://github.com/json-c/json-c/issues/374) - Undefined symbols for architecture x86_64: \
+* [Issue #375](https://github.com/json-c/json-c/issues/375) - what would happened when json_object_object_add add the same key \
+* [Issue #376](https://github.com/json-c/json-c/issues/376) - Eclipse error \
+* [Issue #377](https://github.com/json-c/json-c/issues/377) - on gcc 7.2.0 on my linux distribution with json-c 2013-04-02 source \
+* [Issue #378](https://github.com/json-c/json-c/issues/378) - Eclipse: library (libjson-c) not found, but configured \
+* [Issue #379](https://github.com/json-c/json-c/issues/379) - error: this statement may fall through \[-Werror=implicit-fallthrough=\] \
+* [Issue #380](https://github.com/json-c/json-c/issues/380) - Build on Windows \
+* [Issue #381](https://github.com/json-c/json-c/issues/381) - Fix makedist \
+* [Issue #382](https://github.com/json-c/json-c/issues/382) - Memory leak for json_tokener_parse_ex for version 0.12.1 \
+* [Issue #383](https://github.com/json-c/json-c/issues/383) - Fix a compiler warning. \
+* [Issue #384](https://github.com/json-c/json-c/issues/384) - Fix a VS 2015 compiler warnings. \
diff --git a/issues_closed_for_0.14.md b/issues_closed_for_0.14.md
index bca934a..65096f0 100644
--- a/issues_closed_for_0.14.md
+++ b/issues_closed_for_0.14.md
@@ -14,189 +14,189 @@ sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),[Issue #\2](https:
Issues and Pull Requests closed for the 0.14 release (since commit d582d3a(2017-12-07) to a911439(2020-04-17))
-[Issue #122](https://github.com/json-c/json-c/issues/122) - Add utf-8 validation when parsing strings. \
-[Issue #139](https://github.com/json-c/json-c/issues/139) - json_object_from_file cannot accept max_depth \
-[Issue #143](https://github.com/json-c/json-c/issues/143) - RFE / enhancement for full 64-bit signed/unsigned support \
-[Issue #147](https://github.com/json-c/json-c/issues/147) - Please introduce soname bump if API changed \
-[Issue #166](https://github.com/json-c/json-c/issues/166) - Need a way to specify nesting depth when opening JSON file \
-[Issue #226](https://github.com/json-c/json-c/issues/226) - There is no json_object_new_null() \
-[Issue #314](https://github.com/json-c/json-c/issues/314) - new release ? \
-[Issue #326](https://github.com/json-c/json-c/issues/326) - Please extend api json_object_get_uint64 \
-[Issue #334](https://github.com/json-c/json-c/issues/334) - Switch json-c builds to use CMake \
-[Issue #386](https://github.com/json-c/json-c/issues/386) - Makefile: Add ACLOCAL_AMFLAGS \
-[Issue #387](https://github.com/json-c/json-c/issues/387) - doc: Use other doxygen feature to specify mainpage \
-[Issue #388](https://github.com/json-c/json-c/issues/388) - json_object: Add size_t json_object_sizeof() \
-[Issue #389](https://github.com/json-c/json-c/issues/389) - json_object: Avoid double free (and thus a segfault) when ref_count gets < 0 \
-[Issue #390](https://github.com/json-c/json-c/issues/390) - json_object: Add const size_t json_c_object_sizeof() \
-[Issue #391](https://github.com/json-c/json-c/issues/391) - Fix non-GNUC define for JSON_C_CONST_FUNCTION \
-[Issue #392](https://github.com/json-c/json-c/issues/392) - json_object: Avoid invalid free (and thus a segfault) when ref_count gets < 0 \
-[Issue #393](https://github.com/json-c/json-c/issues/393) - json_object_private: Use unsigned 32-bit integer type for refcount \
-[Issue #394](https://github.com/json-c/json-c/issues/394) - Problem serializing double \
-[Issue #395](https://github.com/json-c/json-c/issues/395) - Key gets modified if it contains "\" \
-[Issue #396](https://github.com/json-c/json-c/issues/396) - Build failure with no threads uClibc toolchain \
-[Issue #397](https://github.com/json-c/json-c/issues/397) - update json object with key. \
-[Issue #398](https://github.com/json-c/json-c/issues/398) - Build failed. \
-[Issue #399](https://github.com/json-c/json-c/issues/399) - Avoid uninitialized variable warnings \
-[Issue #400](https://github.com/json-c/json-c/issues/400) - How to generate static lib (.a) \
-[Issue #401](https://github.com/json-c/json-c/issues/401) - Warnings with Valgrind \
-[Issue #402](https://github.com/json-c/json-c/issues/402) - Add fuzzers from OSS-Fuzz \
-[Issue #403](https://github.com/json-c/json-c/issues/403) - Segmentation fault when double quotes is used \
-[Issue #404](https://github.com/json-c/json-c/issues/404) - valgrind: memory leak \
-[Issue #405](https://github.com/json-c/json-c/issues/405) - Missing API to determine an object is empty \
-[Issue #406](https://github.com/json-c/json-c/issues/406) - Undefine NDEBUG for tests \
-[Issue #407](https://github.com/json-c/json-c/issues/407) - json_tokener_parse is crash \
-[Issue #408](https://github.com/json-c/json-c/issues/408) - bug in array_list_del_idx when array_list_length()==1 \
-[Issue #410](https://github.com/json-c/json-c/issues/410) - Fixed typos \
-[Issue #411](https://github.com/json-c/json-c/issues/411) - Crash- signal SIGSEGV, Segmentation fault. ../sysdeps/x86_64/strlen.S: No such file or directory. \
-[Issue #412](https://github.com/json-c/json-c/issues/412) - json_type changes during inter process communication. \
-[Issue #413](https://github.com/json-c/json-c/issues/413) - how to read object of type `json_object *` in c++ \
-[Issue #414](https://github.com/json-c/json-c/issues/414) - [Question] How JSON-c stores the serialized data in memory? \
-[Issue #415](https://github.com/json-c/json-c/issues/415) - Resolve windows name conflict \
-[Issue #416](https://github.com/json-c/json-c/issues/416) - segmentation fault in json_tokener_parse \
-[Issue #417](https://github.com/json-c/json-c/issues/417) - json_tokener_parse json_object_object_get_ex with string value which is json string \
-[Issue #418](https://github.com/json-c/json-c/issues/418) - json_object_from_* return value documented incorrectly \
-[Issue #419](https://github.com/json-c/json-c/issues/419) - Suggestion: document (and define) that json_object_put() accepts NULL pointer to object \
-[Issue #420](https://github.com/json-c/json-c/issues/420) - arraylist: Fixed names of parameters for callback function \
-[Issue #421](https://github.com/json-c/json-c/issues/421) - install json_object_iterator.h header file \
-[Issue #422](https://github.com/json-c/json-c/issues/422) - json_object_get_double() does not set errno when there is no valid conversion \
-[Issue #423](https://github.com/json-c/json-c/issues/423) - memory leak \
-[Issue #424](https://github.com/json-c/json-c/issues/424) - Parse string contains "\" or "/" errors \
-[Issue #425](https://github.com/json-c/json-c/issues/425) - what this is? \
-[Issue #426](https://github.com/json-c/json-c/issues/426) - __deprecated not supported on clang. \
-[Issue #427](https://github.com/json-c/json-c/issues/427) - CMake: builds involving this target will not be correct \
-[Issue #430](https://github.com/json-c/json-c/issues/430) - json_object_object_del() and Segmentation fault \
-[Issue #431](https://github.com/json-c/json-c/issues/431) - cmake: Bump required version \
-[Issue #432](https://github.com/json-c/json-c/issues/432) - The real CMake support. \
-[Issue #433](https://github.com/json-c/json-c/issues/433) - The real CMake support. \
-[Issue #434](https://github.com/json-c/json-c/issues/434) - The real CMake support \
-[Issue #435](https://github.com/json-c/json-c/issues/435) - json_object_object_del() segmentation fault \
-[Issue #436](https://github.com/json-c/json-c/issues/436) - Improve pkgconfig setting \
-[Issue #437](https://github.com/json-c/json-c/issues/437) - Bad link in README.md \
-[Issue #438](https://github.com/json-c/json-c/issues/438) - Bad link in README.html \
-[Issue #439](https://github.com/json-c/json-c/issues/439) - reserved identifier violation \
-[Issue #440](https://github.com/json-c/json-c/issues/440) - Use of angle brackets around file names for include statements \
-[Issue #441](https://github.com/json-c/json-c/issues/441) - fix c flag loss during cmake building \
-[Issue #442](https://github.com/json-c/json-c/issues/442) - error in configure file \
-[Issue #443](https://github.com/json-c/json-c/issues/443) - remove pretty spaces when using pretty tabs \
-[Issue #444](https://github.com/json-c/json-c/issues/444) - Document refcount of json_tokener_parse_ex return \
-[Issue #445](https://github.com/json-c/json-c/issues/445) - Add missing "make check" target to cmake config \
-[Issue #446](https://github.com/json-c/json-c/issues/446) - Forward slashes get escaped \
-[Issue #448](https://github.com/json-c/json-c/issues/448) - Buffer overflow in json-c \
-[Issue #449](https://github.com/json-c/json-c/issues/449) - Need of json_type_int64 returned by json_object_get_type() \
-[Issue #450](https://github.com/json-c/json-c/issues/450) - Allow use json-c cmake as subproject \
-[Issue #452](https://github.com/json-c/json-c/issues/452) - Update README.md \
-[Issue #453](https://github.com/json-c/json-c/issues/453) - Fixed misalignment in JSON string due to space after \n being printed... \
-[Issue #454](https://github.com/json-c/json-c/issues/454) - json_object_private: save 8 bytes in struct json_object in 64-bit arc… \
-[Issue #455](https://github.com/json-c/json-c/issues/455) - index.html:fix dead link \
-[Issue #456](https://github.com/json-c/json-c/issues/456) - STYLE.txt:remove executable permissions \
-[Issue #457](https://github.com/json-c/json-c/issues/457) - .gitignore:add build directory \
-[Issue #458](https://github.com/json-c/json-c/issues/458) - README.md:fix dead "file.html" link \
-[Issue #459](https://github.com/json-c/json-c/issues/459) - README.html:fix link to Doxygen docs, remove WIN32 link \
-[Issue #460](https://github.com/json-c/json-c/issues/460) - No docs for json_object_new_string_len() \
-[Issue #461](https://github.com/json-c/json-c/issues/461) - json_object.c:set errno in json_object_get_double() \
-[Issue #462](https://github.com/json-c/json-c/issues/462) - json_object.h:document json_object_new_string_len() \
-[Issue #463](https://github.com/json-c/json-c/issues/463) - please check newlocale api first argument valuse. \
-[Issue #465](https://github.com/json-c/json-c/issues/465) - CMakeLists.txt doesn't contain json_object_iterator.h which json.h includes \
-[Issue #466](https://github.com/json-c/json-c/issues/466) - configure:3610: error: C compiler cannot create executables \
-[Issue #467](https://github.com/json-c/json-c/issues/467) - Fix compiler warnings \
-[Issue #468](https://github.com/json-c/json-c/issues/468) - Fix compiler warnings \
-[Issue #469](https://github.com/json-c/json-c/issues/469) - Build under alpine with pecl install & docker-php-ext-enable? \
-[Issue #470](https://github.com/json-c/json-c/issues/470) - cfuhash_foreach_remove doesn't upate cfuhash_num_entries \
-[Issue #472](https://github.com/json-c/json-c/issues/472) - Segmentation fault in json_object_iter_begin \
-[Issue #473](https://github.com/json-c/json-c/issues/473) - Convert ChangeLog to valid UTF-8 encoding. \
-[Issue #474](https://github.com/json-c/json-c/issues/474) - Installation directories empty with CMake in pkg-config. \
-[Issue #475](https://github.com/json-c/json-c/issues/475) - improvement proposal for json_object_object_foreach \
-[Issue #477](https://github.com/json-c/json-c/issues/477) - Hang/Crash with large strings \
-[Issue #478](https://github.com/json-c/json-c/issues/478) - json_object_get_string_len returns 0 when value is number \
-[Issue #479](https://github.com/json-c/json-c/issues/479) - I want to use it in iOS or Android but I can't compile \
-[Issue #480](https://github.com/json-c/json-c/issues/480) - json-c-0.12.1 failed making from source code \
-[Issue #481](https://github.com/json-c/json-c/issues/481) - error while loading shared libraries: libjson-c.so.4 \
-[Issue #482](https://github.com/json-c/json-c/issues/482) - Error "double free or corruption" after free() \
-[Issue #483](https://github.com/json-c/json-c/issues/483) - compatible with rarely-used Chinese characters in GBK charset \
-[Issue #485](https://github.com/json-c/json-c/issues/485) - Install CMake module files \
-[Issue #486](https://github.com/json-c/json-c/issues/486) - In the case of negative double value, it is formatted without including ".0" \
-[Issue #488](https://github.com/json-c/json-c/issues/488) - Some APIs are not exported when built as shared lib on Win32 \
-[Issue #489](https://github.com/json-c/json-c/issues/489) - Don't use -Werror by default \
-[Issue #490](https://github.com/json-c/json-c/issues/490) - do not compile with -Werror by default \
-[Issue #491](https://github.com/json-c/json-c/issues/491) - build: add option --disable-werror to configure \
-[Issue #492](https://github.com/json-c/json-c/issues/492) - lack some quick usage in readme \
-[Issue #494](https://github.com/json-c/json-c/issues/494) - Code generator? \
-[Issue #495](https://github.com/json-c/json-c/issues/495) - README.md:fix 2 typos \
-[Issue #496](https://github.com/json-c/json-c/issues/496) - json_pointer.h:suggest minor grammar improvement for pointer doc \
-[Issue #497](https://github.com/json-c/json-c/issues/497) - add common header for all tests \
-[Issue #498](https://github.com/json-c/json-c/issues/498) - double_serializer_test fails (with valgrind) \
-[Issue #499](https://github.com/json-c/json-c/issues/499) - .travis.yml:test on more recent clang and gcc versions \
-[Issue #500](https://github.com/json-c/json-c/issues/500) - test/Makefile.am:add missing deps for test1 and test2 \
-[Issue #501](https://github.com/json-c/json-c/issues/501) - undefine NDEBUG for tests \
-[Issue #502](https://github.com/json-c/json-c/issues/502) - configure error \
-[Issue #503](https://github.com/json-c/json-c/issues/503) - json-c retuns OK when Invalid json string is passed \
-[Issue #504](https://github.com/json-c/json-c/issues/504) - json_object_put coredump \
-[Issue #505](https://github.com/json-c/json-c/issues/505) - Add vcpkg installation instructions \
-[Issue #506](https://github.com/json-c/json-c/issues/506) - Cannot parse more than one object \
-[Issue #509](https://github.com/json-c/json-c/issues/509) - Sometimes a double value is not serialized \
-[Issue #510](https://github.com/json-c/json-c/issues/510) - Bump so-name and improve CMake \
-[Issue #511](https://github.com/json-c/json-c/issues/511) - Reduce lines for better optimization \
-[Issue #512](https://github.com/json-c/json-c/issues/512) - Properly append to CMAKE_C_FLAGS string \
-[Issue #513](https://github.com/json-c/json-c/issues/513) - What does `userdata` means?And what is the case we can use it? \
-[Issue #514](https://github.com/json-c/json-c/issues/514) - Json c 0.13 \
-[Issue #515](https://github.com/json-c/json-c/issues/515) - Mies suomesta fixes segfaults and logic errors \
-[Issue #516](https://github.com/json-c/json-c/issues/516) - Lja slight mods \
-[Issue #518](https://github.com/json-c/json-c/issues/518) - Escape character "\\003\", get unexpected value \
-[Issue #519](https://github.com/json-c/json-c/issues/519) - Add test case obj token \
-[Issue #520](https://github.com/json-c/json-c/issues/520) - Adding type uint64 \
-[Issue #521](https://github.com/json-c/json-c/issues/521) - build cmake windows 10 \
-[Issue #522](https://github.com/json-c/json-c/issues/522) - update json_visit testcase \
-[Issue #523](https://github.com/json-c/json-c/issues/523) - update tsetcase for tokener_c \
-[Issue #524](https://github.com/json-c/json-c/issues/524) - Increase coverage \
-[Issue #525](https://github.com/json-c/json-c/issues/525) - update pointer test case \
-[Issue #526](https://github.com/json-c/json-c/issues/526) - Increased the test coverage of printbuf.c 82% to 92%. \
-[Issue #527](https://github.com/json-c/json-c/issues/527) - Arraylist testcase \
-[Issue #528](https://github.com/json-c/json-c/issues/528) - Solve issue #108. Skip \u0000 while parsing. \
-[Issue #529](https://github.com/json-c/json-c/issues/529) - Increased the test coverage of json_c_version.c 0% to 100%. \
-[Issue #530](https://github.com/json-c/json-c/issues/530) - validate utf-8 string before parse \
-[Issue #531](https://github.com/json-c/json-c/issues/531) - validate utf-8 string \
-[Issue #532](https://github.com/json-c/json-c/issues/532) - json_object_object_get_ex returning the original object \
-[Issue #533](https://github.com/json-c/json-c/issues/533) - Fix "make check" \
-[Issue #535](https://github.com/json-c/json-c/issues/535) - short string optimization: excessive array length \
-[Issue #536](https://github.com/json-c/json-c/issues/536) - add json_object_new_null() \
-[Issue #538](https://github.com/json-c/json-c/issues/538) - update shortstring and arraylist parameters \
-[Issue #539](https://github.com/json-c/json-c/issues/539) - double serializes to the old value after set_double \
-[Issue #541](https://github.com/json-c/json-c/issues/541) - add coveralls auto tool to json-c \
-[Issue #542](https://github.com/json-c/json-c/issues/542) - add uint64 data to json-c \
-[Issue #543](https://github.com/json-c/json-c/issues/543) - Readme \
-[Issue #544](https://github.com/json-c/json-c/issues/544) - Increase distcheck target in cmake \
-[Issue #545](https://github.com/json-c/json-c/issues/545) - add doc target in cmake \
-[Issue #546](https://github.com/json-c/json-c/issues/546) - Add uninstall target in cmake \
-[Issue #547](https://github.com/json-c/json-c/issues/547) - modify json-c default build type, and fix up the assert() errors in t… \
-[Issue #548](https://github.com/json-c/json-c/issues/548) - Solve some problems about cmake build type (debug/release) \
-[Issue #549](https://github.com/json-c/json-c/issues/549) - lib installation issues \
-[Issue #550](https://github.com/json-c/json-c/issues/550) - Format codes with clang-format tool? \
-[Issue #551](https://github.com/json-c/json-c/issues/551) - Allow hexadecimal number format convention parsing \
-[Issue #553](https://github.com/json-c/json-c/issues/553) - Fix/clang ubsan \
-[Issue #554](https://github.com/json-c/json-c/issues/554) - RFC 8259 compatibility mode \
-[Issue #555](https://github.com/json-c/json-c/issues/555) - Format json-c with clang-format tool \
-[Issue #556](https://github.com/json-c/json-c/issues/556) - Fixes various Wreturn-type and Wimplicit-fallthrough errors on Mingw-w64 \
-[Issue #557](https://github.com/json-c/json-c/issues/557) - Add option in CMAKE to not build documentation \
-[Issue #558](https://github.com/json-c/json-c/issues/558) - modify the doc target message \
-[Issue #559](https://github.com/json-c/json-c/issues/559) - json_c_visit() not exported on Windows \
-[Issue #560](https://github.com/json-c/json-c/issues/560) - error: implicit declaration of function '_strtoi64' \
-[Issue #561](https://github.com/json-c/json-c/issues/561) - add the badge in README.md and test the coveralls \
-[Issue #562](https://github.com/json-c/json-c/issues/562) - Bugfix and testcases supplements \
-[Issue #563](https://github.com/json-c/json-c/issues/563) - Changed order of calloc args to match stdlib \
-[Issue #564](https://github.com/json-c/json-c/issues/564) - Remove autogenerated files \
-[Issue #565](https://github.com/json-c/json-c/issues/565) - test the CI and ignore this PR \
-[Issue #566](https://github.com/json-c/json-c/issues/566) - add the json_types.h to Makefile.am \
-[Issue #567](https://github.com/json-c/json-c/issues/567) - Install json_types.h with autotools build as well. \
-[Issue #568](https://github.com/json-c/json-c/issues/568) - Adding better support to MinGW \
-[Issue #569](https://github.com/json-c/json-c/issues/569) - Handling of -Bsymbolic-function in CMakeLists.txt is deficient \
-[Issue #571](https://github.com/json-c/json-c/issues/571) - CMake: Bump SONAME to 5. \
-[Issue #572](https://github.com/json-c/json-c/issues/572) - Small fixes to CMakeLists \
-[Issue #573](https://github.com/json-c/json-c/issues/573) - Fix coveralls submission. \
-[Issue #574](https://github.com/json-c/json-c/issues/574) - autogen.sh missing from repository \
-[Issue #575](https://github.com/json-c/json-c/issues/575) - Small cosmetics. \
-[Issue #576](https://github.com/json-c/json-c/issues/576) - Test coverage for json_c_version. \
-[Issue #577](https://github.com/json-c/json-c/issues/577) - Be verbose on failing json_c_version test. \
-[Issue #578](https://github.com/json-c/json-c/issues/578) - CMake: Install pkgconfig file in proper location by default \
-[Issue #579](https://github.com/json-c/json-c/issues/579) - Enforce strict prototypes. \
-[Issue #580](https://github.com/json-c/json-c/issues/580) - Fix CMake tests for enforced strict prototypes. \
-[Issue #581](https://github.com/json-c/json-c/issues/581) - CMakeLists: do not enforce strict prototypes on Windows. \
+* [Issue #122](https://github.com/json-c/json-c/issues/122) - Add utf-8 validation when parsing strings. \
+* [Issue #139](https://github.com/json-c/json-c/issues/139) - json_object_from_file cannot accept max_depth \
+* [Issue #143](https://github.com/json-c/json-c/issues/143) - RFE / enhancement for full 64-bit signed/unsigned support \
+* [Issue #147](https://github.com/json-c/json-c/issues/147) - Please introduce soname bump if API changed \
+* [Issue #166](https://github.com/json-c/json-c/issues/166) - Need a way to specify nesting depth when opening JSON file \
+* [Issue #226](https://github.com/json-c/json-c/issues/226) - There is no json_object_new_null() \
+* [Issue #314](https://github.com/json-c/json-c/issues/314) - new release ? \
+* [Issue #326](https://github.com/json-c/json-c/issues/326) - Please extend api json_object_get_uint64 \
+* [Issue #334](https://github.com/json-c/json-c/issues/334) - Switch json-c builds to use CMake \
+* [Issue #386](https://github.com/json-c/json-c/issues/386) - Makefile: Add ACLOCAL_AMFLAGS \
+* [Issue #387](https://github.com/json-c/json-c/issues/387) - doc: Use other doxygen feature to specify mainpage \
+* [Issue #388](https://github.com/json-c/json-c/issues/388) - json_object: Add size_t json_object_sizeof() \
+* [Issue #389](https://github.com/json-c/json-c/issues/389) - json_object: Avoid double free (and thus a segfault) when ref_count gets < 0 \
+* [Issue #390](https://github.com/json-c/json-c/issues/390) - json_object: Add const size_t json_c_object_sizeof() \
+* [Issue #391](https://github.com/json-c/json-c/issues/391) - Fix non-GNUC define for JSON_C_CONST_FUNCTION \
+* [Issue #392](https://github.com/json-c/json-c/issues/392) - json_object: Avoid invalid free (and thus a segfault) when ref_count gets < 0 \
+* [Issue #393](https://github.com/json-c/json-c/issues/393) - json_object_private: Use unsigned 32-bit integer type for refcount \
+* [Issue #394](https://github.com/json-c/json-c/issues/394) - Problem serializing double \
+* [Issue #395](https://github.com/json-c/json-c/issues/395) - Key gets modified if it contains "\" \
+* [Issue #396](https://github.com/json-c/json-c/issues/396) - Build failure with no threads uClibc toolchain \
+* [Issue #397](https://github.com/json-c/json-c/issues/397) - update json object with key. \
+* [Issue #398](https://github.com/json-c/json-c/issues/398) - Build failed. \
+* [Issue #399](https://github.com/json-c/json-c/issues/399) - Avoid uninitialized variable warnings \
+* [Issue #400](https://github.com/json-c/json-c/issues/400) - How to generate static lib (.a) \
+* [Issue #401](https://github.com/json-c/json-c/issues/401) - Warnings with Valgrind \
+* [Issue #402](https://github.com/json-c/json-c/issues/402) - Add fuzzers from OSS-Fuzz \
+* [Issue #403](https://github.com/json-c/json-c/issues/403) - Segmentation fault when double quotes is used \
+* [Issue #404](https://github.com/json-c/json-c/issues/404) - valgrind: memory leak \
+* [Issue #405](https://github.com/json-c/json-c/issues/405) - Missing API to determine an object is empty \
+* [Issue #406](https://github.com/json-c/json-c/issues/406) - Undefine NDEBUG for tests \
+* [Issue #407](https://github.com/json-c/json-c/issues/407) - json_tokener_parse is crash \
+* [Issue #408](https://github.com/json-c/json-c/issues/408) - bug in array_list_del_idx when array_list_length()==1 \
+* [Issue #410](https://github.com/json-c/json-c/issues/410) - Fixed typos \
+* [Issue #411](https://github.com/json-c/json-c/issues/411) - Crash- signal SIGSEGV, Segmentation fault. ../sysdeps/x86_64/strlen.S: No such file or directory. \
+* [Issue #412](https://github.com/json-c/json-c/issues/412) - json_type changes during inter process communication. \
+* [Issue #413](https://github.com/json-c/json-c/issues/413) - how to read object of type `json_object *` in c++ \
+* [Issue #414](https://github.com/json-c/json-c/issues/414) - [Question] How JSON-c stores the serialized data in memory? \
+* [Issue #415](https://github.com/json-c/json-c/issues/415) - Resolve windows name conflict \
+* [Issue #416](https://github.com/json-c/json-c/issues/416) - segmentation fault in json_tokener_parse \
+* [Issue #417](https://github.com/json-c/json-c/issues/417) - json_tokener_parse json_object_object_get_ex with string value which is json string \
+* [Issue #418](https://github.com/json-c/json-c/issues/418) - json_object_from_* return value documented incorrectly \
+* [Issue #419](https://github.com/json-c/json-c/issues/419) - Suggestion: document (and define) that json_object_put() accepts NULL pointer to object \
+* [Issue #420](https://github.com/json-c/json-c/issues/420) - arraylist: Fixed names of parameters for callback function \
+* [Issue #421](https://github.com/json-c/json-c/issues/421) - install json_object_iterator.h header file \
+* [Issue #422](https://github.com/json-c/json-c/issues/422) - json_object_get_double() does not set errno when there is no valid conversion \
+* [Issue #423](https://github.com/json-c/json-c/issues/423) - memory leak \
+* [Issue #424](https://github.com/json-c/json-c/issues/424) - Parse string contains "\" or "/" errors \
+* [Issue #425](https://github.com/json-c/json-c/issues/425) - what this is? \
+* [Issue #426](https://github.com/json-c/json-c/issues/426) - __deprecated not supported on clang. \
+* [Issue #427](https://github.com/json-c/json-c/issues/427) - CMake: builds involving this target will not be correct \
+* [Issue #430](https://github.com/json-c/json-c/issues/430) - json_object_object_del() and Segmentation fault \
+* [Issue #431](https://github.com/json-c/json-c/issues/431) - cmake: Bump required version \
+* [Issue #432](https://github.com/json-c/json-c/issues/432) - The real CMake support. \
+* [Issue #433](https://github.com/json-c/json-c/issues/433) - The real CMake support. \
+* [Issue #434](https://github.com/json-c/json-c/issues/434) - The real CMake support \
+* [Issue #435](https://github.com/json-c/json-c/issues/435) - json_object_object_del() segmentation fault \
+* [Issue #436](https://github.com/json-c/json-c/issues/436) - Improve pkgconfig setting \
+* [Issue #437](https://github.com/json-c/json-c/issues/437) - Bad link in README.md \
+* [Issue #438](https://github.com/json-c/json-c/issues/438) - Bad link in README.html \
+* [Issue #439](https://github.com/json-c/json-c/issues/439) - reserved identifier violation \
+* [Issue #440](https://github.com/json-c/json-c/issues/440) - Use of angle brackets around file names for include statements \
+* [Issue #441](https://github.com/json-c/json-c/issues/441) - fix c flag loss during cmake building \
+* [Issue #442](https://github.com/json-c/json-c/issues/442) - error in configure file \
+* [Issue #443](https://github.com/json-c/json-c/issues/443) - remove pretty spaces when using pretty tabs \
+* [Issue #444](https://github.com/json-c/json-c/issues/444) - Document refcount of json_tokener_parse_ex return \
+* [Issue #445](https://github.com/json-c/json-c/issues/445) - Add missing "make check" target to cmake config \
+* [Issue #446](https://github.com/json-c/json-c/issues/446) - Forward slashes get escaped \
+* [Issue #448](https://github.com/json-c/json-c/issues/448) - Buffer overflow in json-c \
+* [Issue #449](https://github.com/json-c/json-c/issues/449) - Need of json_type_int64 returned by json_object_get_type() \
+* [Issue #450](https://github.com/json-c/json-c/issues/450) - Allow use json-c cmake as subproject \
+* [Issue #452](https://github.com/json-c/json-c/issues/452) - Update README.md \
+* [Issue #453](https://github.com/json-c/json-c/issues/453) - Fixed misalignment in JSON string due to space after \n being printed... \
+* [Issue #454](https://github.com/json-c/json-c/issues/454) - json_object_private: save 8 bytes in struct json_object in 64-bit arc… \
+* [Issue #455](https://github.com/json-c/json-c/issues/455) - index.html:fix dead link \
+* [Issue #456](https://github.com/json-c/json-c/issues/456) - STYLE.txt:remove executable permissions \
+* [Issue #457](https://github.com/json-c/json-c/issues/457) - .gitignore:add build directory \
+* [Issue #458](https://github.com/json-c/json-c/issues/458) - README.md:fix dead "file.html" link \
+* [Issue #459](https://github.com/json-c/json-c/issues/459) - README.html:fix link to Doxygen docs, remove WIN32 link \
+* [Issue #460](https://github.com/json-c/json-c/issues/460) - No docs for json_object_new_string_len() \
+* [Issue #461](https://github.com/json-c/json-c/issues/461) - json_object.c:set errno in json_object_get_double() \
+* [Issue #462](https://github.com/json-c/json-c/issues/462) - json_object.h:document json_object_new_string_len() \
+* [Issue #463](https://github.com/json-c/json-c/issues/463) - please check newlocale api first argument valuse. \
+* [Issue #465](https://github.com/json-c/json-c/issues/465) - CMakeLists.txt doesn't contain json_object_iterator.h which json.h includes \
+* [Issue #466](https://github.com/json-c/json-c/issues/466) - configure:3610: error: C compiler cannot create executables \
+* [Issue #467](https://github.com/json-c/json-c/issues/467) - Fix compiler warnings \
+* [Issue #468](https://github.com/json-c/json-c/issues/468) - Fix compiler warnings \
+* [Issue #469](https://github.com/json-c/json-c/issues/469) - Build under alpine with pecl install & docker-php-ext-enable? \
+* [Issue #470](https://github.com/json-c/json-c/issues/470) - cfuhash_foreach_remove doesn't upate cfuhash_num_entries \
+* [Issue #472](https://github.com/json-c/json-c/issues/472) - Segmentation fault in json_object_iter_begin \
+* [Issue #473](https://github.com/json-c/json-c/issues/473) - Convert ChangeLog to valid UTF-8 encoding. \
+* [Issue #474](https://github.com/json-c/json-c/issues/474) - Installation directories empty with CMake in pkg-config. \
+* [Issue #475](https://github.com/json-c/json-c/issues/475) - improvement proposal for json_object_object_foreach \
+* [Issue #477](https://github.com/json-c/json-c/issues/477) - Hang/Crash with large strings \
+* [Issue #478](https://github.com/json-c/json-c/issues/478) - json_object_get_string_len returns 0 when value is number \
+* [Issue #479](https://github.com/json-c/json-c/issues/479) - I want to use it in iOS or Android but I can't compile \
+* [Issue #480](https://github.com/json-c/json-c/issues/480) - json-c-0.12.1 failed making from source code \
+* [Issue #481](https://github.com/json-c/json-c/issues/481) - error while loading shared libraries: libjson-c.so.4 \
+* [Issue #482](https://github.com/json-c/json-c/issues/482) - Error "double free or corruption" after free() \
+* [Issue #483](https://github.com/json-c/json-c/issues/483) - compatible with rarely-used Chinese characters in GBK charset \
+* [Issue #485](https://github.com/json-c/json-c/issues/485) - Install CMake module files \
+* [Issue #486](https://github.com/json-c/json-c/issues/486) - In the case of negative double value, it is formatted without including ".0" \
+* [Issue #488](https://github.com/json-c/json-c/issues/488) - Some APIs are not exported when built as shared lib on Win32 \
+* [Issue #489](https://github.com/json-c/json-c/issues/489) - Don't use -Werror by default \
+* [Issue #490](https://github.com/json-c/json-c/issues/490) - do not compile with -Werror by default \
+* [Issue #491](https://github.com/json-c/json-c/issues/491) - build: add option --disable-werror to configure \
+* [Issue #492](https://github.com/json-c/json-c/issues/492) - lack some quick usage in readme \
+* [Issue #494](https://github.com/json-c/json-c/issues/494) - Code generator? \
+* [Issue #495](https://github.com/json-c/json-c/issues/495) - README.md:fix 2 typos \
+* [Issue #496](https://github.com/json-c/json-c/issues/496) - json_pointer.h:suggest minor grammar improvement for pointer doc \
+* [Issue #497](https://github.com/json-c/json-c/issues/497) - add common header for all tests \
+* [Issue #498](https://github.com/json-c/json-c/issues/498) - double_serializer_test fails (with valgrind) \
+* [Issue #499](https://github.com/json-c/json-c/issues/499) - .travis.yml:test on more recent clang and gcc versions \
+* [Issue #500](https://github.com/json-c/json-c/issues/500) - test/Makefile.am:add missing deps for test1 and test2 \
+* [Issue #501](https://github.com/json-c/json-c/issues/501) - undefine NDEBUG for tests \
+* [Issue #502](https://github.com/json-c/json-c/issues/502) - configure error \
+* [Issue #503](https://github.com/json-c/json-c/issues/503) - json-c retuns OK when Invalid json string is passed \
+* [Issue #504](https://github.com/json-c/json-c/issues/504) - json_object_put coredump \
+* [Issue #505](https://github.com/json-c/json-c/issues/505) - Add vcpkg installation instructions \
+* [Issue #506](https://github.com/json-c/json-c/issues/506) - Cannot parse more than one object \
+* [Issue #509](https://github.com/json-c/json-c/issues/509) - Sometimes a double value is not serialized \
+* [Issue #510](https://github.com/json-c/json-c/issues/510) - Bump so-name and improve CMake \
+* [Issue #511](https://github.com/json-c/json-c/issues/511) - Reduce lines for better optimization \
+* [Issue #512](https://github.com/json-c/json-c/issues/512) - Properly append to CMAKE_C_FLAGS string \
+* [Issue #513](https://github.com/json-c/json-c/issues/513) - What does `userdata` means?And what is the case we can use it? \
+* [Issue #514](https://github.com/json-c/json-c/issues/514) - Json c 0.13 \
+* [Issue #515](https://github.com/json-c/json-c/issues/515) - Mies suomesta fixes segfaults and logic errors \
+* [Issue #516](https://github.com/json-c/json-c/issues/516) - Lja slight mods \
+* [Issue #518](https://github.com/json-c/json-c/issues/518) - Escape character "\\003\", get unexpected value \
+* [Issue #519](https://github.com/json-c/json-c/issues/519) - Add test case obj token \
+* [Issue #520](https://github.com/json-c/json-c/issues/520) - Adding type uint64 \
+* [Issue #521](https://github.com/json-c/json-c/issues/521) - build cmake windows 10 \
+* [Issue #522](https://github.com/json-c/json-c/issues/522) - update json_visit testcase \
+* [Issue #523](https://github.com/json-c/json-c/issues/523) - update tsetcase for tokener_c \
+* [Issue #524](https://github.com/json-c/json-c/issues/524) - Increase coverage \
+* [Issue #525](https://github.com/json-c/json-c/issues/525) - update pointer test case \
+* [Issue #526](https://github.com/json-c/json-c/issues/526) - Increased the test coverage of printbuf.c 82% to 92%. \
+* [Issue #527](https://github.com/json-c/json-c/issues/527) - Arraylist testcase \
+* [Issue #528](https://github.com/json-c/json-c/issues/528) - Solve issue #108. Skip \u0000 while parsing. \
+* [Issue #529](https://github.com/json-c/json-c/issues/529) - Increased the test coverage of json_c_version.c 0% to 100%. \
+* [Issue #530](https://github.com/json-c/json-c/issues/530) - validate utf-8 string before parse \
+* [Issue #531](https://github.com/json-c/json-c/issues/531) - validate utf-8 string \
+* [Issue #532](https://github.com/json-c/json-c/issues/532) - json_object_object_get_ex returning the original object \
+* [Issue #533](https://github.com/json-c/json-c/issues/533) - Fix "make check" \
+* [Issue #535](https://github.com/json-c/json-c/issues/535) - short string optimization: excessive array length \
+* [Issue #536](https://github.com/json-c/json-c/issues/536) - add json_object_new_null() \
+* [Issue #538](https://github.com/json-c/json-c/issues/538) - update shortstring and arraylist parameters \
+* [Issue #539](https://github.com/json-c/json-c/issues/539) - double serializes to the old value after set_double \
+* [Issue #541](https://github.com/json-c/json-c/issues/541) - add coveralls auto tool to json-c \
+* [Issue #542](https://github.com/json-c/json-c/issues/542) - add uint64 data to json-c \
+* [Issue #543](https://github.com/json-c/json-c/issues/543) - Readme \
+* [Issue #544](https://github.com/json-c/json-c/issues/544) - Increase distcheck target in cmake \
+* [Issue #545](https://github.com/json-c/json-c/issues/545) - add doc target in cmake \
+* [Issue #546](https://github.com/json-c/json-c/issues/546) - Add uninstall target in cmake \
+* [Issue #547](https://github.com/json-c/json-c/issues/547) - modify json-c default build type, and fix up the assert() errors in t… \
+* [Issue #548](https://github.com/json-c/json-c/issues/548) - Solve some problems about cmake build type (debug/release) \
+* [Issue #549](https://github.com/json-c/json-c/issues/549) - lib installation issues \
+* [Issue #550](https://github.com/json-c/json-c/issues/550) - Format codes with clang-format tool? \
+* [Issue #551](https://github.com/json-c/json-c/issues/551) - Allow hexadecimal number format convention parsing \
+* [Issue #553](https://github.com/json-c/json-c/issues/553) - Fix/clang ubsan \
+* [Issue #554](https://github.com/json-c/json-c/issues/554) - RFC 8259 compatibility mode \
+* [Issue #555](https://github.com/json-c/json-c/issues/555) - Format json-c with clang-format tool \
+* [Issue #556](https://github.com/json-c/json-c/issues/556) - Fixes various Wreturn-type and Wimplicit-fallthrough errors on Mingw-w64 \
+* [Issue #557](https://github.com/json-c/json-c/issues/557) - Add option in CMAKE to not build documentation \
+* [Issue #558](https://github.com/json-c/json-c/issues/558) - modify the doc target message \
+* [Issue #559](https://github.com/json-c/json-c/issues/559) - json_c_visit() not exported on Windows \
+* [Issue #560](https://github.com/json-c/json-c/issues/560) - error: implicit declaration of function '_strtoi64' \
+* [Issue #561](https://github.com/json-c/json-c/issues/561) - add the badge in README.md and test the coveralls \
+* [Issue #562](https://github.com/json-c/json-c/issues/562) - Bugfix and testcases supplements \
+* [Issue #563](https://github.com/json-c/json-c/issues/563) - Changed order of calloc args to match stdlib \
+* [Issue #564](https://github.com/json-c/json-c/issues/564) - Remove autogenerated files \
+* [Issue #565](https://github.com/json-c/json-c/issues/565) - test the CI and ignore this PR \
+* [Issue #566](https://github.com/json-c/json-c/issues/566) - add the json_types.h to Makefile.am \
+* [Issue #567](https://github.com/json-c/json-c/issues/567) - Install json_types.h with autotools build as well. \
+* [Issue #568](https://github.com/json-c/json-c/issues/568) - Adding better support to MinGW \
+* [Issue #569](https://github.com/json-c/json-c/issues/569) - Handling of -Bsymbolic-function in CMakeLists.txt is deficient \
+* [Issue #571](https://github.com/json-c/json-c/issues/571) - CMake: Bump SONAME to 5. \
+* [Issue #572](https://github.com/json-c/json-c/issues/572) - Small fixes to CMakeLists \
+* [Issue #573](https://github.com/json-c/json-c/issues/573) - Fix coveralls submission. \
+* [Issue #574](https://github.com/json-c/json-c/issues/574) - autogen.sh missing from repository \
+* [Issue #575](https://github.com/json-c/json-c/issues/575) - Small cosmetics. \
+* [Issue #576](https://github.com/json-c/json-c/issues/576) - Test coverage for json_c_version. \
+* [Issue #577](https://github.com/json-c/json-c/issues/577) - Be verbose on failing json_c_version test. \
+* [Issue #578](https://github.com/json-c/json-c/issues/578) - CMake: Install pkgconfig file in proper location by default \
+* [Issue #579](https://github.com/json-c/json-c/issues/579) - Enforce strict prototypes. \
+* [Issue #580](https://github.com/json-c/json-c/issues/580) - Fix CMake tests for enforced strict prototypes. \
+* [Issue #581](https://github.com/json-c/json-c/issues/581) - CMakeLists: do not enforce strict prototypes on Windows. \
diff --git a/issues_closed_for_0.15.md b/issues_closed_for_0.15.md
new file mode 100644
index 0000000..8c7f2f6
--- /dev/null
+++ b/issues_closed_for_0.15.md
@@ -0,0 +1,85 @@
+This list was created with:
+
+```
+curl "https://api.github.com/search/issues?q=repo%3Ajson-c%2Fjson-c+closed%3A>2020-04-18+created%3A<2020-07-23&sort=created&order=asc&per_page=100&page=1" > issues1.out
+jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues?.out > issues.md
+sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),* [Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i issues.md
+#... manual editing ...
+
+```
+
+----
+
+Issues and Pull Requests closed for the 0.15 release
+(since commit 31ab57ca, the 0.14 branch point, 2020-04-19)
+
+* [Issue #428](https://github.com/json-c/json-c/issues/428) - Added new_null() function
+* [Issue #429](https://github.com/json-c/json-c/issues/429) - Conflict of interest between JSON_C_TO_STRING_SPACED and JSON_C_TO_STRING_PRETTY
+* [Issue #451](https://github.com/json-c/json-c/issues/451) - Add option to disable HAVE___THREAD
+* [Issue #471](https://github.com/json-c/json-c/issues/471) - create folders with mode 0755 when building
+* [Issue #476](https://github.com/json-c/json-c/issues/476) - Add new function named json_object_new_string_noalloc
+* [Issue #484](https://github.com/json-c/json-c/issues/484) - Add support for uint64
+* [Issue #487](https://github.com/json-c/json-c/issues/487) - Any plans to make new release? (0.14)
+* [Issue #493](https://github.com/json-c/json-c/issues/493) - Kdopen rename library
+* [Issue #507](https://github.com/json-c/json-c/issues/507) - Double value -1.0 converts to integer in json_object_to_json_string()
+* [Issue #508](https://github.com/json-c/json-c/issues/508) - Recommend enabling the `-fPIC` compiler flag by default
+* [Issue #517](https://github.com/json-c/json-c/issues/517) - Lja mods
+* [Issue #534](https://github.com/json-c/json-c/issues/534) - Both json-c and json-glib have json_object_get_type()
+* [Issue #584](https://github.com/json-c/json-c/issues/584) - CMake: SOVERSION and the major library VERSION need to be in lockstep.
+* [Issue #585](https://github.com/json-c/json-c/issues/585) - CMake: Do not install config.h, as it is not a public header file.
+* [Issue #586](https://github.com/json-c/json-c/issues/586) - 10796 Segmentation fault
+* [Issue #588](https://github.com/json-c/json-c/issues/588) - Broken RDRAND causes infinite looping
+* [Issue #589](https://github.com/json-c/json-c/issues/589) - Detect broken RDRAND during initialization
+* [Issue #590](https://github.com/json-c/json-c/issues/590) - Fix segmentation fault in CPUID check
+* [Issue #591](https://github.com/json-c/json-c/issues/591) - Update README.md
+* [Issue #592](https://github.com/json-c/json-c/issues/592) - Prevent out of boundary write on malicious input
+* [Issue #593](https://github.com/json-c/json-c/issues/593) - Building both static and shared libraries
+* [Issue #594](https://github.com/json-c/json-c/issues/594) - Some subsequent call of lh_get_hash not working
+* [Issue #595](https://github.com/json-c/json-c/issues/595) - Support to build both static and shared libraries
+* [Issue #596](https://github.com/json-c/json-c/issues/596) - QA Notice: Package triggers severe warnings
+* [Issue #597](https://github.com/json-c/json-c/issues/597) - json_parse demo: fix and use usage() function
+* [Issue #598](https://github.com/json-c/json-c/issues/598) - Turning off shared libs causes target duplication or build error
+* [Issue #599](https://github.com/json-c/json-c/issues/599) - cannot add more than 11 objects. Is this a known issue?
+* [Issue #600](https://github.com/json-c/json-c/issues/600) - Library name conflicts on Windows are back again
+* [Issue #601](https://github.com/json-c/json-c/issues/601) - json_tokener_parse() in master sets errno=1 "Operation not permitted"
+* [Issue #602](https://github.com/json-c/json-c/issues/602) - fix json_parse_uint64() internal error checking with errno
+* [Issue #603](https://github.com/json-c/json-c/issues/603) - Backport of fixes from master branch.
+* [Issue #604](https://github.com/json-c/json-c/issues/604) - commit f2e991a3419ee4078e8915e840b1a0d9003b349e breaks cross-compilation with mingw
+* [Issue #605](https://github.com/json-c/json-c/issues/605) - Update to 0.15 release
+* [Issue #606](https://github.com/json-c/json-c/issues/606) - Improved support for IBM operating systems
+* [Issue #607](https://github.com/json-c/json-c/issues/607) - json-c-0.13.x: Fix CVE-2020-12762 - json-c through 0.14 has an integer overflow and out-of-bounds write ...
+* [Issue #608](https://github.com/json-c/json-c/issues/608) - json-c-0.14: Fix CVE-2020-12762 - json-c through 0.14 has an integer overflow and out-of-bounds write ...
+* [Issue #609](https://github.com/json-c/json-c/issues/609) - use unsigned types for sizes in lh_table and entries
+* [Issue #610](https://github.com/json-c/json-c/issues/610) - let's not call lh_table_resize with INT_MAX
+* [Issue #611](https://github.com/json-c/json-c/issues/611) - json-c-0.12.x: Fix CVE-2020-12762 - json-c through 0.14 has an integer overflow and out-of-bounds write ...
+* [Issue #613](https://github.com/json-c/json-c/issues/613) - json-c-0.10: Fix CVE-2020-12762 - json-c through 0.14 has an integer overflow and out-of-bounds write ...
+* [Issue #614](https://github.com/json-c/json-c/issues/614) - Prevent truncation on custom double formatters.
+* [Issue #615](https://github.com/json-c/json-c/issues/615) - New release with security fix
+* [Issue #616](https://github.com/json-c/json-c/issues/616) - Parsing fails if UTF-16 low surrogate pair is not in same chunk is the high pair
+* [Issue #617](https://github.com/json-c/json-c/issues/617) - Add an option to disable the use of thread-local storage.
+* [Issue #618](https://github.com/json-c/json-c/issues/618) - test_deep_copy: Fix assertion value.
+* [Issue #619](https://github.com/json-c/json-c/issues/619) - CMake: Fix out-of-tree build for Doxygen documentation.
+* [Issue #621](https://github.com/json-c/json-c/issues/621) - json-c and jansson libraries have symbol conflicts
+* [Issue #622](https://github.com/json-c/json-c/issues/622) - doc: Move Doxyfile into doc subdir.
+* [Issue #623](https://github.com/json-c/json-c/issues/623) - json_tokener_parse : Segmentation fault
+* [Issue #626](https://github.com/json-c/json-c/issues/626) - Fixes for cmake 2.8.12 + link issue on AIX 6.1/cc 11.01
+* [Issue #627](https://github.com/json-c/json-c/issues/627) - Compat fixes
+* [Issue #628](https://github.com/json-c/json-c/issues/628) - get_cryptgenrandom_seed: compat with old windows + fallback
+* [Issue #629](https://github.com/json-c/json-c/issues/629) - [0.12] Remove the Visual Studio project file
+* [Issue #630](https://github.com/json-c/json-c/issues/630) - Linking with Windows MINGW not working
+* [Issue #632](https://github.com/json-c/json-c/issues/632) - Json object split
+* [Issue #633](https://github.com/json-c/json-c/issues/633) - fix issue 616: support the surrogate pair in split file.
+* [Issue #634](https://github.com/json-c/json-c/issues/634) - Issue #508: `-fPIC` to link libjson-c.a with libs
+* [Issue #635](https://github.com/json-c/json-c/issues/635) - expression has no effect warning in json_tokener.c
+* [Issue #636](https://github.com/json-c/json-c/issues/636) - json_object_get_string free str memory
+* [Issue #637](https://github.com/json-c/json-c/issues/637) - json_object_put() has 'double free or corruption (out) '
+* [Issue #638](https://github.com/json-c/json-c/issues/638) - json-c/json_object.c:50:2: error: #error Unable to determine size of ssize_t
+* [Issue #639](https://github.com/json-c/json-c/issues/639) - build: Add a symbol version to all exported symbols
+* [Issue #640](https://github.com/json-c/json-c/issues/640) - Fix build issues with SSIZE_MAX on 64bit Linux
+* [Issue #641](https://github.com/json-c/json-c/issues/641) - Formal verification of your test suite
+* [Issue #642](https://github.com/json-c/json-c/issues/642) - Please provide more precise informations about when to call json_object_put
+* [Issue #643](https://github.com/json-c/json-c/issues/643) - not able to compare with string
+* [Issue #644](https://github.com/json-c/json-c/issues/644) - Why src->_userdata not checked before calling strdup?
+* [Issue #645](https://github.com/json-c/json-c/issues/645) - Misuse of tolower() in json_tokener.c
+* [Issue #646](https://github.com/json-c/json-c/issues/646) - Cast to unsigned char instead of int when calling tolower (Fixes #645)
+
diff --git a/json-c.sym b/json-c.sym
new file mode 100644
index 0000000..2dedc6e
--- /dev/null
+++ b/json-c.sym
@@ -0,0 +1,170 @@
+
+/*
+ * Symbol versioning for libjson-c.
+ * All exported symbols must be listed here.
+ *
+ * See
+ * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
+ */
+
+/*
+ * Symbols in JSONC_PRIVATE are exported for historical
+ * reasons, but should not be used outside of json-c.
+ */
+JSONC_PRIVATE {
+ array_list_add;
+ array_list_del_idx;
+ array_list_free;
+ array_list_new;
+ array_list_put_idx;
+ array_list_sort;
+ json_hex_chars;
+ json_parse_double;
+ json_parse_int64;
+ json_parse_uint64;
+ lh_table_delete;
+ lh_table_delete_entry;
+ lh_table_free;
+ lh_table_insert;
+ lh_table_insert_w_hash;
+ lh_table_new;
+ lh_table_resize;
+ mc_debug;
+ mc_error;
+ mc_get_debug;
+ mc_info;
+ mc_set_debug;
+ mc_set_syslog;
+ printbuf_free;
+ printbuf_memappend;
+ printbuf_memset;
+ printbuf_new;
+ printbuf_reset;
+ sprintbuf;
+};
+
+JSONC_0.14 {
+ global:
+ array_list_bsearch;
+ array_list_get_idx;
+ array_list_length;
+ json_c_get_random_seed;
+ json_c_object_sizeof;
+ json_c_set_serialization_double_format;
+ json_c_shallow_copy_default;
+ json_c_version;
+ json_c_version_num;
+ json_c_visit;
+ json_global_set_string_hash;
+ json_number_chars;
+ json_object_array_add;
+ json_object_array_bsearch;
+ json_object_array_del_idx;
+ json_object_array_get_idx;
+ json_object_array_length;
+ json_object_array_put_idx;
+ json_object_array_sort;
+ json_object_deep_copy;
+ json_object_double_to_json_string;
+ json_object_equal;
+ json_object_free_userdata;
+ json_object_from_fd;
+ json_object_from_fd_ex;
+ json_object_from_file;
+ json_object_get;
+ json_object_get_array;
+ json_object_get_boolean;
+ json_object_get_double;
+ json_object_get_int64;
+ json_object_get_int;
+ json_object_get_object;
+ json_object_get_string;
+ json_object_get_string_len;
+ json_object_get_type;
+ json_object_get_uint64;
+ json_object_get_userdata;
+ json_object_int_inc;
+ json_object_is_type;
+ json_object_iter_begin;
+ json_object_iter_end;
+ json_object_iter_equal;
+ json_object_iter_init_default;
+ json_object_iter_next;
+ json_object_iter_peek_name;
+ json_object_iter_peek_value;
+ json_object_new_array;
+ json_object_new_boolean;
+ json_object_new_double;
+ json_object_new_double_s;
+ json_object_new_int64;
+ json_object_new_int;
+ json_object_new_null;
+ json_object_new_object;
+ json_object_new_string;
+ json_object_new_string_len;
+ json_object_new_uint64;
+ json_object_object_add;
+ json_object_object_add_ex;
+ json_object_object_del;
+ json_object_object_get;
+ json_object_object_get_ex;
+ json_object_object_length;
+ json_object_put;
+ json_object_set_boolean;
+ json_object_set_double;
+ json_object_set_int64;
+ json_object_set_int;
+ json_object_set_serializer;
+ json_object_set_string;
+ json_object_set_string_len;
+ json_object_set_uint64;
+ json_object_set_userdata;
+ json_object_to_fd;
+ json_object_to_file;
+ json_object_to_file_ext;
+ json_object_to_json_string;
+ json_object_to_json_string_ext;
+ json_object_to_json_string_length;
+ json_object_userdata_to_json_string;
+ json_pointer_get;
+ json_pointer_getf;
+ json_pointer_set;
+ json_pointer_setf;
+ json_tokener_error_desc;
+ json_tokener_free;
+ json_tokener_get_error;
+ json_tokener_get_parse_end;
+ json_tokener_new;
+ json_tokener_new_ex;
+ json_tokener_parse;
+ json_tokener_parse_ex;
+ json_tokener_parse_verbose;
+ json_tokener_reset;
+ json_tokener_set_flags;
+ json_type_to_name;
+ json_util_get_last_err;
+ lh_char_equal;
+ lh_kchar_table_new;
+ lh_kptr_table_new;
+ lh_ptr_equal;
+ lh_table_length;
+ lh_table_lookup_entry;
+ lh_table_lookup_entry_w_hash;
+ lh_table_lookup_ex;
+
+ local:
+ *;
+};
+
+JSONC_0.15 {
+ global:
+ array_list_new2;
+ array_list_shrink;
+ json_object_array_shrink;
+ json_object_new_array_ext;
+} JSONC_0.14;
+
+JSONC_0.16 {
+# global:
+# ...new symbols here...
+} JSONC_0.15;
diff --git a/json.h b/json.h.cmakein
index 6c3b43b..4fed013 100644
--- a/json.h
+++ b/json.h.cmakein
@@ -26,7 +26,7 @@ extern "C" {
#include "json_c_version.h"
#include "json_object.h"
#include "json_object_iterator.h"
-#include "json_pointer.h"
+@JSON_H_JSON_POINTER@
#include "json_tokener.h"
#include "json_util.h"
#include "linkhash.h"
diff --git a/json_c_version.h b/json_c_version.h
index 84b6b3e..d15ad64 100644
--- a/json_c_version.h
+++ b/json_c_version.h
@@ -17,14 +17,14 @@ extern "C" {
#endif
#define JSON_C_MAJOR_VERSION 0
-#define JSON_C_MINOR_VERSION 14
+#define JSON_C_MINOR_VERSION 15
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM \
((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION)
-#define JSON_C_VERSION "0.14.99"
+#define JSON_C_VERSION "0.15.99"
#ifndef JSON_EXPORT
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && defined(JSON_C_DLL)
#define JSON_EXPORT __declspec(dllexport)
#else
#define JSON_EXPORT extern
diff --git a/json_object.c b/json_object.c
index c2463c1..c15a477 100644
--- a/json_object.c
+++ b/json_object.c
@@ -1,6 +1,4 @@
/*
- * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
- *
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
@@ -16,6 +14,9 @@
#include <assert.h>
#include <ctype.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
#include <math.h>
#include <stddef.h>
#include <stdio.h>
@@ -38,14 +39,98 @@
#error "The long long type isn't 64-bits"
#endif
+#ifndef SSIZE_T_MAX
+#if SIZEOF_SSIZE_T == SIZEOF_INT
+#define SSIZE_T_MAX INT_MAX
+#elif SIZEOF_SSIZE_T == SIZEOF_LONG
+#define SSIZE_T_MAX LONG_MAX
+#elif SIZEOF_SSIZE_T == SIZEOF_LONG_LONG
+#define SSIZE_T_MAX LLONG_MAX
+#else
+#error Unable to determine size of ssize_t
+#endif
+#endif
+
// Don't define this. It's not thread-safe.
/* #define REFCOUNT_DEBUG 1 */
-const char *json_number_chars = "0123456789.+-eE";
const char *json_hex_chars = "0123456789abcdefABCDEF";
static void json_object_generic_delete(struct json_object *jso);
-static struct json_object *json_object_new(enum json_type o_type);
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1800)
+/* VS2013 doesn't know about "inline" */
+#define inline __inline
+#elif defined(AIX_CC)
+#define inline
+#endif
+
+/*
+ * Helper functions to more safely cast to a particular type of json_object
+ */
+static inline struct json_object_object *JC_OBJECT(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_object *JC_OBJECT_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+static inline struct json_object_array *JC_ARRAY(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_array *JC_ARRAY_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+static inline struct json_object_boolean *JC_BOOL(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_boolean *JC_BOOL_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+static inline struct json_object_double *JC_DOUBLE(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_double *JC_DOUBLE_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+static inline struct json_object_int *JC_INT(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_int *JC_INT_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+static inline struct json_object_string *JC_STRING(struct json_object *jso)
+{
+ return (void *)jso;
+}
+static inline const struct json_object_string *JC_STRING_C(const struct json_object *jso)
+{
+ return (const void *)jso;
+}
+
+#define JC_CONCAT(a, b) a##b
+#define JC_CONCAT3(a, b, c) a##b##c
+
+#define JSON_OBJECT_NEW(jtype) \
+ (struct JC_CONCAT(json_object_, jtype) *)json_object_new( \
+ JC_CONCAT(json_type_, jtype), sizeof(struct JC_CONCAT(json_object_, jtype)), \
+ &JC_CONCAT3(json_object_, jtype, _to_json_string))
+
+static inline struct json_object *json_object_new(enum json_type o_type, size_t alloc_size,
+ json_object_to_json_string_fn *to_json_string);
+
+static void json_object_object_delete(struct json_object *jso_base);
+static void json_object_string_delete(struct json_object *jso);
+static void json_object_array_delete(struct json_object *jso);
static json_object_to_json_string_fn json_object_object_to_json_string;
static json_object_to_json_string_fn json_object_boolean_to_json_string;
@@ -111,17 +196,25 @@ static void json_object_fini(void)
/* helper for accessing the optimized string data component in json_object
*/
-static const char *get_string_component(const struct json_object *jso)
+static inline char *get_string_component_mutable(struct json_object *jso)
{
- return (jso->o.c_string.len < LEN_DIRECT_STRING_DATA) ? jso->o.c_string.str.data
- : jso->o.c_string.str.ptr;
+ if (JC_STRING_C(jso)->len < 0)
+ {
+ /* Due to json_object_set_string(), we might have a pointer */
+ return JC_STRING(jso)->c_string.pdata;
+ }
+ return JC_STRING(jso)->c_string.idata;
+}
+static inline const char *get_string_component(const struct json_object *jso)
+{
+ return get_string_component_mutable((void *)(uintptr_t)(const void *)jso);
}
/* string escaping */
-static int json_escape_str(struct printbuf *pb, const char *str, int len, int flags)
+static int json_escape_str(struct printbuf *pb, const char *str, size_t len, int flags)
{
- int pos = 0, start_offset = 0;
+ size_t pos = 0, start_offset = 0;
unsigned char c;
while (len--)
{
@@ -142,7 +235,7 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl
break;
}
- if (pos - start_offset > 0)
+ if (pos > start_offset)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
if (c == '\b')
@@ -168,7 +261,7 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl
if (c < ' ')
{
char sbuf[7];
- if (pos - start_offset > 0)
+ if (pos > start_offset)
printbuf_memappend(pb, str + start_offset,
pos - start_offset);
snprintf(sbuf, sizeof(sbuf), "\\u00%c%c", json_hex_chars[c >> 4],
@@ -180,7 +273,7 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl
pos++;
}
}
- if (pos - start_offset > 0)
+ if (pos > start_offset)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
return 0;
}
@@ -230,7 +323,13 @@ int json_object_put(struct json_object *jso)
if (jso->_user_delete)
jso->_user_delete(jso, jso->_userdata);
- jso->_delete(jso);
+ switch (jso->o_type)
+ {
+ case json_type_object: json_object_object_delete(jso); break;
+ case json_type_array: json_object_array_delete(jso); break;
+ case json_type_string: json_object_string_delete(jso); break;
+ default: json_object_generic_delete(jso); break;
+ }
return 1;
}
@@ -246,16 +345,23 @@ static void json_object_generic_delete(struct json_object *jso)
free(jso);
}
-static struct json_object *json_object_new(enum json_type o_type)
+static inline struct json_object *json_object_new(enum json_type o_type, size_t alloc_size,
+ json_object_to_json_string_fn *to_json_string)
{
struct json_object *jso;
- jso = (struct json_object *)calloc(1, sizeof(struct json_object));
+ jso = (struct json_object *)malloc(alloc_size);
if (!jso)
return NULL;
+
jso->o_type = o_type;
jso->_ref_count = 1;
- jso->_delete = &json_object_generic_delete;
+ jso->_to_json_string = to_json_string;
+ jso->_pb = NULL;
+ jso->_user_delete = NULL;
+ jso->_userdata = NULL;
+ //jso->... // Type-specific fields must be set by caller
+
#ifdef REFCOUNT_DEBUG
lh_table_insert(json_object_table, jso, jso);
MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
@@ -441,28 +547,26 @@ static void json_object_lh_entry_free(struct lh_entry *ent)
json_object_put((struct json_object *)lh_entry_v(ent));
}
-static void json_object_object_delete(struct json_object *jso)
+static void json_object_object_delete(struct json_object *jso_base)
{
- lh_table_free(jso->o.c_object);
- json_object_generic_delete(jso);
+ lh_table_free(JC_OBJECT(jso_base)->c_object);
+ json_object_generic_delete(jso_base);
}
struct json_object *json_object_new_object(void)
{
- struct json_object *jso = json_object_new(json_type_object);
+ struct json_object_object *jso = JSON_OBJECT_NEW(object);
if (!jso)
return NULL;
- jso->_delete = &json_object_object_delete;
- jso->_to_json_string = &json_object_object_to_json_string;
- jso->o.c_object =
+ jso->c_object =
lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, &json_object_lh_entry_free);
- if (!jso->o.c_object)
+ if (!jso->c_object)
{
- json_object_generic_delete(jso);
+ json_object_generic_delete(&jso->base);
errno = ENOMEM;
return NULL;
}
- return jso;
+ return &jso->base;
}
struct lh_table *json_object_get_object(const struct json_object *jso)
@@ -471,7 +575,7 @@ struct lh_table *json_object_get_object(const struct json_object *jso)
return NULL;
switch (jso->o_type)
{
- case json_type_object: return jso->o.c_object;
+ case json_type_object: return JC_OBJECT_C(jso)->c_object;
default: return NULL;
}
}
@@ -487,11 +591,11 @@ int json_object_object_add_ex(struct json_object *jso, const char *const key,
// We lookup the entry and replace the value, rather than just deleting
// and re-adding it, so the existing key remains valid.
- hash = lh_get_hash(jso->o.c_object, (const void *)key);
+ hash = lh_get_hash(JC_OBJECT(jso)->c_object, (const void *)key);
existing_entry =
(opts & JSON_C_OBJECT_ADD_KEY_IS_NEW)
? NULL
- : lh_table_lookup_entry_w_hash(jso->o.c_object, (const void *)key, hash);
+ : lh_table_lookup_entry_w_hash(JC_OBJECT(jso)->c_object, (const void *)key, hash);
// The caller must avoid creating loops in the object tree, but do a
// quick check anyway to make sure we're not creating a trivial loop.
@@ -504,7 +608,7 @@ int json_object_object_add_ex(struct json_object *jso, const char *const key,
(opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ? (const void *)key : strdup(key);
if (k == NULL)
return -1;
- return lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts);
+ return lh_table_insert_w_hash(JC_OBJECT(jso)->c_object, k, val, hash, opts);
}
existing_value = (json_object *)lh_entry_v(existing_entry);
if (existing_value)
@@ -521,7 +625,7 @@ int json_object_object_add(struct json_object *jso, const char *key, struct json
int json_object_object_length(const struct json_object *jso)
{
assert(json_object_get_type(jso) == json_type_object);
- return lh_table_length(jso->o.c_object);
+ return lh_table_length(JC_OBJECT_C(jso)->c_object);
}
size_t json_c_object_sizeof(void)
@@ -548,7 +652,8 @@ json_bool json_object_object_get_ex(const struct json_object *jso, const char *k
switch (jso->o_type)
{
case json_type_object:
- return lh_table_lookup_ex(jso->o.c_object, (const void *)key, (void **)value);
+ return lh_table_lookup_ex(JC_OBJECT_C(jso)->c_object, (const void *)key,
+ (void **)value);
default:
if (value != NULL)
*value = NULL;
@@ -559,7 +664,7 @@ json_bool json_object_object_get_ex(const struct json_object *jso, const char *k
void json_object_object_del(struct json_object *jso, const char *key)
{
assert(json_object_get_type(jso) == json_type_object);
- lh_table_delete(jso->o.c_object, key);
+ lh_table_delete(JC_OBJECT(jso)->c_object, key);
}
/* json_object_boolean */
@@ -567,19 +672,18 @@ void json_object_object_del(struct json_object *jso, const char *key)
static int json_object_boolean_to_json_string(struct json_object *jso, struct printbuf *pb,
int level, int flags)
{
- if (jso->o.c_boolean)
+ if (JC_BOOL(jso)->c_boolean)
return printbuf_strappend(pb, "true");
return printbuf_strappend(pb, "false");
}
struct json_object *json_object_new_boolean(json_bool b)
{
- struct json_object *jso = json_object_new(json_type_boolean);
+ struct json_object_boolean *jso = JSON_OBJECT_NEW(boolean);
if (!jso)
return NULL;
- jso->_to_json_string = &json_object_boolean_to_json_string;
- jso->o.c_boolean = b;
- return jso;
+ jso->c_boolean = b;
+ return &jso->base;
}
json_bool json_object_get_boolean(const struct json_object *jso)
@@ -588,16 +692,16 @@ json_bool json_object_get_boolean(const struct json_object *jso)
return 0;
switch (jso->o_type)
{
- case json_type_boolean: return jso->o.c_boolean;
+ case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_int:
- switch (jso->o.c_int.cint_type)
+ switch (JC_INT_C(jso)->cint_type)
{
- case json_object_int_type_int64: return (jso->o.c_int.cint.c_int64 != 0);
- case json_object_int_type_uint64: return (jso->o.c_int.cint.c_uint64 != 0);
+ case json_object_int_type_int64: return (JC_INT_C(jso)->cint.c_int64 != 0);
+ case json_object_int_type_uint64: return (JC_INT_C(jso)->cint.c_uint64 != 0);
default: json_abort("invalid cint_type");
}
- case json_type_double: return (jso->o.c_double != 0);
- case json_type_string: return (jso->o.c_string.len != 0);
+ case json_type_double: return (JC_DOUBLE_C(jso)->c_double != 0);
+ case json_type_string: return (JC_STRING_C(jso)->len != 0);
default: return 0;
}
}
@@ -606,7 +710,7 @@ int json_object_set_boolean(struct json_object *jso, json_bool new_value)
{
if (!jso || jso->o_type != json_type_boolean)
return 0;
- jso->o.c_boolean = new_value;
+ JC_BOOL(jso)->c_boolean = new_value;
return 1;
}
@@ -617,46 +721,44 @@ static int json_object_int_to_json_string(struct json_object *jso, struct printb
{
/* room for 19 digits, the sign char, and a null term */
char sbuf[21];
- if (jso->o.c_int.cint_type == json_object_int_type_int64)
- snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int.cint.c_int64);
+ if (JC_INT(jso)->cint_type == json_object_int_type_int64)
+ snprintf(sbuf, sizeof(sbuf), "%" PRId64, JC_INT(jso)->cint.c_int64);
else
- snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_int.cint.c_uint64);
+ snprintf(sbuf, sizeof(sbuf), "%" PRIu64, JC_INT(jso)->cint.c_uint64);
return printbuf_memappend(pb, sbuf, strlen(sbuf));
}
struct json_object *json_object_new_int(int32_t i)
{
- struct json_object *jso = json_object_new(json_type_int);
- if (!jso)
- return NULL;
- jso->_to_json_string = &json_object_int_to_json_string;
- jso->o.c_int.cint.c_int64 = i;
- jso->o.c_int.cint_type = json_object_int_type_int64;
- return jso;
+ return json_object_new_int64(i);
}
int32_t json_object_get_int(const struct json_object *jso)
{
- int64_t cint64;
+ int64_t cint64=0;
+ double cdouble;
enum json_type o_type;
if (!jso)
return 0;
o_type = jso->o_type;
- if (jso->o.c_int.cint_type == json_object_int_type_int64)
+ if (o_type == json_type_int)
{
- cint64 = jso->o.c_int.cint.c_int64;
- }
- else
- {
- if (jso->o.c_int.cint.c_uint64 >= INT64_MAX)
- cint64 = INT64_MAX;
+ const struct json_object_int *jsoint = JC_INT_C(jso);
+ if (jsoint->cint_type == json_object_int_type_int64)
+ {
+ cint64 = jsoint->cint.c_int64;
+ }
else
- cint64 = (int64_t)jso->o.c_int.cint.c_uint64;
+ {
+ if (jsoint->cint.c_uint64 >= INT64_MAX)
+ cint64 = INT64_MAX;
+ else
+ cint64 = (int64_t)jsoint->cint.c_uint64;
+ }
}
-
- if (o_type == json_type_string)
+ else if (o_type == json_type_string)
{
/*
* Parse strings into 64-bit numbers, then use the
@@ -677,12 +779,13 @@ int32_t json_object_get_int(const struct json_object *jso)
return INT32_MAX;
return (int32_t)cint64;
case json_type_double:
- if (jso->o.c_double <= INT32_MIN)
+ cdouble = JC_DOUBLE_C(jso)->c_double;
+ if (cdouble <= INT32_MIN)
return INT32_MIN;
- if (jso->o.c_double >= INT32_MAX)
+ if (cdouble >= INT32_MAX)
return INT32_MAX;
- return (int32_t)jso->o.c_double;
- case json_type_boolean: return jso->o.c_boolean;
+ return (int32_t)cdouble;
+ case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
default: return 0;
}
}
@@ -694,24 +797,22 @@ int json_object_set_int(struct json_object *jso, int new_value)
struct json_object *json_object_new_int64(int64_t i)
{
- struct json_object *jso = json_object_new(json_type_int);
+ struct json_object_int *jso = JSON_OBJECT_NEW(int);
if (!jso)
return NULL;
- jso->_to_json_string = &json_object_int_to_json_string;
- jso->o.c_int.cint.c_int64 = i;
- jso->o.c_int.cint_type = json_object_int_type_int64;
- return jso;
+ jso->cint.c_int64 = i;
+ jso->cint_type = json_object_int_type_int64;
+ return &jso->base;
}
struct json_object *json_object_new_uint64(uint64_t i)
{
- struct json_object *jso = json_object_new(json_type_int);
+ struct json_object_int *jso = JSON_OBJECT_NEW(int);
if (!jso)
return NULL;
- jso->_to_json_string = &json_object_int_to_json_string;
- jso->o.c_int.cint.c_uint64 = i;
- jso->o.c_int.cint_type = json_object_int_type_uint64;
- return jso;
+ jso->cint.c_uint64 = i;
+ jso->cint_type = json_object_int_type_uint64;
+ return &jso->base;
}
int64_t json_object_get_int64(const struct json_object *jso)
@@ -723,24 +824,27 @@ int64_t json_object_get_int64(const struct json_object *jso)
switch (jso->o_type)
{
case json_type_int:
- switch (jso->o.c_int.cint_type)
+ {
+ const struct json_object_int *jsoint = JC_INT_C(jso);
+ switch (jsoint->cint_type)
{
- case json_object_int_type_int64: return jso->o.c_int.cint.c_int64;
+ case json_object_int_type_int64: return jsoint->cint.c_int64;
case json_object_int_type_uint64:
- if (jso->o.c_int.cint.c_uint64 >= INT64_MAX)
+ if (jsoint->cint.c_uint64 >= INT64_MAX)
return INT64_MAX;
- return (int64_t)jso->o.c_int.cint.c_uint64;
+ return (int64_t)jsoint->cint.c_uint64;
default: json_abort("invalid cint_type");
}
+ }
case json_type_double:
// INT64_MAX can't be exactly represented as a double
// so cast to tell the compiler it's ok to round up.
- if (jso->o.c_double >= (double)INT64_MAX)
+ if (JC_DOUBLE_C(jso)->c_double >= (double)INT64_MAX)
return INT64_MAX;
- if (jso->o.c_double <= INT64_MIN)
+ if (JC_DOUBLE_C(jso)->c_double <= INT64_MIN)
return INT64_MIN;
- return (int64_t)jso->o.c_double;
- case json_type_boolean: return jso->o.c_boolean;
+ return (int64_t)JC_DOUBLE_C(jso)->c_double;
+ case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_string:
if (json_parse_int64(get_string_component(jso), &cint) == 0)
return cint;
@@ -758,24 +862,27 @@ uint64_t json_object_get_uint64(const struct json_object *jso)
switch (jso->o_type)
{
case json_type_int:
- switch (jso->o.c_int.cint_type)
+ {
+ const struct json_object_int *jsoint = JC_INT_C(jso);
+ switch (jsoint->cint_type)
{
case json_object_int_type_int64:
- if (jso->o.c_int.cint.c_int64 < 0)
+ if (jsoint->cint.c_int64 < 0)
return 0;
- return (uint64_t)jso->o.c_int.cint.c_int64;
- case json_object_int_type_uint64: return jso->o.c_int.cint.c_uint64;
+ return (uint64_t)jsoint->cint.c_int64;
+ case json_object_int_type_uint64: return jsoint->cint.c_uint64;
default: json_abort("invalid cint_type");
}
+ }
case json_type_double:
// UINT64_MAX can't be exactly represented as a double
// so cast to tell the compiler it's ok to round up.
- if (jso->o.c_double >= (double)UINT64_MAX)
+ if (JC_DOUBLE_C(jso)->c_double >= (double)UINT64_MAX)
return UINT64_MAX;
- if (jso->o.c_double < 0)
+ if (JC_DOUBLE_C(jso)->c_double < 0)
return 0;
- return (uint64_t)jso->o.c_double;
- case json_type_boolean: return jso->o.c_boolean;
+ return (uint64_t)JC_DOUBLE_C(jso)->c_double;
+ case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_string:
if (json_parse_uint64(get_string_component(jso), &cuint) == 0)
return cuint;
@@ -788,8 +895,8 @@ int json_object_set_int64(struct json_object *jso, int64_t new_value)
{
if (!jso || jso->o_type != json_type_int)
return 0;
- jso->o.c_int.cint.c_int64 = new_value;
- jso->o.c_int.cint_type = json_object_int_type_int64;
+ JC_INT(jso)->cint.c_int64 = new_value;
+ JC_INT(jso)->cint_type = json_object_int_type_int64;
return 1;
}
@@ -797,50 +904,51 @@ int json_object_set_uint64(struct json_object *jso, uint64_t new_value)
{
if (!jso || jso->o_type != json_type_int)
return 0;
- jso->o.c_int.cint.c_uint64 = new_value;
- jso->o.c_int.cint_type = json_object_int_type_uint64;
+ JC_INT(jso)->cint.c_uint64 = new_value;
+ JC_INT(jso)->cint_type = json_object_int_type_uint64;
return 1;
}
int json_object_int_inc(struct json_object *jso, int64_t val)
{
+ struct json_object_int *jsoint;
if (!jso || jso->o_type != json_type_int)
return 0;
- switch (jso->o.c_int.cint_type)
+ jsoint = JC_INT(jso);
+ switch (jsoint->cint_type)
{
case json_object_int_type_int64:
- if (val > 0 && jso->o.c_int.cint.c_int64 > INT64_MAX - val)
+ if (val > 0 && jsoint->cint.c_int64 > INT64_MAX - val)
{
- jso->o.c_int.cint.c_uint64 =
- (uint64_t)jso->o.c_int.cint.c_int64 + (uint64_t)val;
- jso->o.c_int.cint_type = json_object_int_type_uint64;
+ jsoint->cint.c_uint64 = (uint64_t)jsoint->cint.c_int64 + (uint64_t)val;
+ jsoint->cint_type = json_object_int_type_uint64;
}
- else if (val < 0 && jso->o.c_int.cint.c_int64 < INT64_MIN - val)
+ else if (val < 0 && jsoint->cint.c_int64 < INT64_MIN - val)
{
- jso->o.c_int.cint.c_int64 = INT64_MIN;
+ jsoint->cint.c_int64 = INT64_MIN;
}
else
{
- jso->o.c_int.cint.c_int64 += val;
+ jsoint->cint.c_int64 += val;
}
return 1;
case json_object_int_type_uint64:
- if (val > 0 && jso->o.c_int.cint.c_uint64 > UINT64_MAX - (uint64_t)val)
+ if (val > 0 && jsoint->cint.c_uint64 > UINT64_MAX - (uint64_t)val)
{
- jso->o.c_int.cint.c_uint64 = UINT64_MAX;
+ jsoint->cint.c_uint64 = UINT64_MAX;
}
- else if (val < 0 && jso->o.c_int.cint.c_uint64 < (uint64_t)(-val))
+ else if (val < 0 && jsoint->cint.c_uint64 < (uint64_t)(-val))
{
- jso->o.c_int.cint.c_int64 = (int64_t)jso->o.c_int.cint.c_uint64 + val;
- jso->o.c_int.cint_type = json_object_int_type_int64;
+ jsoint->cint.c_int64 = (int64_t)jsoint->cint.c_uint64 + val;
+ jsoint->cint_type = json_object_int_type_int64;
}
- else if (val < 0 && jso->o.c_int.cint.c_uint64 >= (uint64_t)(-val))
+ else if (val < 0 && jsoint->cint.c_uint64 >= (uint64_t)(-val))
{
- jso->o.c_int.cint.c_uint64 -= (uint64_t)(-val);
+ jsoint->cint.c_uint64 -= (uint64_t)(-val);
}
else
{
- jso->o.c_int.cint.c_uint64 += val;
+ jsoint->cint.c_uint64 += val;
}
return 1;
default: json_abort("invalid cint_type");
@@ -896,6 +1004,7 @@ int json_c_set_serialization_double_format(const char *double_format, int global
static int json_object_double_to_json_string_format(struct json_object *jso, struct printbuf *pb,
int level, int flags, const char *format)
{
+ struct json_object_double *jsodbl = JC_DOUBLE(jso);
char buf[128], *p, *q;
int size;
/* Although JSON RFC does not support
@@ -903,13 +1012,13 @@ static int json_object_double_to_json_string_format(struct json_object *jso, str
* ECMA 262 section 9.8.1 defines
* how to handle these cases as strings
*/
- if (isnan(jso->o.c_double))
+ if (isnan(jsodbl->c_double))
{
size = snprintf(buf, sizeof(buf), "NaN");
}
- else if (isinf(jso->o.c_double))
+ else if (isinf(jsodbl->c_double))
{
- if (jso->o.c_double > 0)
+ if (jsodbl->c_double > 0)
size = snprintf(buf, sizeof(buf), "Infinity");
else
size = snprintf(buf, sizeof(buf), "-Infinity");
@@ -932,7 +1041,7 @@ static int json_object_double_to_json_string_format(struct json_object *jso, str
else
format = std_format;
}
- size = snprintf(buf, sizeof(buf), format, jso->o.c_double);
+ size = snprintf(buf, sizeof(buf), format, jsodbl->c_double);
if (size < 0)
return -1;
@@ -1001,12 +1110,12 @@ int json_object_double_to_json_string(struct json_object *jso, struct printbuf *
struct json_object *json_object_new_double(double d)
{
- struct json_object *jso = json_object_new(json_type_double);
+ struct json_object_double *jso = JSON_OBJECT_NEW(double);
if (!jso)
return NULL;
- jso->_to_json_string = &json_object_double_to_json_string_default;
- jso->o.c_double = d;
- return jso;
+ jso->base._to_json_string = &json_object_double_to_json_string_default;
+ jso->c_double = d;
+ return &jso->base;
}
struct json_object *json_object_new_double_s(double d, const char *ds)
@@ -1061,15 +1170,15 @@ double json_object_get_double(const struct json_object *jso)
return 0.0;
switch (jso->o_type)
{
- case json_type_double: return jso->o.c_double;
+ case json_type_double: return JC_DOUBLE_C(jso)->c_double;
case json_type_int:
- switch (jso->o.c_int.cint_type)
+ switch (JC_INT_C(jso)->cint_type)
{
- case json_object_int_type_int64: return jso->o.c_int.cint.c_int64;
- case json_object_int_type_uint64: return jso->o.c_int.cint.c_uint64;
+ case json_object_int_type_int64: return JC_INT_C(jso)->cint.c_int64;
+ case json_object_int_type_uint64: return JC_INT_C(jso)->cint.c_uint64;
default: json_abort("invalid cint_type");
}
- case json_type_boolean: return jso->o.c_boolean;
+ case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_string:
errno = 0;
cdouble = strtod(get_string_component(jso), &errPtr);
@@ -1114,7 +1223,7 @@ int json_object_set_double(struct json_object *jso, double new_value)
{
if (!jso || jso->o_type != json_type_double)
return 0;
- jso->o.c_double = new_value;
+ JC_DOUBLE(jso)->c_double = new_value;
if (jso->_to_json_string == &_json_object_userdata_to_json_string)
json_object_set_serializer(jso, NULL, NULL, NULL);
return 1;
@@ -1125,71 +1234,65 @@ int json_object_set_double(struct json_object *jso, double new_value)
static int json_object_string_to_json_string(struct json_object *jso, struct printbuf *pb,
int level, int flags)
{
+ ssize_t len = JC_STRING(jso)->len;
printbuf_strappend(pb, "\"");
- json_escape_str(pb, get_string_component(jso), jso->o.c_string.len, flags);
+ json_escape_str(pb, get_string_component(jso), len < 0 ? -(ssize_t)len : len, flags);
printbuf_strappend(pb, "\"");
return 0;
}
static void json_object_string_delete(struct json_object *jso)
{
- if (jso->o.c_string.len >= LEN_DIRECT_STRING_DATA)
- free(jso->o.c_string.str.ptr);
+ if (JC_STRING(jso)->len < 0)
+ free(JC_STRING(jso)->c_string.pdata);
json_object_generic_delete(jso);
}
-struct json_object *json_object_new_string(const char *s)
+static struct json_object *_json_object_new_string(const char *s, const size_t len)
{
- struct json_object *jso = json_object_new(json_type_string);
+ size_t objsize;
+ struct json_object_string *jso;
+
+ /*
+ * Structures Actual memory layout
+ * ------------------- --------------------
+ * [json_object_string [json_object_string
+ * [json_object] [json_object]
+ * ...other fields... ...other fields...
+ * c_string] len
+ * bytes
+ * of
+ * string
+ * data
+ * \0]
+ */
+ if (len > (SSIZE_T_MAX - (sizeof(*jso) - sizeof(jso->c_string)) - 1))
+ return NULL;
+ objsize = (sizeof(*jso) - sizeof(jso->c_string)) + len + 1;
+ if (len < sizeof(void *))
+ // We need a minimum size to support json_object_set_string() mutability
+ // so we can stuff a pointer into pdata :(
+ objsize += sizeof(void *) - len;
+
+ jso = (struct json_object_string *)json_object_new(json_type_string, objsize,
+ &json_object_string_to_json_string);
+
if (!jso)
return NULL;
- jso->_delete = &json_object_string_delete;
- jso->_to_json_string = &json_object_string_to_json_string;
- jso->o.c_string.len = strlen(s);
- if (jso->o.c_string.len < LEN_DIRECT_STRING_DATA)
- {
- memcpy(jso->o.c_string.str.data, s, jso->o.c_string.len);
- }
- else
- {
- jso->o.c_string.str.ptr = strdup(s);
- if (!jso->o.c_string.str.ptr)
- {
- json_object_generic_delete(jso);
- errno = ENOMEM;
- return NULL;
- }
- }
- return jso;
+ jso->len = len;
+ memcpy(jso->c_string.idata, s, len);
+ jso->c_string.idata[len] = '\0';
+ return &jso->base;
+}
+
+struct json_object *json_object_new_string(const char *s)
+{
+ return _json_object_new_string(s, strlen(s));
}
struct json_object *json_object_new_string_len(const char *s, const int len)
{
- char *dstbuf;
- struct json_object *jso = json_object_new(json_type_string);
- if (!jso)
- return NULL;
- jso->_delete = &json_object_string_delete;
- jso->_to_json_string = &json_object_string_to_json_string;
- if (len < LEN_DIRECT_STRING_DATA)
- {
- dstbuf = jso->o.c_string.str.data;
- }
- else
- {
- jso->o.c_string.str.ptr = (char *)malloc(len + 1);
- if (!jso->o.c_string.str.ptr)
- {
- json_object_generic_delete(jso);
- errno = ENOMEM;
- return NULL;
- }
- dstbuf = jso->o.c_string.str.ptr;
- }
- memcpy(dstbuf, (const void *)s, len);
- dstbuf[len] = '\0';
- jso->o.c_string.len = len;
- return jso;
+ return _json_object_new_string(s, len);
}
const char *json_object_get_string(struct json_object *jso)
@@ -1202,49 +1305,78 @@ const char *json_object_get_string(struct json_object *jso)
default: return json_object_to_json_string(jso);
}
}
-
int json_object_get_string_len(const struct json_object *jso)
{
+ ssize_t len;
if (!jso)
return 0;
switch (jso->o_type)
{
- case json_type_string: return jso->o.c_string.len;
+ case json_type_string:
+ {
+ len = JC_STRING_C(jso)->len;
+ return (len < 0) ? -(ssize_t)len : len;
+ }
default: return 0;
}
}
-int json_object_set_string(json_object *jso, const char *s)
-{
- return json_object_set_string_len(jso, s, (int)(strlen(s)));
-}
-
-int json_object_set_string_len(json_object *jso, const char *s, int len)
+static int _json_object_set_string_len(json_object *jso, const char *s, size_t len)
{
char *dstbuf;
+ ssize_t curlen;
+ ssize_t newlen;
if (jso == NULL || jso->o_type != json_type_string)
return 0;
- if (len < LEN_DIRECT_STRING_DATA)
- {
- dstbuf = jso->o.c_string.str.data;
- if (jso->o.c_string.len >= LEN_DIRECT_STRING_DATA)
- free(jso->o.c_string.str.ptr);
- }
- else
+
+ if (len >= INT_MAX - 1)
+ // jso->len is a signed ssize_t, so it can't hold the
+ // full size_t range. json_object_get_string_len returns
+ // length as int, cap length at INT_MAX.
+ return 0;
+
+ dstbuf = get_string_component_mutable(jso);
+ curlen = JC_STRING(jso)->len;
+ if (curlen < 0)
+ curlen = -curlen;
+ newlen = len;
+
+ if ((ssize_t)len > curlen)
{
+ // We have no way to return the new ptr from realloc(jso, newlen)
+ // and we have no way of knowing whether there's extra room available
+ // so we need to stuff a pointer in to pdata :(
dstbuf = (char *)malloc(len + 1);
if (dstbuf == NULL)
return 0;
- if (jso->o.c_string.len >= LEN_DIRECT_STRING_DATA)
- free(jso->o.c_string.str.ptr);
- jso->o.c_string.str.ptr = dstbuf;
+ if (JC_STRING(jso)->len < 0)
+ free(JC_STRING(jso)->c_string.pdata);
+ JC_STRING(jso)->c_string.pdata = dstbuf;
+ newlen = -(ssize_t)len;
}
- jso->o.c_string.len = len;
+ else if (JC_STRING(jso)->len < 0)
+ {
+ // We've got enough room in the separate allocated buffer,
+ // so use it as-is and continue to indicate that pdata is used.
+ newlen = -(ssize_t)len;
+ }
+
memcpy(dstbuf, (const void *)s, len);
dstbuf[len] = '\0';
+ JC_STRING(jso)->len = newlen;
return 1;
}
+int json_object_set_string(json_object *jso, const char *s)
+{
+ return _json_object_set_string_len(jso, s, strlen(s));
+}
+
+int json_object_set_string_len(json_object *jso, const char *s, int len)
+{
+ return _json_object_set_string_len(jso, s, len);
+}
+
/* json_object_array */
static int json_object_array_to_json_string(struct json_object *jso, struct printbuf *pb, int level,
@@ -1294,24 +1426,26 @@ static void json_object_array_entry_free(void *data)
static void json_object_array_delete(struct json_object *jso)
{
- array_list_free(jso->o.c_array);
+ array_list_free(JC_ARRAY(jso)->c_array);
json_object_generic_delete(jso);
}
struct json_object *json_object_new_array(void)
{
- struct json_object *jso = json_object_new(json_type_array);
+ return json_object_new_array_ext(ARRAY_LIST_DEFAULT_SIZE);
+}
+struct json_object *json_object_new_array_ext(int initial_size)
+{
+ struct json_object_array *jso = JSON_OBJECT_NEW(array);
if (!jso)
return NULL;
- jso->_delete = &json_object_array_delete;
- jso->_to_json_string = &json_object_array_to_json_string;
- jso->o.c_array = array_list_new(&json_object_array_entry_free);
- if (jso->o.c_array == NULL)
+ jso->c_array = array_list_new2(&json_object_array_entry_free, initial_size);
+ if (jso->c_array == NULL)
{
free(jso);
return NULL;
}
- return jso;
+ return &jso->base;
}
struct array_list *json_object_get_array(const struct json_object *jso)
@@ -1320,7 +1454,7 @@ struct array_list *json_object_get_array(const struct json_object *jso)
return NULL;
switch (jso->o_type)
{
- case json_type_array: return jso->o.c_array;
+ case json_type_array: return JC_ARRAY_C(jso)->c_array;
default: return NULL;
}
}
@@ -1328,7 +1462,7 @@ struct array_list *json_object_get_array(const struct json_object *jso)
void json_object_array_sort(struct json_object *jso, int (*sort_fn)(const void *, const void *))
{
assert(json_object_get_type(jso) == json_type_array);
- array_list_sort(jso->o.c_array, sort_fn);
+ array_list_sort(JC_ARRAY(jso)->c_array, sort_fn);
}
struct json_object *json_object_array_bsearch(const struct json_object *key,
@@ -1339,7 +1473,7 @@ struct json_object *json_object_array_bsearch(const struct json_object *key,
assert(json_object_get_type(jso) == json_type_array);
result = (struct json_object **)array_list_bsearch((const void **)(void *)&key,
- jso->o.c_array, sort_fn);
+ JC_ARRAY_C(jso)->c_array, sort_fn);
if (!result)
return NULL;
@@ -1349,31 +1483,31 @@ struct json_object *json_object_array_bsearch(const struct json_object *key,
size_t json_object_array_length(const struct json_object *jso)
{
assert(json_object_get_type(jso) == json_type_array);
- return array_list_length(jso->o.c_array);
+ return array_list_length(JC_ARRAY_C(jso)->c_array);
}
int json_object_array_add(struct json_object *jso, struct json_object *val)
{
assert(json_object_get_type(jso) == json_type_array);
- return array_list_add(jso->o.c_array, val);
+ return array_list_add(JC_ARRAY(jso)->c_array, val);
}
int json_object_array_put_idx(struct json_object *jso, size_t idx, struct json_object *val)
{
assert(json_object_get_type(jso) == json_type_array);
- return array_list_put_idx(jso->o.c_array, idx, val);
+ return array_list_put_idx(JC_ARRAY(jso)->c_array, idx, val);
}
int json_object_array_del_idx(struct json_object *jso, size_t idx, size_t count)
{
assert(json_object_get_type(jso) == json_type_array);
- return array_list_del_idx(jso->o.c_array, idx, count);
+ return array_list_del_idx(JC_ARRAY(jso)->c_array, idx, count);
}
struct json_object *json_object_array_get_idx(const struct json_object *jso, size_t idx)
{
assert(json_object_get_type(jso) == json_type_array);
- return (struct json_object *)array_list_get_idx(jso->o.c_array, idx);
+ return (struct json_object *)array_list_get_idx(JC_ARRAY_C(jso)->c_array, idx);
}
static int json_array_equal(struct json_object *jso1, struct json_object *jso2)
@@ -1393,6 +1527,13 @@ static int json_array_equal(struct json_object *jso1, struct json_object *jso2)
return 1;
}
+int json_object_array_shrink(struct json_object *jso, int empty_slots)
+{
+ if (empty_slots < 0)
+ json_abort("json_object_array_shrink called with negative empty_slots");
+ return array_list_shrink(JC_ARRAY(jso)->c_array, empty_slots);
+}
+
struct json_object *json_object_new_null(void)
{
return NULL;
@@ -1408,7 +1549,8 @@ static int json_object_all_values_equal(struct json_object *jso1, struct json_ob
/* Iterate over jso1 keys and see if they exist and are equal in jso2 */
json_object_object_foreachC(jso1, iter)
{
- if (!lh_table_lookup_ex(jso2->o.c_object, (void *)iter.key, (void **)(void *)&sub))
+ if (!lh_table_lookup_ex(JC_OBJECT(jso2)->c_object, (void *)iter.key,
+ (void **)(void *)&sub))
return 0;
if (!json_object_equal(iter.val, sub))
return 0;
@@ -1417,7 +1559,8 @@ static int json_object_all_values_equal(struct json_object *jso1, struct json_ob
/* Iterate over jso2 keys to see if any exist that are not in jso1 */
json_object_object_foreachC(jso2, iter)
{
- if (!lh_table_lookup_ex(jso1->o.c_object, (void *)iter.key, (void **)(void *)&sub))
+ if (!lh_table_lookup_ex(JC_OBJECT(jso1)->c_object, (void *)iter.key,
+ (void **)(void *)&sub))
return 0;
}
@@ -1437,31 +1580,36 @@ int json_object_equal(struct json_object *jso1, struct json_object *jso2)
switch (jso1->o_type)
{
- case json_type_boolean: return (jso1->o.c_boolean == jso2->o.c_boolean);
+ case json_type_boolean: return (JC_BOOL(jso1)->c_boolean == JC_BOOL(jso2)->c_boolean);
- case json_type_double: return (jso1->o.c_double == jso2->o.c_double);
+ case json_type_double: return (JC_DOUBLE(jso1)->c_double == JC_DOUBLE(jso2)->c_double);
case json_type_int:
- if (jso1->o.c_int.cint_type == json_object_int_type_int64)
+ {
+ struct json_object_int *int1 = JC_INT(jso1);
+ struct json_object_int *int2 = JC_INT(jso2);
+ if (int1->cint_type == json_object_int_type_int64)
{
- if (jso2->o.c_int.cint_type == json_object_int_type_int64)
- return (jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_int64);
- if (jso1->o.c_int.cint.c_int64 < 0)
+ if (int2->cint_type == json_object_int_type_int64)
+ return (int1->cint.c_int64 == int2->cint.c_int64);
+ if (int1->cint.c_int64 < 0)
return 0;
- return ((uint64_t)jso1->o.c_int.cint.c_int64 ==
- jso2->o.c_int.cint.c_uint64);
+ return ((uint64_t)int1->cint.c_int64 == int2->cint.c_uint64);
}
// else jso1 is a uint64
- if (jso2->o.c_int.cint_type == json_object_int_type_uint64)
- return (jso1->o.c_int.cint.c_uint64 == jso2->o.c_int.cint.c_uint64);
- if (jso2->o.c_int.cint.c_int64 < 0)
+ if (int2->cint_type == json_object_int_type_uint64)
+ return (int1->cint.c_uint64 == int2->cint.c_uint64);
+ if (int2->cint.c_int64 < 0)
return 0;
- return (jso1->o.c_int.cint.c_uint64 == (uint64_t)jso2->o.c_int.cint.c_int64);
+ return (int1->cint.c_uint64 == (uint64_t)int2->cint.c_int64);
+ }
case json_type_string:
- return (jso1->o.c_string.len == jso2->o.c_string.len &&
+ {
+ return (json_object_get_string_len(jso1) == json_object_get_string_len(jso2) &&
memcmp(get_string_component(jso1), get_string_component(jso2),
- jso1->o.c_string.len) == 0);
+ json_object_get_string_len(jso1)) == 0);
+ }
case json_type_object: return json_object_all_values_equal(jso1, jso2);
@@ -1488,7 +1636,7 @@ static int json_object_copy_serializer_data(struct json_object *src, struct json
{
_json_c_set_last_err(
"json_object_deep_copy: unable to copy unknown serializer data: %p\n",
- dst->_to_json_string);
+ (void *)dst->_to_json_string);
return -1;
}
dst->_user_delete = src->_user_delete;
@@ -1508,18 +1656,18 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha
{
switch (src->o_type)
{
- case json_type_boolean: *dst = json_object_new_boolean(src->o.c_boolean); break;
+ case json_type_boolean: *dst = json_object_new_boolean(JC_BOOL(src)->c_boolean); break;
- case json_type_double: *dst = json_object_new_double(src->o.c_double); break;
+ case json_type_double: *dst = json_object_new_double(JC_DOUBLE(src)->c_double); break;
case json_type_int:
- switch (src->o.c_int.cint_type)
+ switch (JC_INT(src)->cint_type)
{
case json_object_int_type_int64:
- *dst = json_object_new_int64(src->o.c_int.cint.c_int64);
+ *dst = json_object_new_int64(JC_INT(src)->cint.c_int64);
break;
case json_object_int_type_uint64:
- *dst = json_object_new_uint64(src->o.c_int.cint.c_uint64);
+ *dst = json_object_new_uint64(JC_INT(src)->cint.c_uint64);
break;
default: json_abort("invalid cint_type");
}
@@ -1577,7 +1725,7 @@ static int json_object_deep_copy_recursive(struct json_object *src, struct json_
/* This handles the `json_type_null` case */
if (!iter.val)
jso = NULL;
- else if (json_object_deep_copy_recursive(iter.val, src, iter.key, -1, &jso,
+ else if (json_object_deep_copy_recursive(iter.val, src, iter.key, UINT_MAX, &jso,
shallow_copy) < 0)
{
json_object_put(jso);
@@ -1642,7 +1790,7 @@ int json_object_deep_copy(struct json_object *src, struct json_object **dst,
if (shallow_copy == NULL)
shallow_copy = json_c_shallow_copy_default;
- rc = json_object_deep_copy_recursive(src, NULL, NULL, -1, dst, shallow_copy);
+ rc = json_object_deep_copy_recursive(src, NULL, NULL, UINT_MAX, dst, shallow_copy);
if (rc < 0)
{
json_object_put(*dst);
diff --git a/json_object.h b/json_object.h
index be6919a..d67f384 100644
--- a/json_object.h
+++ b/json_object.h
@@ -18,16 +18,6 @@
#define _json_object_h_
#ifdef __GNUC__
-#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__((deprecated))
-#elif defined(_MSC_VER)
-#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func
-#elif defined(__clang__)
-#define THIS_FUNCTION_IS_DEPRECATED(func) func __deprecated
-#else
-#define THIS_FUNCTION_IS_DEPRECATED(func) func
-#endif
-
-#ifdef __GNUC__
#define JSON_C_CONST_FUNCTION(func) func __attribute__((const))
#else
#define JSON_C_CONST_FUNCTION(func) func
@@ -133,21 +123,43 @@ extern "C" {
/* reference counting functions */
/**
- * Increment the reference count of json_object, thereby grabbing shared
- * ownership of obj.
+ * Increment the reference count of json_object, thereby taking ownership of it.
+ *
+ * Cases where you might need to increase the refcount include:
+ * - Using an object field or array index (retrieved through
+ * `json_object_object_get()` or `json_object_array_get_idx()`)
+ * beyond the lifetime of the parent object.
+ * - Detaching an object field or array index from its parent object
+ * (using `json_object_object_del()` or `json_object_array_del_idx()`)
+ * - Sharing a json_object with multiple (not necesarily parallel) threads
+ * of execution that all expect to free it (with `json_object_put()`) when
+ * they're done.
*
* @param obj the json_object instance
+ * @see json_object_put()
+ * @see json_object_object_get()
+ * @see json_object_array_get_idx()
*/
JSON_EXPORT struct json_object *json_object_get(struct json_object *obj);
/**
* Decrement the reference count of json_object and free if it reaches zero.
+ *
* You must have ownership of obj prior to doing this or you will cause an
- * imbalance in the reference count.
- * An obj of NULL may be passed; in that case this call is a no-op.
+ * imbalance in the reference count, leading to a classic use-after-free bug.
+ * In particular, you normally do not need to call `json_object_put()` on the
+ * json_object returned by `json_object_object_get()` or `json_object_array_get_idx()`.
+ *
+ * Just like after calling `free()` on a block of memory, you must not use
+ * `obj` after calling `json_object_put()` on it or any object that it
+ * is a member of (unless you know you've called `json_object_get(obj)` to
+ * explicitly increment the refcount).
+ *
+ * NULL may be passed, which which case this is a no-op.
*
* @param obj the json_object instance
* @returns 1 if the object was freed.
+ * @see json_object_get()
*/
JSON_EXPORT int json_object_put(struct json_object *obj);
@@ -347,15 +359,21 @@ JSON_C_CONST_FUNCTION(JSON_EXPORT size_t json_c_object_sizeof(void));
/** Add an object field to a json_object of type json_type_object
*
- * The reference count will *not* be incremented. This is to make adding
- * fields to objects in code more compact. If you want to retain a reference
- * to an added object, independent of the lifetime of obj, you must wrap the
- * passed object with json_object_get.
+ * The reference count of `val` will *not* be incremented, in effect
+ * transferring ownership that object to `obj`, and thus `val` will be
+ * freed when `obj` is. (i.e. through `json_object_put(obj)`)
+ *
+ * If you want to retain a reference to the added object, independent
+ * of the lifetime of obj, you must increment the refcount with
+ * `json_object_get(val)` (and later release it with json_object_put()).
+ *
+ * Since ownership transfers to `obj`, you must make sure
+ * that you do in fact have ownership over `val`. For instance,
+ * json_object_new_object() will give you ownership until you transfer it,
+ * whereas json_object_object_get() does not.
*
- * Upon calling this, the ownership of val transfers to obj. Thus you must
- * make sure that you do in fact have ownership over this object. For instance,
- * json_object_new_object will give you ownership until you transfer it,
- * whereas json_object_object_get does not.
+ * Any previous object stored under `key` in `obj` will have its refcount
+ * decremented, and be freed normally if that drops to zero.
*
* @param obj the json_object instance
* @param key the object field name (a private copy will be duplicated)
@@ -378,7 +396,7 @@ JSON_EXPORT int json_object_object_add(struct json_object *obj, const char *key,
* @param key the object field name (a private copy will be duplicated)
* @param val a json_object or NULL member to associate with the given field
* @param opts process-modifying options. To specify multiple options, use
- * arithmetic or (OPT1|OPT2)
+ * (OPT1|OPT2)
*/
JSON_EXPORT int json_object_object_add_ex(struct json_object *obj, const char *const key,
struct json_object *const val, const unsigned opts);
@@ -500,10 +518,23 @@ JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key
/* Array type methods */
/** Create a new empty json_object of type json_type_array
+ * with 32 slots allocated.
+ * If you know the array size you'll need ahead of time, use
+ * json_object_new_array_ext() instead.
+ * @see json_object_new_array_ext()
+ * @see json_object_array_shrink()
* @returns a json_object of type json_type_array
*/
JSON_EXPORT struct json_object *json_object_new_array(void);
+/** Create a new empty json_object of type json_type_array
+ * with the desired number of slots allocated.
+ * @see json_object_array_shrink()
+ * @param initial_size the number of slots to allocate
+ * @returns a json_object of type json_type_array
+ */
+JSON_EXPORT struct json_object *json_object_new_array_ext(int initial_size);
+
/** Get the arraylist of a json_object of type json_type_array
* @param obj the json_object instance
* @returns an arraylist
@@ -574,7 +605,15 @@ JSON_EXPORT int json_object_array_add(struct json_object *obj, struct json_objec
JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx,
struct json_object *val);
-/** Get the element at specified index of the array (a json_object of type json_type_array)
+/** Get the element at specified index of array `obj` (which must be a json_object of type json_type_array)
+ *
+ * *No* reference counts will be changed, and ownership of the returned
+ * object remains with `obj`. See json_object_object_get() for additional
+ * implications of this behavior.
+ *
+ * Calling this with anything other than a json_type_array will trigger
+ * an assert.
+ *
* @param obj the json_object instance
* @param idx the index to get the element at
* @returns the json_object at the specified index (or NULL)
@@ -595,6 +634,15 @@ JSON_EXPORT struct json_object *json_object_array_get_idx(const struct json_obje
*/
JSON_EXPORT int json_object_array_del_idx(struct json_object *obj, size_t idx, size_t count);
+/**
+ * Shrink the internal memory allocation of the array to just
+ * enough to fit the number of elements in it, plus empty_slots.
+ *
+ * @param jso the json_object instance, must be json_type_array
+ * @param empty_slots the number of empty slots to leave allocated
+ */
+JSON_EXPORT int json_object_array_shrink(struct json_object *jso, int empty_slots);
+
/* json_bool type methods */
/** Create a new empty json_object of type json_type_boolean
@@ -608,8 +656,9 @@ JSON_EXPORT struct json_object *json_object_new_boolean(json_bool b);
* The type is coerced to a json_bool if the passed object is not a json_bool.
* integer and double objects will return 0 if there value is zero
* or 1 otherwise. If the passed object is a string it will return
- * 1 if it has a non zero length. If any other object type is passed
- * 1 will be returned if the object is not NULL.
+ * 1 if it has a non zero length.
+ * If any other object type is passed 0 will be returned, even non-empty
+ * json_type_array and json_type_object objects.
*
* @param obj the json_object instance
* @returns a json_bool
diff --git a/json_object_iterator.c b/json_object_iterator.c
index 796015e..1c2b3f2 100644
--- a/json_object_iterator.c
+++ b/json_object_iterator.c
@@ -9,6 +9,7 @@
*
*******************************************************************************
*/
+#include "config.h"
#include <stddef.h>
diff --git a/json_object_private.h b/json_object_private.h
index 1c7737a..e143b46 100644
--- a/json_object_private.h
+++ b/json_object_private.h
@@ -20,14 +20,18 @@
extern "C" {
#endif
-/**< how many bytes are directly stored in json_object for strings? */
-#define LEN_DIRECT_STRING_DATA 32
-
struct json_object;
#include "json_inttypes.h"
#include "json_types.h"
-typedef void(json_object_private_delete_fn)(struct json_object *o);
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef _MSC_VER
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
/* json object int type, support extension*/
typedef enum json_object_int_type
@@ -40,44 +44,60 @@ struct json_object
{
enum json_type o_type;
uint32_t _ref_count;
- json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
struct printbuf *_pb;
- union data
- {
- json_bool c_boolean;
- double c_double;
- struct
- {
- union
- {
- int64_t c_int64;
- uint64_t c_uint64;
- } cint;
- enum json_object_int_type cint_type;
- } c_int;
- struct lh_table *c_object;
- struct array_list *c_array;
- struct
- {
- union
- {
- /* optimize: if we have small strings, we can store them
- * directly. This saves considerable CPU cycles AND memory.
- */
- char *ptr;
- char data[LEN_DIRECT_STRING_DATA];
- } str;
- int len;
- } c_string;
- } o;
json_object_delete_fn *_user_delete;
void *_userdata;
+ // Actually longer, always malloc'd as some more-specific type.
+ // The rest of a struct json_object_${o_type} follows
+};
+
+struct json_object_object
+{
+ struct json_object base;
+ struct lh_table *c_object;
+};
+struct json_object_array
+{
+ struct json_object base;
+ struct array_list *c_array;
+};
+
+struct json_object_boolean
+{
+ struct json_object base;
+ json_bool c_boolean;
+};
+struct json_object_double
+{
+ struct json_object base;
+ double c_double;
+};
+struct json_object_int
+{
+ struct json_object base;
+ enum json_object_int_type cint_type;
+ union
+ {
+ int64_t c_int64;
+ uint64_t c_uint64;
+ } cint;
+};
+struct json_object_string
+{
+ struct json_object base;
+ ssize_t len; // Signed b/c negative lengths indicate data is a pointer
+ // Consider adding an "alloc" field here, if json_object_set_string calls
+ // to expand the length of a string are common operations to perform.
+ union
+ {
+ char idata[1]; // Immediate data. Actually longer
+ char *pdata; // Only when len < 0
+ } c_string;
};
void _json_c_set_last_err(const char *err_fmt, ...);
-extern const char *json_number_chars;
extern const char *json_hex_chars;
#ifdef __cplusplus
diff --git a/json_tokener.c b/json_tokener.c
index 0373d6f..aad463a 100644
--- a/json_tokener.c
+++ b/json_tokener.c
@@ -97,6 +97,8 @@ static const char *json_tokener_errors[] = {
*/
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);
+static int json_tokener_parse_double(const char *buf, int len, double *retval);
+
const char *json_tokener_error_desc(enum json_tokener_error jerr)
{
int jerr_int = (int)jerr;
@@ -132,6 +134,12 @@ struct json_tokener *json_tokener_new_ex(int depth)
return NULL;
}
tok->pb = printbuf_new();
+ if (!tok->pb)
+ {
+ free(tok);
+ free(tok->stack);
+ return NULL;
+ }
tok->max_depth = depth;
json_tokener_reset(tok);
return tok;
@@ -191,7 +199,17 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
return NULL;
obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err;
- if (tok->err != json_tokener_success)
+ if (tok->err != json_tokener_success
+#if 0
+ /* This would be a more sensible default, and cause parsing
+ * things like "null123" to fail when the caller can't know
+ * where the parsing left off, but starting to fail would
+ * be a notable behaviour change. Save for a 1.0 release.
+ */
+ || json_tokener_get_parse_end(tok) != strlen(str)
+#endif
+ )
+
{
if (obj != NULL)
json_object_put(obj);
@@ -223,7 +241,7 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
/* PEEK_CHAR(dest, tok) macro:
* Peeks at the current char and stores it in dest.
* Returns 1 on success, sets tok->err and returns 0 if no more chars.
- * Implicit inputs: str, len vars
+ * Implicit inputs: str, len, nBytesp vars
*/
#define PEEK_CHAR(dest, tok) \
(((tok)->char_offset == len) \
@@ -295,7 +313,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
}
#endif
- while (PEEK_CHAR(c, tok))
+ while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
{
redo_char:
@@ -418,7 +436,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
{
char inf_char = *str;
if (!(tok->flags & JSON_TOKENER_STRICT))
- inf_char = tolower((int)*str);
+ inf_char = tolower((unsigned char)*str);
if (inf_char != _json_inf_str[tok->st_pos])
{
tok->err = json_tokener_error_parse_unexpected;
@@ -628,173 +646,165 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
}
break;
+ // ===================================================
+
case json_tokener_state_escape_unicode:
{
- unsigned int got_hi_surrogate = 0;
-
- /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
+ /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
while (1)
{
- if (c && strchr(json_hex_chars, c))
- {
- tok->ucs_char += ((unsigned int)jt_hexdigit(c)
- << ((3 - tok->st_pos++) * 4));
- if (tok->st_pos == 4)
- {
- unsigned char unescaped_utf[4];
-
- if (got_hi_surrogate)
- {
- if (IS_LOW_SURROGATE(tok->ucs_char))
- {
- /* Recalculate the ucs_char, then fall thru to process normally */
- tok->ucs_char =
- DECODE_SURROGATE_PAIR(
- got_hi_surrogate,
- tok->ucs_char);
- }
- else
- {
- /* Hi surrogate was not followed by a low surrogate */
- /* Replace the hi and process the rest normally */
- printbuf_memappend_fast(
- tok->pb,
- (char *)utf8_replacement_char,
- 3);
- }
- got_hi_surrogate = 0;
- }
-
- if (tok->ucs_char < 0x80)
- {
- unescaped_utf[0] = tok->ucs_char;
- printbuf_memappend_fast(
- tok->pb, (char *)unescaped_utf, 1);
- }
- else if (tok->ucs_char < 0x800)
- {
- unescaped_utf[0] =
- 0xc0 | (tok->ucs_char >> 6);
- unescaped_utf[1] =
- 0x80 | (tok->ucs_char & 0x3f);
- printbuf_memappend_fast(
- tok->pb, (char *)unescaped_utf, 2);
- }
- else if (IS_HIGH_SURROGATE(tok->ucs_char))
- {
- /* Got a high surrogate. Remember it and look for
- * the beginning of another sequence, which
- * should be the low surrogate.
- */
- got_hi_surrogate = tok->ucs_char;
- /* Not at end, and the next two chars should be "\u" */
- if ((len == -1 ||
- len > (tok->char_offset + 2)) &&
- // str[0] != '0' && // implied by json_hex_chars, above.
- (str[1] == '\\') && (str[2] == 'u'))
- {
- /* Advance through the 16 bit surrogate, and move
- * on to the next sequence. The next step is to
- * process the following characters.
- */
- if (!ADVANCE_CHAR(str, tok) ||
- !ADVANCE_CHAR(str, tok))
- {
- printbuf_memappend_fast(
- tok->pb,
- (char *)
- utf8_replacement_char,
- 3);
- }
- /* Advance to the first char of the next sequence and
- * continue processing with the next sequence.
- */
- if (!ADVANCE_CHAR(str, tok) ||
- !PEEK_CHAR(c, tok))
- {
- printbuf_memappend_fast(
- tok->pb,
- (char *)
- utf8_replacement_char,
- 3);
- goto out;
- }
- tok->ucs_char = 0;
- tok->st_pos = 0;
- /* other json_tokener_state_escape_unicode */
- continue;
- }
- else
- {
- /* Got a high surrogate without another sequence following
- * it. Put a replacement char in for the hi surrogate
- * and pretend we finished.
- */
- printbuf_memappend_fast(
- tok->pb,
- (char *)utf8_replacement_char,
- 3);
- }
- }
- else if (IS_LOW_SURROGATE(tok->ucs_char))
- {
- /* Got a low surrogate not preceded by a high */
- printbuf_memappend_fast(
- tok->pb, (char *)utf8_replacement_char,
- 3);
- }
- else if (tok->ucs_char < 0x10000)
- {
- unescaped_utf[0] =
- 0xe0 | (tok->ucs_char >> 12);
- unescaped_utf[1] =
- 0x80 | ((tok->ucs_char >> 6) & 0x3f);
- unescaped_utf[2] =
- 0x80 | (tok->ucs_char & 0x3f);
- printbuf_memappend_fast(
- tok->pb, (char *)unescaped_utf, 3);
- }
- else if (tok->ucs_char < 0x110000)
- {
- unescaped_utf[0] =
- 0xf0 | ((tok->ucs_char >> 18) & 0x07);
- unescaped_utf[1] =
- 0x80 | ((tok->ucs_char >> 12) & 0x3f);
- unescaped_utf[2] =
- 0x80 | ((tok->ucs_char >> 6) & 0x3f);
- unescaped_utf[3] =
- 0x80 | (tok->ucs_char & 0x3f);
- printbuf_memappend_fast(
- tok->pb, (char *)unescaped_utf, 4);
- }
- else
- {
- /* Don't know what we got--insert the replacement char */
- printbuf_memappend_fast(
- tok->pb, (char *)utf8_replacement_char,
- 3);
- }
- state = saved_state;
- break;
- }
- }
- else
+ if (!c || !strchr(json_hex_chars, c))
{
tok->err = json_tokener_error_parse_string;
goto out;
}
- if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
+ tok->ucs_char |=
+ ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
+ tok->st_pos++;
+ if (tok->st_pos >= 4)
+ break;
+
+ (void)ADVANCE_CHAR(str, tok);
+ if (!PEEK_CHAR(c, tok))
{
- /* Clean up any pending chars */
- if (got_hi_surrogate)
- printbuf_memappend_fast(
- tok->pb, (char *)utf8_replacement_char, 3);
+ /*
+ * We're out of characters in the current call to
+ * json_tokener_parse(), but a subsequent call might
+ * provide us with more, so leave our current state
+ * as-is (including tok->high_surrogate) and return.
+ */
goto out;
}
}
+ tok->st_pos = 0;
+
+ /* Now, we have a full \uNNNN sequence in tok->ucs_char */
+
+ /* If the *previous* sequence was a high surrogate ... */
+ if (tok->high_surrogate)
+ {
+ if (IS_LOW_SURROGATE(tok->ucs_char))
+ {
+ /* Recalculate the ucs_char, then fall thru to process normally */
+ tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
+ tok->ucs_char);
+ }
+ else
+ {
+ /* High surrogate was not followed by a low surrogate
+ * Replace the high and process the rest normally
+ */
+ printbuf_memappend_fast(tok->pb,
+ (char *)utf8_replacement_char, 3);
+ }
+ tok->high_surrogate = 0;
+ }
+
+ if (tok->ucs_char < 0x80)
+ {
+ unsigned char unescaped_utf[1];
+ unescaped_utf[0] = tok->ucs_char;
+ printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 1);
+ }
+ else if (tok->ucs_char < 0x800)
+ {
+ unsigned char unescaped_utf[2];
+ unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
+ unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 2);
+ }
+ else if (IS_HIGH_SURROGATE(tok->ucs_char))
+ {
+ /*
+ * The next two characters should be \u, HOWEVER,
+ * we can't simply peek ahead here, because the
+ * characters we need might not be passed to us
+ * until a subsequent call to json_tokener_parse.
+ * Instead, transition throug a couple of states.
+ * (now):
+ * _escape_unicode => _unicode_need_escape
+ * (see a '\\' char):
+ * _unicode_need_escape => _unicode_need_u
+ * (see a 'u' char):
+ * _unicode_need_u => _escape_unicode
+ * ...and we'll end up back around here.
+ */
+ tok->high_surrogate = tok->ucs_char;
+ tok->ucs_char = 0;
+ state = json_tokener_state_escape_unicode_need_escape;
+ break;
+ }
+ else if (IS_LOW_SURROGATE(tok->ucs_char))
+ {
+ /* Got a low surrogate not preceded by a high */
+ printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+ }
+ else if (tok->ucs_char < 0x10000)
+ {
+ unsigned char unescaped_utf[3];
+ unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
+ unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+ unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 3);
+ }
+ else if (tok->ucs_char < 0x110000)
+ {
+ unsigned char unescaped_utf[4];
+ unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
+ unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
+ unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+ unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 4);
+ }
+ else
+ {
+ /* Don't know what we got--insert the replacement char */
+ printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+ }
+ state = saved_state; // i.e. _state_string or _state_object_field
}
break;
+ case json_tokener_state_escape_unicode_need_escape:
+ // We get here after processing a high_surrogate
+ // require a '\\' char
+ if (!c || c != '\\')
+ {
+ /* Got a high surrogate without another sequence following
+ * it. Put a replacement char in for the high surrogate
+ * and pop back up to _state_string or _state_object_field.
+ */
+ printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+ tok->high_surrogate = 0;
+ tok->ucs_char = 0;
+ tok->st_pos = 0;
+ state = saved_state;
+ goto redo_char;
+ }
+ state = json_tokener_state_escape_unicode_need_u;
+ break;
+
+ case json_tokener_state_escape_unicode_need_u:
+ /* We already had a \ char, check that it's \u */
+ if (!c || c != 'u')
+ {
+ /* Got a high surrogate with some non-unicode escape
+ * sequence following it.
+ * Put a replacement char in for the high surrogate
+ * and handle the escape sequence normally.
+ */
+ printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+ tok->high_surrogate = 0;
+ tok->ucs_char = 0;
+ tok->st_pos = 0;
+ state = json_tokener_state_string_escape;
+ goto redo_char;
+ }
+ state = json_tokener_state_escape_unicode;
+ break;
+
+ // ===================================================
+
case json_tokener_state_boolean:
{
int size1, size2;
@@ -844,9 +854,38 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
const char *case_start = str;
int case_len = 0;
int is_exponent = 0;
- int negativesign_next_possible_location = 1;
- while (c && strchr(json_number_chars, c))
+ int neg_sign_ok = 1;
+ int pos_sign_ok = 0;
+ if (printbuf_length(tok->pb) > 0)
+ {
+ /* We don't save all state from the previous incremental parse
+ so we need to re-generate it based on the saved string so far.
+ */
+ char *e_loc = strchr(tok->pb->buf, 'e');
+ if (!e_loc)
+ e_loc = strchr(tok->pb->buf, 'E');
+ if (e_loc)
+ {
+ char *last_saved_char =
+ &tok->pb->buf[printbuf_length(tok->pb) - 1];
+ is_exponent = 1;
+ pos_sign_ok = neg_sign_ok = 1;
+ /* If the "e" isn't at the end, we can't start with a '-' */
+ if (e_loc != last_saved_char)
+ {
+ neg_sign_ok = 0;
+ pos_sign_ok = 0;
+ }
+ // else leave it set to 1, i.e. start of the new input
+ }
+ }
+
+ while (c && ((c >= '0' && c <= '9') ||
+ (!is_exponent && (c == 'e' || c == 'E')) ||
+ (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
+ (!tok->is_double && c == '.')))
{
+ pos_sign_ok = neg_sign_ok = 0;
++case_len;
/* non-digit characters checks */
@@ -855,40 +894,21 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
* protected from input starting with '.' or
* e/E.
*/
- if (c == '.')
+ switch (c)
{
- if (tok->is_double != 0)
- {
- /* '.' can only be found once, and out of the exponent part.
- * Thus, if the input is already flagged as double, it
- * is invalid.
- */
- tok->err = json_tokener_error_parse_number;
- goto out;
- }
+ case '.':
tok->is_double = 1;
- }
- if (c == 'e' || c == 'E')
- {
- if (is_exponent != 0)
- {
- /* only one exponent possible */
- tok->err = json_tokener_error_parse_number;
- goto out;
- }
+ pos_sign_ok = 1;
+ neg_sign_ok = 1;
+ break;
+ case 'e': /* FALLTHRU */
+ case 'E':
is_exponent = 1;
tok->is_double = 1;
/* the exponent part can begin with a negative sign */
- negativesign_next_possible_location = case_len + 1;
- }
- if (c == '-' && case_len != negativesign_next_possible_location)
- {
- /* If the negative sign is not where expected (ie
- * start of input or start of exponent part), the
- * input is invalid.
- */
- tok->err = json_tokener_error_parse_number;
- goto out;
+ pos_sign_ok = neg_sign_ok = 1;
+ break;
+ default: break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
@@ -897,6 +917,20 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
goto out;
}
}
+ /*
+ Now we know c isn't a valid number char, but check whether
+ it might have been intended to be, and return a potentially
+ more understandable error right away.
+ However, if we're at the top-level, use the number as-is
+ because c can be part of a new object to parse on the
+ next call to json_tokener_parse().
+ */
+ if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
+ c != 'I' && c != 'i' && !isspace((unsigned char)c))
+ {
+ tok->err = json_tokener_error_parse_number;
+ goto out;
+ }
if (case_len > 0)
printbuf_memappend_fast(tok->pb, case_start, case_len);
@@ -907,6 +941,22 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
tok->st_pos = 0;
goto redo_char;
}
+ if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
+ {
+ /* Trim some chars off the end, to allow things
+ like "123e+" to parse ok. */
+ while (printbuf_length(tok->pb) > 1)
+ {
+ char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
+ if (last_char != 'e' && last_char != 'E' &&
+ last_char != '-' && last_char != '+')
+ {
+ break;
+ }
+ tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
+ printbuf_length(tok->pb)--;
+ }
+ }
}
{
int64_t num64;
@@ -943,7 +993,8 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
}
}
else if (tok->is_double &&
- json_parse_double(tok->pb->buf, &numd) == 0)
+ json_tokener_parse_double(
+ tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
{
current = json_object_new_double_s(numd, tok->pb->buf);
if (current == NULL)
@@ -964,6 +1015,9 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
case json_tokener_state_array:
if (c == ']')
{
+ // Minimize memory usage; assume parsed objs are unlikely to be changed
+ json_object_array_shrink(current, 0);
+
if (state == json_tokener_state_array_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
@@ -997,6 +1051,9 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
case json_tokener_state_array_sep:
if (c == ']')
{
+ // Minimize memory usage; assume parsed objs are unlikely to be changed
+ json_object_array_shrink(current, 0);
+
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
}
@@ -1122,8 +1179,9 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
}
break;
}
- if (!ADVANCE_CHAR(str, tok))
- goto out;
+ (void)ADVANCE_CHAR(str, tok);
+ if (!c) // This is the char *before* advancing
+ break;
} /* while(PEEK_CHAR) */
out:
@@ -1132,7 +1190,8 @@ out:
tok->err = json_tokener_error_parse_utf8_string;
}
if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
- (tok->flags & (JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS)) == JSON_TOKENER_STRICT)
+ (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
+ JSON_TOKENER_STRICT)
{
/* unexpected char after JSON data */
tok->err = json_tokener_error_parse_unexpected;
@@ -1204,3 +1263,12 @@ size_t json_tokener_get_parse_end(struct json_tokener *tok)
assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
return (size_t)tok->char_offset;
}
+
+static int json_tokener_parse_double(const char *buf, int len, double *retval)
+{
+ char *end;
+ *retval = strtod(buf, &end);
+ if (buf + len == end)
+ return 0; // It worked
+ return 1;
+}
diff --git a/json_tokener.h b/json_tokener.h
index ea49ad8..a07e12c 100644
--- a/json_tokener.h
+++ b/json_tokener.h
@@ -59,6 +59,8 @@ enum json_tokener_state
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
+ json_tokener_state_escape_unicode_need_escape,
+ json_tokener_state_escape_unicode_need_u,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
@@ -111,7 +113,7 @@ struct json_tokener
* @deprecated See json_tokener_get_error() instead.
*/
enum json_tokener_error err;
- unsigned int ucs_char;
+ unsigned int ucs_char, high_surrogate;
char quote_char;
struct json_tokener_srec *stack;
int flags;
@@ -194,11 +196,44 @@ JSON_EXPORT const char *json_tokener_error_desc(enum json_tokener_error jerr);
*/
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
+/**
+ * Allocate a new json_tokener.
+ * When done using that to parse objects, free it with json_tokener_free().
+ * See json_tokener_parse_ex() for usage details.
+ */
JSON_EXPORT struct json_tokener *json_tokener_new(void);
+
+/**
+ * Allocate a new json_tokener with a custom max nesting depth.
+ * @see JSON_TOKENER_DEFAULT_DEPTH
+ */
JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth);
+
+/**
+ * Free a json_tokener previously allocated with json_tokener_new().
+ */
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
+
+/**
+ * Reset the state of a json_tokener, to prepare to parse a
+ * brand new JSON object.
+ */
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
+
+/**
+ * Parse a json_object out of the string `str`.
+ *
+ * If you need more control over how the parsing occurs,
+ * see json_tokener_parse_ex().
+ */
JSON_EXPORT struct json_object *json_tokener_parse(const char *str);
+
+/**
+ * Parser a json_object out of the string `str`, but if it fails
+ * return the error in `*error`.
+ * @see json_tokener_parse()
+ * @see json_tokener_parse_ex()
+ */
JSON_EXPORT struct json_object *json_tokener_parse_verbose(const char *str,
enum json_tokener_error *error);
@@ -220,8 +255,8 @@ JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
*
* If json_tokener_parse_ex() returns NULL and the error is anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
- * halted. Then, the tok object must not be reused until json_tokener_reset() is
- * called.
+ * halted. Then, the tok object must not be reused until json_tokener_reset()
+ * is called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned, with a reference count of one which belongs to the caller. Also,
@@ -234,13 +269,18 @@ JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
+ * If the caller knows that they are at the end of their input, the length
+ * passed MUST include the final '\0' character, so values with no inherent
+ * end (i.e. numbers) can be properly parsed, rather than just returning
+ * json_tokener_continue.
+ *
* Extra characters can be detected by comparing the value returned by
* json_tokener_get_parse_end() against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
- * responsible for calling json_tokener_parse_ex with an appropriate str
- * parameter starting with the extra characters.
+ * responsible for a subsequent call to json_tokener_parse_ex with an
+ * appropriate str parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
@@ -256,6 +296,8 @@ enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
+ if (end_of_input)
+ stringlen++; // Include the '\0' if we know we're at the end of input
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
diff --git a/json_types.h b/json_types.h
index 67f4497..b7e55ad 100644
--- a/json_types.h
+++ b/json_types.h
@@ -18,7 +18,7 @@ extern "C" {
#endif
#ifndef JSON_EXPORT
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && defined(JSON_C_DLL)
#define JSON_EXPORT __declspec(dllexport)
#else
#define JSON_EXPORT extern
diff --git a/json_util.c b/json_util.c
index e8e2ec6..a065523 100644
--- a/json_util.c
+++ b/json_util.c
@@ -222,6 +222,7 @@ int json_object_to_file(const char *filename, struct json_object *obj)
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
}
+// Deprecated json_parse_double function. See json_tokener_parse_double instead.
int json_parse_double(const char *buf, double *retval)
{
char *end;
@@ -250,7 +251,7 @@ int json_parse_uint64(const char *buf, uint64_t *retval)
while (*buf == ' ')
buf++;
if (*buf == '-')
- return 1; /* error: uint cannot be negative */
+ return 1; /* error: uint cannot be negative */
val = strtoull(buf, &end, 10);
if (end != buf)
diff --git a/json_util.h b/json_util.h
index 7520f03..1f663e8 100644
--- a/json_util.h
+++ b/json_util.h
@@ -103,6 +103,9 @@ JSON_EXPORT const char *json_util_get_last_err(void);
/* these parsing helpers return zero on success */
JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval);
JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval);
+/**
+ * @deprecated
+ */
JSON_EXPORT int json_parse_double(const char *buf, double *retval);
/**
diff --git a/linkhash.h b/linkhash.h
index 9377723..414599d 100644
--- a/linkhash.h
+++ b/linkhash.h
@@ -311,11 +311,11 @@ int lh_table_resize(struct lh_table *t, int new_size);
/**
* @deprecated Don't use this outside of linkhash.h:
*/
-#if !defined(_MSC_VER) || (_MSC_VER > 1800)
+#if (defined(AIX_CC) || (defined(_MSC_VER) && (_MSC_VER <= 1800)) )
/* VS2010 can't handle inline funcs, so skip it there */
-#define _LH_INLINE inline
-#else
#define _LH_INLINE
+#else
+#define _LH_INLINE inline
#endif
/**
diff --git a/printbuf.h b/printbuf.h
index bfcbd2b..a0da668 100644
--- a/printbuf.h
+++ b/printbuf.h
@@ -24,7 +24,7 @@
#define _printbuf_h_
#ifndef JSON_EXPORT
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && defined(JSON_C_DLL)
#define JSON_EXPORT __declspec(dllexport)
#else
#define JSON_EXPORT extern
diff --git a/random_seed.c b/random_seed.c
index b5f8a07..f474e39 100644
--- a/random_seed.c
+++ b/random_seed.c
@@ -13,9 +13,23 @@
#include "config.h"
#include "strerror_override.h"
#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_BSD_STDLIB_H
+#include <bsd/stdlib.h>
+#endif
#define DEBUG_SEED(s)
+#if defined(__APPLE__) || defined(__unix__) || defined(__linux__)
+#define HAVE_DEV_RANDOM 1
+#endif
+
+#ifdef HAVE_ARC4RANDOM
+#undef HAVE_GETRANDOM
+#undef HAVE_DEV_RANDOM
+#undef HAVE_CRYPTGENRANDOM
+#endif
+
#if defined ENABLE_RDRAND
/* cpuid */
@@ -155,9 +169,45 @@ retry:
#endif /* defined ENABLE_RDRAND */
-/* has_dev_urandom */
+#ifdef HAVE_GETRANDOM
-#if defined(__APPLE__) || defined(__unix__) || defined(__linux__)
+#include <stdlib.h>
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
+
+static int get_getrandom_seed(int *seed)
+{
+ DEBUG_SEED("get_getrandom_seed");
+
+ ssize_t ret;
+
+ do
+ {
+ ret = getrandom(seed, sizeof(*seed), GRND_NONBLOCK);
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret == -1)
+ {
+ if (errno == ENOSYS) /* syscall not available in kernel */
+ return -1;
+ if (errno == EAGAIN) /* entropy not yet initialized */
+ return -1;
+
+ fprintf(stderr, "error from getrandom(): %s", strerror(errno));
+ return -1;
+ }
+
+ if (ret != sizeof(*seed))
+ return -1;
+
+ return 0;
+}
+#endif /* defined HAVE_GETRANDOM */
+
+/* get_dev_random_seed */
+
+#ifdef HAVE_DEV_RANDOM
#include <fcntl.h>
#include <string.h>
@@ -167,43 +217,34 @@ retry:
#include <stdlib.h>
#include <sys/stat.h>
-#define HAVE_DEV_RANDOM 1
-
static const char *dev_random_file = "/dev/urandom";
-static int has_dev_urandom(void)
+static int get_dev_random_seed(int *seed)
{
+ DEBUG_SEED("get_dev_random_seed");
+
struct stat buf;
if (stat(dev_random_file, &buf))
- {
- return 0;
- }
- return ((buf.st_mode & S_IFCHR) != 0);
-}
-
-/* get_dev_random_seed */
-
-static int get_dev_random_seed(void)
-{
- DEBUG_SEED("get_dev_random_seed");
+ return -1;
+ if ((buf.st_mode & S_IFCHR) == 0)
+ return -1;
int fd = open(dev_random_file, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
- exit(1);
+ return -1;
}
- int r;
- ssize_t nread = read(fd, &r, sizeof(r));
- if (nread != sizeof(r))
+ ssize_t nread = read(fd, seed, sizeof(*seed));
+ if (nread != sizeof(*seed))
{
fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
- exit(1);
+ return -1;
}
close(fd);
- return r;
+ return 0;
}
#endif
@@ -226,58 +267,87 @@ static int get_dev_random_seed(void)
#pragma comment(lib, "advapi32.lib")
#endif
-static int get_cryptgenrandom_seed(void)
+static int get_cryptgenrandom_seed(int *seed)
{
HCRYPTPROV hProvider = 0;
- int r;
+ DWORD dwFlags = CRYPT_VERIFYCONTEXT;
DEBUG_SEED("get_cryptgenrandom_seed");
- if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ /* WinNT 4 and Win98 do no support CRYPT_SILENT */
+ if (LOBYTE(LOWORD(GetVersion())) > 4)
+ dwFlags |= CRYPT_SILENT;
+
+ if (!CryptAcquireContextA(&hProvider, 0, 0, PROV_RSA_FULL, dwFlags))
{
- fprintf(stderr, "error CryptAcquireContextW");
- exit(1);
+ fprintf(stderr, "error CryptAcquireContextA 0x%08lx", GetLastError());
+ return -1;
}
-
- if (!CryptGenRandom(hProvider, sizeof(r), (BYTE *)&r))
+ else
{
- fprintf(stderr, "error CryptGenRandom");
- exit(1);
+ BOOL ret = CryptGenRandom(hProvider, sizeof(*seed), (BYTE *)seed);
+ CryptReleaseContext(hProvider, 0);
+ if (!ret)
+ {
+ fprintf(stderr, "error CryptGenRandom 0x%08lx", GetLastError());
+ return -1;
+ }
}
- CryptReleaseContext(hProvider, 0);
-
- return r;
+ return 0;
}
#endif
/* get_time_seed */
+#ifndef HAVE_ARC4RANDOM
#include <time.h>
static int get_time_seed(void)
{
DEBUG_SEED("get_time_seed");
- return (int)time(NULL) * 433494437;
+ return (unsigned)time(NULL) * 433494437;
}
+#endif
/* json_c_get_random_seed */
int json_c_get_random_seed(void)
{
+#ifdef OVERRIDE_GET_RANDOM_SEED
+ OVERRIDE_GET_RANDOM_SEED;
+#endif
#if defined HAVE_RDRAND && HAVE_RDRAND
if (has_rdrand())
return get_rdrand_seed();
#endif
+#ifdef HAVE_ARC4RANDOM
+ /* arc4random never fails, so use it if it's available */
+ return arc4random();
+#else
+#ifdef HAVE_GETRANDOM
+ {
+ int seed;
+ if (get_getrandom_seed(&seed) == 0)
+ return seed;
+ }
+#endif
#if defined HAVE_DEV_RANDOM && HAVE_DEV_RANDOM
- if (has_dev_urandom())
- return get_dev_random_seed();
+ {
+ int seed;
+ if (get_dev_random_seed(&seed) == 0)
+ return seed;
+ }
#endif
#if defined HAVE_CRYPTGENRANDOM && HAVE_CRYPTGENRANDOM
- return get_cryptgenrandom_seed();
+ {
+ int seed;
+ if (get_cryptgenrandom_seed(&seed) == 0)
+ return seed;
+ }
#endif
return get_time_seed();
+#endif /* !HAVE_ARC4RANDOM */
}
diff --git a/strerror_override.c b/strerror_override.c
index a93be38..a3dd377 100644
--- a/strerror_override.c
+++ b/strerror_override.c
@@ -59,7 +59,8 @@ static struct
/* clang-format on */
// Enabled during tests
-int _json_c_strerror_enable = 0;
+static int _json_c_strerror_enable = 0;
+extern char *getenv(const char *name); // Avoid including stdlib.h
#define PREFIX "ERRNO="
static char errno_buf[128] = PREFIX;
@@ -70,6 +71,8 @@ char *_json_c_strerror(int errno_in)
int ii, jj;
if (!_json_c_strerror_enable)
+ _json_c_strerror_enable = (getenv("_JSON_C_STRERROR_ENABLE") == NULL) ? -1 : 1;
+ if (_json_c_strerror_enable == -1)
return strerror(errno_in);
// Avoid standard functions, so we don't need to include any
@@ -91,7 +94,7 @@ char *_json_c_strerror(int errno_in)
}
// It's not one of the known errno values, return the numeric value.
- for (ii = 0; errno_in > 10; errno_in /= 10, ii++)
+ for (ii = 0; errno_in >= 10; errno_in /= 10, ii++)
{
digbuf[ii] = "0123456789"[(errno_in % 10)];
}
@@ -102,5 +105,6 @@ char *_json_c_strerror(int errno_in)
{
errno_buf[start_idx] = digbuf[ii];
}
+ errno_buf[start_idx] = '\0';
return errno_buf;
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a871573..d7abf51 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -12,31 +12,41 @@ target_link_libraries(test2Formatted PRIVATE ${PROJECT_NAME})
include_directories(PUBLIC ${CMAKE_SOURCE_DIR})
-foreach(TESTNAME
- test1
- test2
- test4
- testReplaceExisting
- test_cast
- test_charcase
- test_compare
- test_deep_copy
- test_double_serializer
- test_float
- test_int_add
- test_json_pointer
- test_locale
- test_null
- test_parse
- test_parse_int64
- test_printbuf
- test_set_serializer
- test_set_value
- test_util_file
- test_visit
- test_object_iterator)
+set(ALL_TEST_NAMES
+ test1
+ test2
+ test4
+ testReplaceExisting
+ test_cast
+ test_charcase
+ test_compare
+ test_deep_copy
+ test_double_serializer
+ test_float
+ test_int_add
+ test_locale
+ test_null
+ test_parse
+ test_parse_int64
+ test_printbuf
+ test_set_serializer
+ test_set_value
+ test_strerror
+ test_util_file
+ test_visit
+ test_object_iterator)
+
+if (NOT DISABLE_JSON_POINTER)
+ set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_json_pointer)
+endif()
+
+foreach(TESTNAME ${ALL_TEST_NAMES})
add_executable(${TESTNAME} ${TESTNAME}.c)
+if(${TESTNAME} STREQUAL test_strerror OR ${TESTNAME} STREQUAL test_util_file)
+# For output consistency, we need _json_c_strerror() in some tests:
+target_sources(${TESTNAME} PRIVATE ../strerror_override.c)
+endif()
add_test(NAME ${TESTNAME} COMMAND ${PROJECT_SOURCE_DIR}/tests/${TESTNAME}.test)
# XXX using the non-target_ versions of these doesn't work :(
diff --git a/tests/test1.c b/tests/test1.c
index 98546bf..4d29601 100644
--- a/tests/test1.c
+++ b/tests/test1.c
@@ -1,9 +1,12 @@
#include <assert.h>
+#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "config.h"
+
#include "json.h"
#include "parse_flags.h"
@@ -250,7 +253,7 @@ int main(int argc, char **argv)
test_array_del_idx();
test_array_list_expand_internal();
- my_array = json_object_new_array();
+ my_array = json_object_new_array_ext(5);
json_object_array_add(my_array, json_object_new_int(3));
json_object_array_add(my_array, json_object_new_int(1));
json_object_array_add(my_array, json_object_new_int(2));
@@ -307,6 +310,27 @@ int main(int argc, char **argv)
}
printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object));
+ json_object_put(my_array);
+ my_array = json_object_new_array_ext(INT_MIN + 1);
+ if (my_array != NULL)
+ {
+ printf("ERROR: able to allocate an array of negative size!\n");
+ fflush(stdout);
+ json_object_put(my_array);
+ my_array = NULL;
+ }
+
+#if SIZEOF_SIZE_T == SIZEOF_INT
+ my_array = json_object_new_array_ext(INT_MAX / 2 + 2);
+ if (my_array != NULL)
+ {
+ printf("ERROR: able to allocate an array of insufficient size!\n");
+ fflush(stdout);
+ json_object_put(my_array);
+ my_array = NULL;
+ }
+#endif
+
json_object_put(my_string);
json_object_put(my_int);
json_object_put(my_null);
diff --git a/tests/test_basic.test b/tests/test_basic.test
index 154e036..474e7a8 100755
--- a/tests/test_basic.test
+++ b/tests/test_basic.test
@@ -1,5 +1,7 @@
#!/bin/sh
+export _JSON_C_STRERROR_ENABLE=1
+
# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
diff --git a/tests/test_cast.c b/tests/test_cast.c
index fb63e0d..fc769f5 100644
--- a/tests/test_cast.c
+++ b/tests/test_cast.c
@@ -28,6 +28,11 @@ int main(int argc, char **argv)
\"int64_number\": 2147483649,\n\
\"negative_number\": -321321321,\n\
\"a_null\": null,\n\
+ \"empty_array\": [],\n\
+ \"nonempty_array\": [ 123 ],\n\
+ \"array_with_zero\": [ 0 ],\n\
+ \"empty_object\": {},\n\
+ \"nonempty_object\": { \"a\": 123 },\n\
}";
/* Note: 2147483649 = INT_MAX + 2 */
/* Note: 9223372036854775809 = INT64_MAX + 2 */
@@ -49,6 +54,11 @@ int main(int argc, char **argv)
getit(new_obj, "int64_number");
getit(new_obj, "negative_number");
getit(new_obj, "a_null");
+ getit(new_obj, "empty_array");
+ getit(new_obj, "nonempty_array");
+ getit(new_obj, "array_with_zero");
+ getit(new_obj, "empty_object");
+ getit(new_obj, "nonempty_object");
// Now check the behaviour of the json_object_is_type() function.
printf("\n================================\n");
diff --git a/tests/test_cast.expected b/tests/test_cast.expected
index 347d540..6a19de9 100644
--- a/tests/test_cast.expected
+++ b/tests/test_cast.expected
@@ -7,6 +7,11 @@ Parsed input: {
"int64_number": 2147483649,
"negative_number": -321321321,
"a_null": null,
+ "empty_array": [],
+ "nonempty_array": [ 123 ],
+ "array_with_zero": [ 0 ],
+ "empty_object": {},
+ "nonempty_object": { "a": 123 },
}
Result is not NULL
new_obj.string_of_digits json_object_get_type()=string
@@ -57,6 +62,36 @@ new_obj.a_null json_object_get_int64()=0
new_obj.a_null json_object_get_uint64()=0
new_obj.a_null json_object_get_boolean()=0
new_obj.a_null json_object_get_double()=0.000000
+new_obj.empty_array json_object_get_type()=array
+new_obj.empty_array json_object_get_int()=0
+new_obj.empty_array json_object_get_int64()=0
+new_obj.empty_array json_object_get_uint64()=0
+new_obj.empty_array json_object_get_boolean()=0
+new_obj.empty_array json_object_get_double()=0.000000
+new_obj.nonempty_array json_object_get_type()=array
+new_obj.nonempty_array json_object_get_int()=0
+new_obj.nonempty_array json_object_get_int64()=0
+new_obj.nonempty_array json_object_get_uint64()=0
+new_obj.nonempty_array json_object_get_boolean()=0
+new_obj.nonempty_array json_object_get_double()=0.000000
+new_obj.array_with_zero json_object_get_type()=array
+new_obj.array_with_zero json_object_get_int()=0
+new_obj.array_with_zero json_object_get_int64()=0
+new_obj.array_with_zero json_object_get_uint64()=0
+new_obj.array_with_zero json_object_get_boolean()=0
+new_obj.array_with_zero json_object_get_double()=0.000000
+new_obj.empty_object json_object_get_type()=object
+new_obj.empty_object json_object_get_int()=0
+new_obj.empty_object json_object_get_int64()=0
+new_obj.empty_object json_object_get_uint64()=0
+new_obj.empty_object json_object_get_boolean()=0
+new_obj.empty_object json_object_get_double()=0.000000
+new_obj.nonempty_object json_object_get_type()=object
+new_obj.nonempty_object json_object_get_int()=0
+new_obj.nonempty_object json_object_get_int64()=0
+new_obj.nonempty_object json_object_get_uint64()=0
+new_obj.nonempty_object json_object_get_boolean()=0
+new_obj.nonempty_object json_object_get_double()=0.000000
================================
json_object_is_type: null,boolean,double,int,object,array,string
diff --git a/tests/test_deep_copy.c b/tests/test_deep_copy.c
index b6c1b99..34ef1fe 100644
--- a/tests/test_deep_copy.c
+++ b/tests/test_deep_copy.c
@@ -126,7 +126,7 @@ int main(int argc, char **argv)
src3 = json_tokener_parse(json_str3);
assert(src1 != NULL);
- assert(src1 != NULL);
+ assert(src2 != NULL);
assert(src3 != NULL);
printf("PASSED - loaded input data\n");
diff --git a/tests/test_double_serializer.c b/tests/test_double_serializer.c
index 71ec8ec..8b2487a 100644
--- a/tests/test_double_serializer.c
+++ b/tests/test_double_serializer.c
@@ -59,6 +59,7 @@ int main()
#else
// Just fake it up, so the output matches.
printf("obj.to_string(with thread format)=%s\n", "T0.52X");
+ printf("obj.to_string(long thread format)=%s\n", "Ttttttttttttt0.52xxxxxxxxxxxxxxxxxxX");
printf("obj.to_string(back to global format)=%s\n", "x0.524y");
#endif
if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_GLOBAL) < 0)
diff --git a/tests/test_json_pointer.c b/tests/test_json_pointer.c
index 34fa202..3174c87 100644
--- a/tests/test_json_pointer.c
+++ b/tests/test_json_pointer.c
@@ -1,9 +1,8 @@
-#include "strerror_override.h"
-#include "strerror_override_private.h"
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <assert.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -320,8 +319,6 @@ static void test_wrong_inputs_set(void)
int main(int argc, char **argv)
{
- _json_c_strerror_enable = 1;
-
test_example_get();
test_recursion_get();
test_wrong_inputs_get();
diff --git a/tests/test_parse.c b/tests/test_parse.c
index 6014ac1..5363f32 100644
--- a/tests/test_parse.c
+++ b/tests/test_parse.c
@@ -33,6 +33,52 @@ int main(void)
static json_c_visit_userfunc clear_serializer;
static void do_clear_serializer(json_object *jso);
+static void single_incremental_parse(const char *test_string, int clear_serializer)
+{
+ int ii;
+ int chunksize = atoi(getenv("TEST_PARSE_CHUNKSIZE"));
+ struct json_tokener *tok;
+ enum json_tokener_error jerr;
+ json_object *all_at_once_obj, *new_obj;
+ const char *all_at_once_str, *new_str;
+
+ assert(chunksize > 0);
+ all_at_once_obj = json_tokener_parse(test_string);
+ if (clear_serializer)
+ do_clear_serializer(all_at_once_obj);
+ all_at_once_str = json_object_to_json_string(all_at_once_obj);
+
+ tok = json_tokener_new();
+ int test_string_len = strlen(test_string) + 1; // Including '\0' !
+ for (ii = 0; ii < test_string_len; ii += chunksize)
+ {
+ int len_to_parse = chunksize;
+ if (ii + chunksize > test_string_len)
+ len_to_parse = test_string_len - ii;
+
+ if (getenv("TEST_PARSE_DEBUG") != NULL)
+ printf(" chunk: %.*s\n", len_to_parse, &test_string[ii]);
+ new_obj = json_tokener_parse_ex(tok, &test_string[ii], len_to_parse);
+ jerr = json_tokener_get_error(tok);
+ if (jerr != json_tokener_continue || new_obj)
+ break;
+ }
+ if (clear_serializer && new_obj)
+ do_clear_serializer(new_obj);
+ new_str = json_object_to_json_string(new_obj);
+
+ if (strcmp(all_at_once_str, new_str) != 0)
+ {
+ printf("ERROR: failed to parse (%s) in %d byte chunks: %s != %s\n", test_string,
+ chunksize, all_at_once_str, new_str);
+ }
+ json_tokener_free(tok);
+ if (all_at_once_obj)
+ json_object_put(all_at_once_obj);
+ if (new_obj)
+ json_object_put(new_obj);
+}
+
static void single_basic_parse(const char *test_string, int clear_serializer)
{
json_object *new_obj;
@@ -42,6 +88,9 @@ static void single_basic_parse(const char *test_string, int clear_serializer)
do_clear_serializer(new_obj);
printf("new_obj.to_string(%s)=%s\n", test_string, json_object_to_json_string(new_obj));
json_object_put(new_obj);
+
+ if (getenv("TEST_PARSE_CHUNKSIZE") != NULL)
+ single_incremental_parse(test_string, clear_serializer);
}
static void test_basic_parse()
{
@@ -93,16 +142,18 @@ static void test_basic_parse()
single_basic_parse("12", 0);
single_basic_parse("12.3", 0);
- single_basic_parse("12.3.4", 0); /* non-sensical, returns null */
- /* was returning (int)2015 before patch, should return null */
- single_basic_parse("2015-01-15", 0);
- /* ...but this works. It's rather inconsistent, and a future major release
- * should change the behavior so it either always returns null when extra
- * bytes are present (preferred), or always return object created from as much
- * as was able to be parsed.
+ /* Even though, when using json_tokener_parse() there's no way to
+ * know when there is more data after the parsed object,
+ * an object is successfully returned anyway (in some cases)
*/
+
+ single_basic_parse("12.3.4", 0);
+ single_basic_parse("2015-01-15", 0);
single_basic_parse("12.3xxx", 0);
+ single_basic_parse("12.3{\"a\":123}", 0);
+ single_basic_parse("12.3\n", 0);
+ single_basic_parse("12.3 ", 0);
single_basic_parse("{\"FoO\" : -12.3E512}", 0);
single_basic_parse("{\"FoO\" : -12.3e512}", 0);
@@ -149,8 +200,8 @@ static void test_utf8_parse()
// json_tokener_parse doesn't support checking for byte order marks.
// It's the responsibility of the caller to detect and skip a BOM.
// Both of these checks return null.
- char* utf8_bom = "\xEF\xBB\xBF";
- char* utf8_bom_and_chars = "\xEF\xBB\xBF{}";
+ char *utf8_bom = "\xEF\xBB\xBF";
+ char *utf8_bom_and_chars = "\xEF\xBB\xBF{}";
single_basic_parse(utf8_bom, 0);
single_basic_parse(utf8_bom_and_chars, 0);
}
@@ -201,7 +252,7 @@ struct incremental_step
int char_offset;
enum json_tokener_error expected_error;
int reset_tokener; /* Set to 1 to call json_tokener_reset() after parsing */
- int tok_flags; /* JSON_TOKENER_* flags to pass to json_tokener_set_flags() */
+ int tok_flags; /* JSON_TOKENER_* flags to pass to json_tokener_set_flags() */
} incremental_steps[] = {
/* Check that full json messages can be parsed, both w/ and w/o a reset */
@@ -224,6 +275,49 @@ struct incremental_step
{"\": {\"bar", -1, -1, json_tokener_continue, 0},
{"\":13}}", -1, -1, json_tokener_success, 1},
+ /* Check the UTF-16 surrogate pair handling in various ways.
+ * Note: \ud843\udd1e is u+1D11E, Musical Symbol G Clef
+ * Your terminal may not display these correctly, in particular
+ * PuTTY doesn't currently show this character.
+ */
+ /* parse one char at every time */
+ {"\"\\", -1, -1, json_tokener_continue, 0},
+ {"u", -1, -1, json_tokener_continue, 0},
+ {"d", -1, -1, json_tokener_continue, 0},
+ {"8", -1, -1, json_tokener_continue, 0},
+ {"3", -1, -1, json_tokener_continue, 0},
+ {"4", -1, -1, json_tokener_continue, 0},
+ {"\\", -1, -1, json_tokener_continue, 0},
+ {"u", -1, -1, json_tokener_continue, 0},
+ {"d", -1, -1, json_tokener_continue, 0},
+ {"d", -1, -1, json_tokener_continue, 0},
+ {"1", -1, -1, json_tokener_continue, 0},
+ {"e\"", -1, -1, json_tokener_success, 1},
+ /* parse two char at every time */
+ {"\"\\u", -1, -1, json_tokener_continue, 0},
+ {"d8", -1, -1, json_tokener_continue, 0},
+ {"34", -1, -1, json_tokener_continue, 0},
+ {"\\u", -1, -1, json_tokener_continue, 0},
+ {"dd", -1, -1, json_tokener_continue, 0},
+ {"1e\"", -1, -1, json_tokener_success, 1},
+ /* check the low surrogate pair */
+ {"\"\\ud834", -1, -1, json_tokener_continue, 0},
+ {"\\udd1e\"", -1, -1, json_tokener_success, 1},
+ {"\"\\ud834\\", -1, -1, json_tokener_continue, 0},
+ {"udd1e\"", -1, -1, json_tokener_success, 1},
+ {"\"\\ud834\\u", -1, -1, json_tokener_continue, 0},
+ {"dd1e\"", -1, -1, json_tokener_success, 1},
+ {"\"fff \\ud834\\ud", -1, -1, json_tokener_continue, 0},
+ {"d1e bar\"", -1, -1, json_tokener_success, 1},
+ {"\"fff \\ud834\\udd", -1, -1, json_tokener_continue, 0},
+ {"1e bar\"", -1, -1, json_tokener_success, 1},
+
+ /* \ud83d\ude00 is U+1F600, Grinning Face
+ * Displays fine in PuTTY, though you may need "less -r"
+ */
+ {"\"fff \\ud83d\\ude", -1, -1, json_tokener_continue, 0},
+ {"00 bar\"", -1, -1, json_tokener_success, 1},
+
/* Check that json_tokener_reset actually resets */
{"{ \"foo", -1, -1, json_tokener_continue, 1},
{": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1},
@@ -239,19 +333,49 @@ struct incremental_step
{"\"Y\"", -1, -1, json_tokener_success, 1},
/* Trailing characters should cause a failure in strict mode */
- {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
+ {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
/* ... unless explicitly allowed. */
- {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_success, 0, JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS },
- {"{\"b\":8}ignored garbage", -1, 7, json_tokener_success, 1, JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS },
+ {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_success, 0,
+ JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS},
+ {"{\"b\":8}ignored garbage", -1, 7, json_tokener_success, 1,
+ JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS},
/* To stop parsing a number we need to reach a non-digit, e.g. a \0 */
{"1", 1, 1, json_tokener_continue, 0},
/* This should parse as the number 12, since it continues the "1" */
{"2", 2, 1, json_tokener_success, 0},
{"12{", 3, 2, json_tokener_success, 1},
- /* Parse number in strict model */
- {"[02]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT },
+ /* Parse number in strict mode */
+ {"[02]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
+
+ {"0e+0", 5, 4, json_tokener_success, 1},
+ {"[0e+0]", -1, -1, json_tokener_success, 1},
+
+ /* The behavior when missing the exponent varies slightly */
+ {"0e", 2, 2, json_tokener_continue, 1},
+ {"0e", 3, 2, json_tokener_success, 1},
+ {"0e", 3, 2, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT},
+ {"[0e]", -1, -1, json_tokener_success, 1},
+ {"[0e]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
+
+ {"0e+", 3, 3, json_tokener_continue, 1},
+ {"0e+", 4, 3, json_tokener_success, 1},
+ {"0e+", 4, 3, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT},
+ {"[0e+]", -1, -1, json_tokener_success, 1},
+ {"[0e+]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
+
+ {"0e-", 3, 3, json_tokener_continue, 1},
+ {"0e-", 4, 3, json_tokener_success, 1},
+ {"0e-", 4, 3, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT},
+ {"[0e-]", -1, -1, json_tokener_success, 1},
+ {"[0e-]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
+
+ /* You might expect this to fail, but it won't because
+ it's a valid partial parse; note the char_offset: */
+ {"0e+-", 5, 3, json_tokener_success, 1},
+ {"0e+-", 5, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
+ {"[0e+-]", -1, 4, json_tokener_error_parse_number, 1},
/* Similar tests for other kinds of objects: */
/* These could all return success immediately, since regardless of
@@ -267,8 +391,8 @@ struct incremental_step
{"Infinity", 9, 8, json_tokener_success, 1},
{"infinity", 9, 8, json_tokener_success, 1},
{"-infinity", 10, 9, json_tokener_success, 1},
- {"infinity", 9, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
- {"-infinity", 10, 1, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
+ {"infinity", 9, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
+ {"-infinity", 10, 1, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
{"inf", 3, 3, json_tokener_continue, 0},
{"inity", 6, 5, json_tokener_success, 1},
@@ -322,15 +446,29 @@ struct incremental_step
* the next few tests check that parsing multiple sequential
* json objects in the input works as expected
*/
- {"null123", 9, 4, json_tokener_success, 0},
+ {"null123", 8, 4, json_tokener_success, 0},
{&"null123"[4], 4, 3, json_tokener_success, 1},
- {"nullx", 5, 4, json_tokener_success, 0},
+ {"nullx", 6, 4, json_tokener_success, 0},
{&"nullx"[4], 2, 0, json_tokener_error_parse_unexpected, 1},
{"{\"a\":1}{\"b\":2}", 15, 7, json_tokener_success, 0},
{&"{\"a\":1}{\"b\":2}"[7], 8, 7, json_tokener_success, 1},
- /* Some bad formatting. Check we get the correct error status */
- {"2015-01-15", 10, 4, json_tokener_error_parse_number, 1},
+ /*
+ * Though this may seem invalid at first glance, it
+ * parses as three separate numbers, 2015, -1 and -15
+ * Of course, simply pasting together a stream of arbitrary
+ * positive numbers won't work, since there'll be no way to
+ * tell where in e.g. "2015015" the next number stats, so
+ * a reliably parsable stream must not include json_type_int
+ * or json_type_double objects without some other delimiter.
+ * e.g. whitespace
+ */
+ {&"2015-01-15"[0], 11, 4, json_tokener_success, 1},
+ {&"2015-01-15"[4], 7, 3, json_tokener_success, 1},
+ {&"2015-01-15"[7], 4, 3, json_tokener_success, 1},
+ {&"2015 01 15"[0], 11, 5, json_tokener_success, 1},
+ {&"2015 01 15"[4], 7, 4, json_tokener_success, 1},
+ {&"2015 01 15"[7], 4, 3, json_tokener_success, 1},
/* Strings have a well defined end point, so we can stop at the quote */
{"\"blue\"", -1, -1, json_tokener_success, 0},
@@ -350,7 +488,7 @@ struct incremental_step
{"\"\\a\"", -1, 2, json_tokener_error_parse_string, 1},
/* Check '\'' in strict model */
- {"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
+ {"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
/* Parse array/object */
{"[1,2,3]", -1, -1, json_tokener_success, 0},
@@ -372,42 +510,54 @@ struct incremental_step
{"[1,2,3,]", -1, -1, json_tokener_success, 0},
{"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0},
- {"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
- {"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT },
+ {"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
+ {"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
// utf-8 test
// acsll encoding
- {"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1},
// utf-8 encoding
- {"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x22\xe4\xb8", -1, 3, json_tokener_error_parse_utf8_string, 0, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x96\xe7\x95\x8c\x22", -1, 0, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
+ {"\x22\xe4\xb8", -1, 3, json_tokener_error_parse_utf8_string, 0, JSON_TOKENER_VALIDATE_UTF8},
+ {"\x96\xe7\x95\x8c\x22", -1, 0, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1},
- {"\x22\xcf\x80\xcf\x86\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x22\xf0\xa5\x91\x95\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\xcf\x80\xcf\x86\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8},
+ {"\x22\xf0\xa5\x91\x95\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8},
// wrong utf-8 encoding
- {"\x22\xe6\x9d\x4e\x22", -1, 3, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\xe6\x9d\x4e\x22", -1, 3, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{"\x22\xe6\x9d\x4e\x22", -1, 5, json_tokener_success, 1},
// GBK encoding
- {"\x22\xc0\xee\xc5\xf4\x22", -1, 2, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\xc0\xee\xc5\xf4\x22", -1, 2, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{"\x22\xc0\xee\xc5\xf4\x22", -1, 6, json_tokener_success, 1},
// char after space
- {"\x20\x20\x22\xe4\xb8\x96\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x20\x20\x81\x22\xe4\xb8\x96\x22", -1, 2, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x5b\x20\x81\x31\x5d", -1, 2, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x20\x20\x22\xe4\xb8\x96\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8},
+ {"\x20\x20\x81\x22\xe4\xb8\x96\x22", -1, 2, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
+ {"\x5b\x20\x81\x31\x5d", -1, 2, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
// char in state inf
{"\x49\x6e\x66\x69\x6e\x69\x74\x79", 9, 8, json_tokener_success, 1},
- {"\x49\x6e\x66\x81\x6e\x69\x74\x79", -1, 3, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x49\x6e\x66\x81\x6e\x69\x74\x79", -1, 3, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
// char in escape unicode
- {"\x22\x5c\x75\x64\x38\x35\x35\x5c\x75\x64\x63\x35\x35\x22", 15, 14, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x22\x5c\x75\x64\x38\x35\x35\x5c\x75\x64\x63\x35\x35\x22", 15, 14, json_tokener_success, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{"\x22\x5c\x75\x64\x38\x35\x35\xc0\x75\x64\x63\x35\x35\x22", -1, 8,
- json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
- {"\x22\x5c\x75\x64\x30\x30\x33\x31\xc0\x22", -1, 9, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8},
+ {"\x22\x5c\x75\x64\x30\x30\x33\x31\xc0\x22", -1, 9, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
// char in number
- {"\x31\x31\x81\x31\x31", -1, 2, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x31\x31\x81\x31\x31", -1, 2, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
// char in object
- {"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8 },
+ {"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 1,
+ JSON_TOKENER_VALIDATE_UTF8},
{NULL, -1, -1, json_tokener_success, 0},
};
diff --git a/tests/test_parse.expected b/tests/test_parse.expected
index 77e8be1..37db44d 100644
--- a/tests/test_parse.expected
+++ b/tests/test_parse.expected
@@ -40,9 +40,13 @@ new_obj.to_string(nAn)=NaN
new_obj.to_string(iNfinity)=Infinity
new_obj.to_string(12)=12
new_obj.to_string(12.3)=12.3
-new_obj.to_string(12.3.4)=null
-new_obj.to_string(2015-01-15)=null
+new_obj.to_string(12.3.4)=12.3
+new_obj.to_string(2015-01-15)=2015
new_obj.to_string(12.3xxx)=12.3
+new_obj.to_string(12.3{"a":123})=12.3
+new_obj.to_string(12.3
+)=12.3
+new_obj.to_string(12.3 )=12.3
new_obj.to_string({"FoO" : -12.3E512})={ "FoO": -12.3E512 }
new_obj.to_string({"FoO" : -12.3e512})={ "FoO": -12.3e512 }
new_obj.to_string({"FoO" : -12.3E51.2})=null
@@ -100,6 +104,36 @@ json_tokener_parse_ex(tok, // hello"foo", 13) ... OK: got correct error: contin
json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue
json_tokener_parse_ex(tok, ":13}} , 6) ... OK: got object of type [object]: { "foo": { "bar": 13 } }
+json_tokener_parse_ex(tok, "\ , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, u , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, d , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 8 , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 3 , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 4 , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, \ , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, u , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, d , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, d , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, e" , 2) ... OK: got object of type [string]: "ð„ž"
+json_tokener_parse_ex(tok, "\u , 3) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, d8 , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 34 , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, \u , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, dd , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 1e" , 3) ... OK: got object of type [string]: "ð„ž"
+json_tokener_parse_ex(tok, "\ud834 , 7) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, \udd1e" , 7) ... OK: got object of type [string]: "ð„ž"
+json_tokener_parse_ex(tok, "\ud834\ , 8) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, udd1e" , 6) ... OK: got object of type [string]: "ð„ž"
+json_tokener_parse_ex(tok, "\ud834\u , 9) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, dd1e" , 5) ... OK: got object of type [string]: "ð„ž"
+json_tokener_parse_ex(tok, "fff \ud834\ud, 14) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, d1e bar" , 8) ... OK: got object of type [string]: "fff ð„ž bar"
+json_tokener_parse_ex(tok, "fff \ud834\udd, 15) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 1e bar" , 7) ... OK: got object of type [string]: "fff ð„ž bar"
+json_tokener_parse_ex(tok, "fff \ud83d\ude, 15) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 00 bar" , 7) ... OK: got object of type [string]: "fff 😀 bar"
json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
@@ -115,6 +149,26 @@ json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continu
json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12
json_tokener_parse_ex(tok, 12{ , 3) ... OK: got object of type [int]: 12
json_tokener_parse_ex(tok, [02] , 4) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, 0e+0 , 5) ... OK: got object of type [double]: 0e+0
+json_tokener_parse_ex(tok, [0e+0] , 6) ... OK: got object of type [array]: [ 0e+0 ]
+json_tokener_parse_ex(tok, 0e , 2) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 0e , 3) ... OK: got object of type [double]: 0
+json_tokener_parse_ex(tok, 0e , 3) ... OK: got correct error: unexpected end of data
+json_tokener_parse_ex(tok, [0e] , 4) ... OK: got object of type [array]: [ 0 ]
+json_tokener_parse_ex(tok, [0e] , 4) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, 0e+ , 3) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 0e+ , 4) ... OK: got object of type [double]: 0
+json_tokener_parse_ex(tok, 0e+ , 4) ... OK: got correct error: unexpected end of data
+json_tokener_parse_ex(tok, [0e+] , 5) ... OK: got object of type [array]: [ 0 ]
+json_tokener_parse_ex(tok, [0e+] , 5) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, 0e- , 3) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 0e- , 4) ... OK: got object of type [double]: 0
+json_tokener_parse_ex(tok, 0e- , 4) ... OK: got correct error: unexpected end of data
+json_tokener_parse_ex(tok, [0e-] , 5) ... OK: got object of type [array]: [ 0 ]
+json_tokener_parse_ex(tok, [0e-] , 5) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, 0e+- , 5) ... OK: got object of type [double]: 0
+json_tokener_parse_ex(tok, 0e+- , 5) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, [0e+-] , 6) ... OK: got correct error: number expected
json_tokener_parse_ex(tok, false , 5) ... OK: got correct error: continue
json_tokener_parse_ex(tok, false , 6) ... OK: got object of type [boolean]: false
json_tokener_parse_ex(tok, true , 4) ... OK: got correct error: continue
@@ -160,13 +214,18 @@ json_tokener_parse_ex(tok, noodle , 7) ... OK: got correct error: null ex
json_tokener_parse_ex(tok, naodle , 7) ... OK: got correct error: null expected
json_tokener_parse_ex(tok, track , 6) ... OK: got correct error: boolean expected
json_tokener_parse_ex(tok, fail , 5) ... OK: got correct error: boolean expected
-json_tokener_parse_ex(tok, null123 , 9) ... OK: got object of type [null]: null
+json_tokener_parse_ex(tok, null123 , 8) ... OK: got object of type [null]: null
json_tokener_parse_ex(tok, 123 , 4) ... OK: got object of type [int]: 123
-json_tokener_parse_ex(tok, nullx , 5) ... OK: got object of type [null]: null
+json_tokener_parse_ex(tok, nullx , 6) ... OK: got object of type [null]: null
json_tokener_parse_ex(tok, x , 2) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, {"a":1}{"b":2}, 15) ... OK: got object of type [object]: { "a": 1 }
json_tokener_parse_ex(tok, {"b":2} , 8) ... OK: got object of type [object]: { "b": 2 }
-json_tokener_parse_ex(tok, 2015-01-15 , 10) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, 2015-01-15 , 11) ... OK: got object of type [int]: 2015
+json_tokener_parse_ex(tok, -01-15 , 7) ... OK: got object of type [int]: -1
+json_tokener_parse_ex(tok, -15 , 4) ... OK: got object of type [int]: -15
+json_tokener_parse_ex(tok, 2015 01 15 , 11) ... OK: got object of type [int]: 2015
+json_tokener_parse_ex(tok, 01 15 , 7) ... OK: got object of type [int]: 1
+json_tokener_parse_ex(tok, 15 , 4) ... OK: got object of type [int]: 15
json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue"
json_tokener_parse_ex(tok, "\"" , 4) ... OK: got object of type [string]: "\""
json_tokener_parse_ex(tok, "\\" , 4) ... OK: got object of type [string]: "\\"
@@ -216,5 +275,5 @@ json_tokener_parse_ex(tok, "\ud855Àudc55", 14) ... OK: got correct error: inval
json_tokener_parse_ex(tok, "\ud0031À" , 10) ... OK: got correct error: invalid utf-8 string
json_tokener_parse_ex(tok, 1111 , 5) ... OK: got correct error: invalid utf-8 string
json_tokener_parse_ex(tok, {"1":1} , 8) ... OK: got correct error: invalid utf-8 string
-End Incremental Tests OK=130 ERROR=0
+End Incremental Tests OK=185 ERROR=0
==================================
diff --git a/tests/test_set_value.c b/tests/test_set_value.c
index d6f1a33..157e64f 100644
--- a/tests/test_set_value.c
+++ b/tests/test_set_value.c
@@ -56,14 +56,18 @@ int main(int argc, char **argv)
#define MID "A MID STRING"
// 12345678901234567890123456789012....
#define HUGE "A string longer than 32 chars as to check non local buf codepath"
- tmp = json_object_new_string(SHORT);
- assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
- json_object_set_string(tmp, MID);
+ tmp = json_object_new_string(MID);
assert(strcmp(json_object_get_string(tmp), MID) == 0);
+ assert(strcmp(json_object_to_json_string(tmp), "\"" MID "\"") == 0);
+ json_object_set_string(tmp, SHORT);
+ assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
+ assert(strcmp(json_object_to_json_string(tmp), "\"" SHORT "\"") == 0);
json_object_set_string(tmp, HUGE);
assert(strcmp(json_object_get_string(tmp), HUGE) == 0);
+ assert(strcmp(json_object_to_json_string(tmp), "\"" HUGE "\"") == 0);
json_object_set_string(tmp, SHORT);
assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
+ assert(strcmp(json_object_to_json_string(tmp), "\"" SHORT "\"") == 0);
json_object_put(tmp);
printf("STRING PASSED\n");
diff --git a/tests/test_strerror.c b/tests/test_strerror.c
new file mode 100644
index 0000000..1780564
--- /dev/null
+++ b/tests/test_strerror.c
@@ -0,0 +1,11 @@
+#include "strerror_override.h"
+#include "strerror_override_private.h"
+
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ puts(strerror(10000));
+ puts(strerror(999));
+ return 0;
+}
diff --git a/tests/test_strerror.expected b/tests/test_strerror.expected
new file mode 100644
index 0000000..b6b3bb6
--- /dev/null
+++ b/tests/test_strerror.expected
@@ -0,0 +1,2 @@
+ERRNO=10000
+ERRNO=999
diff --git a/tests/test_strerror.test b/tests/test_strerror.test
new file mode 120000
index 0000000..58a13f4
--- /dev/null
+++ b/tests/test_strerror.test
@@ -0,0 +1 @@
+test_basic.test \ No newline at end of file
diff --git a/tests/test_util_file.c b/tests/test_util_file.c
index 9d50663..9150586 100644
--- a/tests/test_util_file.c
+++ b/tests/test_util_file.c
@@ -127,8 +127,6 @@ int main(int argc, char **argv)
// json_object_to_file(file, obj);
// json_object_to_file_ext(file, obj, flags);
- _json_c_strerror_enable = 1;
-
const char *testdir;
if (argc < 2)
{