From a68df043bfbc7f8f38332143577877846631eca4 Mon Sep 17 00:00:00 2001 From: MichaÅ‚ CichoÅ„ Date: Tue, 25 Aug 2015 19:58:37 +0200 Subject: Update build environment - remove faad2 - remove mad - remove polarssl - remove pthreads - add libcurl - add vtparse with UTF8 support - update project to use Visual Studio 2015 --- json-c/src/.gitignore | 94 +- json-c/src/AUTHORS | 10 +- json-c/src/COPYING | 61 +- json-c/src/ChangeLog | 347 +++--- json-c/src/Doxyfile | 2306 ++++++++++++++++++------------------- json-c/src/INSTALL | 229 ---- json-c/src/Makefile.am | 120 +- json-c/src/Makefile.am.inc | 4 +- json-c/src/README | 28 - json-c/src/README-WIN32.html | 2 +- json-c/src/README.html | 68 +- json-c/src/RELEASE_CHECKLIST.txt | 166 ++- json-c/src/arraylist.c | 209 ++-- json-c/src/arraylist.h | 117 +- json-c/src/autogen.sh | 14 +- json-c/src/bits.h | 63 +- json-c/src/config.h.in | 304 +++-- json-c/src/config.h.win32 | 150 ++- json-c/src/configure.in | 41 - json-c/src/debug.c | 181 ++- json-c/src/debug.h | 143 ++- json-c/src/json.h | 66 +- json-c/src/json.pc.in | 11 - json-c/src/json_config.h.in | 6 +- json-c/src/json_inttypes.h | 51 +- json-c/src/json_object.c | 1523 ++++++++++++++---------- json-c/src/json_object.h | 1098 ++++++++++-------- json-c/src/json_object_iterator.c | 336 +++--- json-c/src/json_object_iterator.h | 478 ++++---- json-c/src/json_object_private.h | 94 +- json-c/src/json_tokener.c | 1656 ++++++++++++++------------ json-c/src/json_tokener.h | 396 ++++--- json-c/src/json_util.c | 548 +++++---- json-c/src/json_util.h | 89 +- json-c/src/linkhash.c | 838 ++++++++++---- json-c/src/linkhash.h | 583 +++++----- json-c/src/printbuf.c | 385 ++++--- json-c/src/printbuf.h | 154 +-- 38 files changed, 7140 insertions(+), 5829 deletions(-) delete mode 100644 json-c/src/INSTALL delete mode 100644 json-c/src/configure.in delete mode 100644 json-c/src/json.pc.in (limited to 'json-c/src') diff --git a/json-c/src/.gitignore b/json-c/src/.gitignore index 5534d69..2eb042f 100644 --- a/json-c/src/.gitignore +++ b/json-c/src/.gitignore @@ -1,37 +1,57 @@ -.deps/ -.libs/ -/aclocal.m4 -/autom4te.cache -/config.guess -/json_config.h -/config.h -/config.log -/config.status -/config.sub -/configure -/depcomp -/install-sh -/json.pc -/libtool -/ltmain.sh -/Makefile -/Makefile.in -/missing -/stamp-h1 -/stamp-h2 -/tests/Makefile -/tests/Makefile.in -/tests/test1 -/tests/test2 -/tests/test4 -/tests/testSubDir -/tests/test_parse_int64 -/tests/test_parse -/tests/test_cast -/tests/test_null -/tests/test_printbuf -/Debug -/Release -*.lo -*.o -/libjson.la +*~ +*.swp +/INSTALL +.deps/ +.libs/ +/aclocal.m4 +/autom4te.cache +/config.guess +/json_config.h +/compile +/config.h +/config.log +/config.status +/config.sub +/configure +/depcomp +/doc +/install-sh +/json.pc +/json-c.pc +/json-c-uninstalled.pc +/libtool +/ltmain.sh +/Makefile +/Makefile.in +/missing +/stamp-h1 +/stamp-h2 +/test-driver +/tests/Makefile +/tests/Makefile.in +/tests/test1 +/tests/test1Formatted +/tests/test2 +/tests/test2Formatted +/tests/test4 +/tests/testReplaceExisting +/tests/testSubDir +/tests/test_parse_int64 +/tests/test_parse +/tests/test_cast +/tests/test_charcase +/tests/test_locale +/tests/test_null +/tests/test_printbuf +/tests/test_set_serializer +/tests/*.vg.out +/tests/*.log +/tests/*.trs +/Debug +/Release +/*/Debug +/*/Release +*.lo +*.o +/libjson-c.la +/libjson.la diff --git a/json-c/src/AUTHORS b/json-c/src/AUTHORS index b389989..836925a 100644 --- a/json-c/src/AUTHORS +++ b/json-c/src/AUTHORS @@ -1,5 +1,5 @@ -Michael Clark -Jehiah Czebotar -Eric Haszlakiewicz -C. Watford (christopher.watford@gmail.com) - +Michael Clark +Jehiah Czebotar +Eric Haszlakiewicz +C. Watford (christopher.watford@gmail.com) + diff --git a/json-c/src/COPYING b/json-c/src/COPYING index f8ff2e1..67ff5d5 100644 --- a/json-c/src/COPYING +++ b/json-c/src/COPYING @@ -1,19 +1,42 @@ -Copyright (c) 2004, 2005 Metaparadigm Pte Ltd - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + +Copyright (c) 2009-2012 Eric Haszlakiewicz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +---------------------------------------------------------------- + +Copyright (c) 2004, 2005 Metaparadigm Pte Ltd + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/json-c/src/ChangeLog b/json-c/src/ChangeLog index 5d2c9af..5bf5bb8 100644 --- a/json-c/src/ChangeLog +++ b/json-c/src/ChangeLog @@ -1,129 +1,218 @@ -0.10 - * Fix a bug in json_object_get_int(), which would incorrectly return 0 - when called on a string type object. - Eric Haszlakiewicz - * Add a json_type_to_name() function. - Eric Haszlakiewicz - * Add a json_tokener_parse_verbose() function. - Jehiah Czebotar - * Improve support for null bytes within JSON strings. - Jehiah Czebotar - * Fix file descriptor leak if memory allocation fails in json_util - Zachary Blair, zack_blair at hotmail dot com - * Add int64 support. Two new functions json_object_net_int64 and - json_object_get_int64. Binary compatibility preserved. - Eric Haszlakiewicz, EHASZLA at transunion com - Rui Miguel Silva Seabra, rms at 1407 dot org - * Fix subtle bug in linkhash where lookup could hang after all slots - were filled then successively freed. - Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com - * Make json_object_from_file take const char *filename - Spotted by Vikram Raj V, vsagar at attinteractive dot com - * Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am) - Brent Miller, bdmiller at yahoo dash inc dot com - * Correction to comment describing printbuf_memappend in printbuf.h - Brent Miller, bdmiller at yahoo dash inc dot com - -0.9 - * Add README.html README-WIN32.html config.h.win32 to Makefile.am - Michael Clark, - * Add const qualifier to the json_tokener_parse functions - Eric Haszlakiewicz, EHASZLA at transunion dot com - * Rename min and max so we can never clash with C or C++ std library - Ian Atha, thatha at yahoo dash inc dot com - * Fix any noticeable spelling or grammar errors. - * Make sure every va_start has a va_end. - * Check all pointers for validity. - Erik Hovland, erik at hovland dot org - * Fix json_object_get_boolean to return false for empty string - Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com - * optimizations to json_tokener_parse_ex(), printbuf_memappend() - Brent Miller, bdmiller at yahoo dash inc dot com - * Disable REFCOUNT_DEBUG by default in json_object.c - * Don't use this as a variable, so we can compile with a C++ compiler - * Add casts from void* to type of assignment when using malloc - * Add #ifdef __cplusplus guards to all of the headers - * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table - Michael Clark, - * Null pointer dereference fix. Fix json_object_get_boolean strlen test - to not return TRUE for zero length string. Remove redundant includes. - Erik Hovland, erik at hovland dot org - * Fixed warning reported by adding -Wstrict-prototypes - -Wold-style-definition to the compilatin flags. - Dotan Barak, dotanba at gmail dot com - * Add const correctness to public interfaces - Gerard Krol, g dot c dot krol at student dot tudelft dot nl - -0.8 - * Add va_end for every va_start - Dotan Barak, dotanba at gmail dot com - * Add macros to enable compiling out debug code - Geoffrey Young, geoff at modperlcookbook dot org - * Fix bug with use of capital E in numbers with exponents - Mateusz Loskot, mateusz at loskot dot net - * Add stddef.h include - * Patch allows for json-c compile with -Werror and not fail due to - -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations - Geoffrey Young, geoff at modperlcookbook dot org - -0.7 - * Add escaping of backslash to json output - * Add escaping of foward slash on tokenizing and output - * Changes to internal tokenizer from using recursion to - using a depth state structure to allow incremental parsing - -0.6 - * Fix bug in escaping of control characters - Johan Björklund, johbjo09 at kth dot se - * Remove include "config.h" from headers (should only - be included from .c files) - Michael Clark - -0.5 - * Make headers C++ compatible by change *this to *obj - * Add ifdef C++ extern "C" to headers - * Use simpler definition of min and max in bits.h - Larry Lansing, llansing at fuzzynerd dot com - - * Remove automake 1.6 requirement - * Move autogen commands into autogen.sh. Update README - * Remove error pointer special case for Windows - * Change license from LGPL to MIT - Michael Clark - -0.4 - * Fix additional error case in object parsing - * Add back sign reversal in nested object parse as error pointer - value is negative, while error value is positive. - Michael Clark - -0.3 - * fix pointer arithmetic bug for error pointer check in is_error() macro - * fix type passed to printbuf_memappend in json_tokener - * update autotools bootstrap instructions in README - Michael Clark - -0.2 - * printbuf.c - C. Watford (christopher.watford@gmail.com) - Added a Win32/Win64 compliant implementation of vasprintf - * debug.c - C. Watford (christopher.watford@gmail.com) - Removed usage of vsyslog on Win32/Win64 systems, needs to be handled - by a configure script - * json_object.c - C. Watford (christopher.watford@gmail.com) - Added scope operator to wrap usage of json_object_object_foreach, this - needs to be rethought to be more ANSI C friendly - * json_object.h - C. Watford (christopher.watford@gmail.com) - Added Microsoft C friendly version of json_object_object_foreach - * json_tokener.c - C. Watford (christopher.watford@gmail.com) - Added a Win32/Win64 compliant implementation of strndup - * json_util.c - C. Watford (christopher.watford@gmail.com) - Added cast and mask to suffice size_t v. unsigned int conversion - correctness - * json_tokener.c - sign reversal issue on error info for nested object parse - spotted by Johan Björklund (johbjo09 at kth.se) - * json_object.c - escape " in json_escape_str - * Change to automake and libtool to build shared and static library - Michael Clark - -0.1 - * initial release + +NEXT.VERSION + + ...nothing yet... + +0.12 + + * Address security issues: + * CVE-2013-6371: hash collision denial of service + * CVE-2013-6370: buffer overflow if size_t is larger than int + + * Avoid potential overflow in json_object_get_double + + * Eliminate the mc_abort() function and MC_ABORT macro. + + * Make the json_tokener_errors array local. It has been deprecated for + a while, and json_tokener_error_desc() should be used instead. + + * change the floating point output format to %.17g so values with + more than 6 digits show up in the output. + + * Remove the old libjson.so name compatibility support. The library is + only created as libjson-c.so now and headers are only installed + into the ${prefix}/json-c directory. + + * When supported by the linker, add the -Bsymbolic-functions flag. + + * Various changes to fix the build on MSVC. + + * Make strict mode more strict: + * number must not start with 0 + * no single-quote strings + * no comments + * trailing char not allowed + * only allow lowercase literals + + * Added a json_object_new_double_s() convenience function to allow + an exact string representation of a double to be specified when + creating the object and use it in json_tokener_parse_ex() so + a re-serialized object more exactly matches the input. + + * Add support NaN and Infinity + + +0.11 + + * IMPORTANT: the name of the library has changed to libjson-c.so and + the header files are now in include/json-c. + The pkgconfig name has also changed from json to json-c. + You should change your build to use appropriate -I and -l options. + A compatibility shim is in place so builds using the old name will + continue to work, but that will be removed in the next release. + * Maximum recursion depth is now a runtime option. + json_tokener_new() is provided for compatibility. + json_tokener_new_ex(depth) + * Include json_object_iterator.h in the installed headers. + * Add support for building on Android. + * Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid. + * Make it safe to delete keys while iterating with the json_object_object_foreach macro. + * Add a json_set_serializer() function to allow the string output of a json_object to be customized. + * Make float parsing locale independent. + * Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag. + * Enable -Werror when building. + * speed improvements to parsing 64-bit integers on systems with working sscanf + * Add a json_object_object_length function. + * Fix a bug (buffer overrun) when expanding arrays to more than 64 entries. + +0.10 + + * Add a json_object_to_json_string_ext() function to allow output to be + formatted in a more human readable form. + * Add json_object_object_get_ex(), a NULL-safe get object method, to be able + to distinguish between a key not present and the value being NULL. + * Add an alternative iterator implementation, see json_object_iterator.h + * Make json_object_iter public to enable external use of the + json_object_object_foreachC macro. + * Add a printbuf_memset() function to provide an effecient way to set and + append things like whitespace indentation. + * Adjust json_object_is_type and json_object_get_type so they return + json_type_null for NULL objects and handle NULL passed to + json_objct_object_get(). + * Rename boolean type to json_bool. + * Fix various compile issues for Visual Studio and MinGW. + * Allow json_tokener_parse_ex() to be re-used to parse multiple object. + Also, fix some parsing issues with capitalized hexadecimal numbers and + number in E notation. + * Add json_tokener_get_error() and json_tokener_error_desc() to better + encapsulate the process of retrieving errors while parsing. + * Various improvements to the documentation of many functions. + * Add new json_object_array_sort() function. + * Fix a bug in json_object_get_int(), which would incorrectly return 0 + when called on a string type object. + Eric Haszlakiewicz + * Add a json_type_to_name() function. + Eric Haszlakiewicz + * Add a json_tokener_parse_verbose() function. + Jehiah Czebotar + * Improve support for null bytes within JSON strings. + Jehiah Czebotar + * Fix file descriptor leak if memory allocation fails in json_util + Zachary Blair, zack_blair at hotmail dot com + * Add int64 support. Two new functions json_object_net_int64 and + json_object_get_int64. Binary compatibility preserved. + Eric Haszlakiewicz, EHASZLA at transunion com + Rui Miguel Silva Seabra, rms at 1407 dot org + * Fix subtle bug in linkhash where lookup could hang after all slots + were filled then successively freed. + Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com + * Make json_object_from_file take const char *filename + Spotted by Vikram Raj V, vsagar at attinteractive dot com + * Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am) + Brent Miller, bdmiller at yahoo dash inc dot com + * Correction to comment describing printbuf_memappend in printbuf.h + Brent Miller, bdmiller at yahoo dash inc dot com + +0.9 + * Add README.html README-WIN32.html config.h.win32 to Makefile.am + Michael Clark, + * Add const qualifier to the json_tokener_parse functions + Eric Haszlakiewicz, EHASZLA at transunion dot com + * Rename min and max so we can never clash with C or C++ std library + Ian Atha, thatha at yahoo dash inc dot com + * Fix any noticeable spelling or grammar errors. + * Make sure every va_start has a va_end. + * Check all pointers for validity. + Erik Hovland, erik at hovland dot org + * Fix json_object_get_boolean to return false for empty string + Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com + * optimizations to json_tokener_parse_ex(), printbuf_memappend() + Brent Miller, bdmiller at yahoo dash inc dot com + * Disable REFCOUNT_DEBUG by default in json_object.c + * Don't use this as a variable, so we can compile with a C++ compiler + * Add casts from void* to type of assignment when using malloc + * Add #ifdef __cplusplus guards to all of the headers + * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table + Michael Clark, + * Null pointer dereference fix. Fix json_object_get_boolean strlen test + to not return TRUE for zero length string. Remove redundant includes. + Erik Hovland, erik at hovland dot org + * Fixed warning reported by adding -Wstrict-prototypes + -Wold-style-definition to the compilatin flags. + Dotan Barak, dotanba at gmail dot com + * Add const correctness to public interfaces + Gerard Krol, g dot c dot krol at student dot tudelft dot nl + +0.8 + * Add va_end for every va_start + Dotan Barak, dotanba at gmail dot com + * Add macros to enable compiling out debug code + Geoffrey Young, geoff at modperlcookbook dot org + * Fix bug with use of capital E in numbers with exponents + Mateusz Loskot, mateusz at loskot dot net + * Add stddef.h include + * Patch allows for json-c compile with -Werror and not fail due to + -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations + Geoffrey Young, geoff at modperlcookbook dot org + +0.7 + * Add escaping of backslash to json output + * Add escaping of foward slash on tokenizing and output + * Changes to internal tokenizer from using recursion to + using a depth state structure to allow incremental parsing + +0.6 + * Fix bug in escaping of control characters + Johan Björklund, johbjo09 at kth dot se + * Remove include "config.h" from headers (should only + be included from .c files) + Michael Clark + +0.5 + * Make headers C++ compatible by change *this to *obj + * Add ifdef C++ extern "C" to headers + * Use simpler definition of min and max in bits.h + Larry Lansing, llansing at fuzzynerd dot com + + * Remove automake 1.6 requirement + * Move autogen commands into autogen.sh. Update README + * Remove error pointer special case for Windows + * Change license from LGPL to MIT + Michael Clark + +0.4 + * Fix additional error case in object parsing + * Add back sign reversal in nested object parse as error pointer + value is negative, while error value is positive. + Michael Clark + +0.3 + * fix pointer arithmetic bug for error pointer check in is_error() macro + * fix type passed to printbuf_memappend in json_tokener + * update autotools bootstrap instructions in README + Michael Clark + +0.2 + * printbuf.c - C. Watford (christopher.watford@gmail.com) + Added a Win32/Win64 compliant implementation of vasprintf + * debug.c - C. Watford (christopher.watford@gmail.com) + Removed usage of vsyslog on Win32/Win64 systems, needs to be handled + by a configure script + * json_object.c - C. Watford (christopher.watford@gmail.com) + Added scope operator to wrap usage of json_object_object_foreach, this + needs to be rethought to be more ANSI C friendly + * json_object.h - C. Watford (christopher.watford@gmail.com) + Added Microsoft C friendly version of json_object_object_foreach + * json_tokener.c - C. Watford (christopher.watford@gmail.com) + Added a Win32/Win64 compliant implementation of strndup + * json_util.c - C. Watford (christopher.watford@gmail.com) + Added cast and mask to suffice size_t v. unsigned int conversion + correctness + * json_tokener.c - sign reversal issue on error info for nested object parse + spotted by Johan Björklund (johbjo09 at kth.se) + * json_object.c - escape " in json_escape_str + * Change to automake and libtool to build shared and static library + Michael Clark + +0.1 + * initial release diff --git a/json-c/src/Doxyfile b/json-c/src/Doxyfile index 3ff27eb..23f05ff 100644 --- a/json-c/src/Doxyfile +++ b/json-c/src/Doxyfile @@ -1,1153 +1,1153 @@ -# Doxyfile 1.3.8 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = json-c - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.10 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doc - -# 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 will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of source -# files, where putting all generated files in the same directory would otherwise -# cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, -# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, -# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, -# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, -# Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# This tag can be used to specify the encoding used in the generated output. -# The encoding is not always determined by the language that is chosen, -# but also whether or not the output is meant for Windows or non-Windows users. -# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES -# forces the Windows encoding (this is the default for the Windows binary), -# whereas setting the tag to NO uses a Unix-style encoding (the default for -# all platforms other than Windows). - -USE_WINDOWS_ENCODING = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is used -# as the annotated text. Otherwise, the brief description is used as-is. If left -# blank, the following values are used ("$name" is automatically replaced with the -# name of the entity): "The $name class" "The $name widget" "The $name file" -# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# 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 header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explicit @brief command for a brief description. - -JAVADOC_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources -# only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = NO - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories -# that are symbolic links (a Unix filesystem feature) are excluded from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# 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 command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# 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 -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the -# parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superseded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes that -# lay further from the root node will be omitted. Note that setting this option to -# 1 or 2 may greatly reduce the computation time needed for large code bases. Also -# note that a graph may be further truncated if the graph's image dimensions are -# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). -# If 0 is used for the depth value (the default), the graph is not depth-constrained. - -MAX_DOT_GRAPH_DEPTH = 0 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO +# Doxyfile 1.3.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = json-c + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.12.99 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# 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 will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# 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 header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# 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 command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# 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 +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/json-c/src/INSTALL b/json-c/src/INSTALL deleted file mode 100644 index a4b3414..0000000 --- a/json-c/src/INSTALL +++ /dev/null @@ -1,229 +0,0 @@ -Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. - - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is -disabled by default to prevent problems with accidental use of stale -cache files.) - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the `--target=TYPE' option to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -will cause the specified gcc to be used as the C compiler (unless it is -overridden in the site shell script). - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/json-c/src/Makefile.am b/json-c/src/Makefile.am index d4a7bbb..f330b7e 100644 --- a/json-c/src/Makefile.am +++ b/json-c/src/Makefile.am @@ -1,46 +1,74 @@ -include Makefile.am.inc - -EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc json-c.vcproj -SUBDIRS = . tests - -lib_LTLIBRARIES = libjson.la - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = json.pc - -libjsonincludedir = $(includedir)/json -libjsoninclude_HEADERS = \ - arraylist.h \ - bits.h \ - debug.h \ - json.h \ - json_config.h \ - json_inttypes.h \ - json_object.h \ - json_object_private.h \ - json_tokener.h \ - json_util.h \ - linkhash.h \ - printbuf.h - -#libjsonx_includedir = $(libdir)/json-c-@VERSION@ -# -#libjsonx_include_HEADERS = \ -# json_config.h - -libjson_la_LDFLAGS = -version-info 1:0:1 -no-undefined - -libjson_la_SOURCES = \ - arraylist.c \ - debug.c \ - json_object.c \ - json_tokener.c \ - json_util.c \ - linkhash.c \ - printbuf.c - - -distclean-local: - -rm -rf $(testsubdir) - -rm -rf config.h.in~ Makefile.in aclocal.m4 autom4te.cache/ config.guess config.sub configure depcomp install-sh ltmain.sh missing - +include Makefile.am.inc + +EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc json-c.vcproj +SUBDIRS = . tests + +lib_LTLIBRARIES = libjson-c.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = json-c.pc + +libjson_cincludedir = $(includedir)/json-c +libjson_cinclude_HEADERS = \ + arraylist.h \ + bits.h \ + debug.h \ + json.h \ + json_config.h \ + json_c_version.h \ + json_inttypes.h \ + json_object.h \ + json_object_iterator.h \ + json_object_private.h \ + json_tokener.h \ + json_util.h \ + linkhash.h \ + printbuf.h \ + random_seed.h + +#libjsonx_includedir = $(libdir)/json-c-@VERSION@ +# +#libjsonx_include_HEADERS = \ +# json_config.h + +libjson_c_la_LDFLAGS = -version-info 3:0:0 -no-undefined @JSON_BSYMBOLIC_LDFLAGS@ + +libjson_c_la_SOURCES = \ + arraylist.c \ + debug.c \ + json_c_version.c \ + json_object.c \ + json_object_iterator.c \ + json_tokener.c \ + json_util.c \ + linkhash.c \ + printbuf.c \ + random_seed.c + + +distclean-local: + -rm -rf $(testsubdir) + -rm -rf config.h.in~ Makefile.in aclocal.m4 autom4te.cache/ config.guess config.sub depcomp install-sh ltmain.sh missing + -rm -f INSTALL test-driver tests/Makefile.in compile + +maintainer-clean-local: + -rm -rf configure + +uninstall-local: + rm -rf "$(DESTDIR)@includedir@/json-c" + rm -f "$(DESTDIR)@includedir@/json" + +ANDROID_CFLAGS = -I$(top_srcdir) -DHAVE_CONFIG_H + +Android.mk: Makefile.am + androgenizer -:PROJECT json-c \ + -:SHARED libjson-c \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libjson_c_la_SOURCES) $(nodist_libjson_c_la_SOURCES) \ + -:CFLAGS $(DEFS) $(ANDROID_CFLAGS) $(libjson_c_la_CFLAGS) \ + -:LDFLAGS $(libjson_c_la_LDFLAGS) $(libjson_c_la_LIBADD) \ + -:HEADER_TARGET json-c \ + -:HEADERS $(libjson_cinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/json-c/src/Makefile.am.inc b/json-c/src/Makefile.am.inc index b1ebce8..0e11275 100644 --- a/json-c/src/Makefile.am.inc +++ b/json-c/src/Makefile.am.inc @@ -1,2 +1,2 @@ -AM_CFLAGS = -Wall -Wwrite-strings -Werror -std=gnu99 -D_GNU_SOURCE -D_REENTRANT - +AM_CFLAGS = -Wall -Werror -Wno-error=deprecated-declarations -Wextra -Wwrite-strings -Wno-unused-parameter -std=gnu99 -D_GNU_SOURCE -D_REENTRANT + diff --git a/json-c/src/README b/json-c/src/README index 05ec274..e69de29 100644 --- a/json-c/src/README +++ b/json-c/src/README @@ -1,28 +0,0 @@ -Building on Unix with git, gcc and autotools - -Home page for json-c: - http://oss.metaparadigm.com/json-c/ - -Github repo for json-c: - https://github.com/json-c/json-c - - $ git clone https://github.com/json-c/json-c.git - $ cd json-c - $ sh autogen.sh - -Then - - $ ./configure - $ make - $ make install - -To build and run the test programs run - - $ make check - -Linking to libjson - -If your system has pkgconfig then you can just add this to your makefile - -CFLAGS += $(shell pkg-config --cflags json) -LDFLAGS += $(shell pkg-config --libs json) diff --git a/json-c/src/README-WIN32.html b/json-c/src/README-WIN32.html index 28fc7d8..abdb39e 100644 --- a/json-c/src/README-WIN32.html +++ b/json-c/src/README-WIN32.html @@ -13,7 +13,7 @@ Various functions have been redefined to their Win32 version (i.e. open on win32 is _open)
  • - Implemented missing functions from MS's libc (i.e. vasprintf and strndup)
  • + Implemented missing functions from MS's libc (i.e. vasprintf)
  • Added code to allow Win64 support without integer resizing issues, this probably makes it much nicer on 64bit machines everywhere (i.e. using ptrdiff_t diff --git a/json-c/src/README.html b/json-c/src/README.html index dc696af..7c2f9f4 100644 --- a/json-c/src/README.html +++ b/json-c/src/README.html @@ -1,34 +1,34 @@ - - - - JSON-C - A JSON implementation in C - - - -

    JSON-C - A JSON implementation in C

    - -

    Overview

    -

    JSON-C implements a reference counting object model that allows you to easily - construct JSON objects in C, output them as JSON formatted strings and parse - JSON formatted strings back into the C representation of JSON objects.

    - -

    Building

    -

    To setup JSON-C to build on your system please run configure and make.

    -

    If you are on Win32 and are not using the VS project file, be sure - to rename config.h.win32 to config.h before building.

    - -

    Documentation

    -

    Doxygen generated documentation exists here - and Win32 specific notes can be found here.

    - -

    GIT Reposository

    -

    git clone https://github.com/json-c/json-c.git

    - -

    Mailing List

    - Send email to json-c <at> googlegroups <dot> com

    - -

    License

    -

    This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..

    -
    - - + + + + JSON-C - A JSON implementation in C + + + +

    JSON-C - A JSON implementation in C

    + +

    Overview

    +

    JSON-C implements a reference counting object model that allows you to easily + construct JSON objects in C, output them as JSON formatted strings and parse + JSON formatted strings back into the C representation of JSON objects.

    + +

    Building

    +

    To setup JSON-C to build on your system please run configure and make.

    +

    If you are on Win32 and are not using the VS project file, be sure + to rename config.h.win32 to config.h before building.

    + +

    Documentation

    +

    Doxygen generated documentation exists here + and Win32 specific notes can be found here.

    + +

    GIT Reposository

    +

    git clone https://github.com/json-c/json-c.git

    + +

    Mailing List

    + Send email to json-c <at> googlegroups <dot> com

    + +

    License

    +

    This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..

    +
    + + diff --git a/json-c/src/RELEASE_CHECKLIST.txt b/json-c/src/RELEASE_CHECKLIST.txt index 1a8d555..ac11109 100644 --- a/json-c/src/RELEASE_CHECKLIST.txt +++ b/json-c/src/RELEASE_CHECKLIST.txt @@ -1,34 +1,132 @@ - -Release checklist: - -release=0.10 -git clone https://github.com/json-c/json-c json-c-${release} -cd json-c-${release} - -Check that the compile works on Linux -Check that the compile works on Windows -Check ChangeLog to see if anything should be added. - -git branch json-c-${release} -git checkout json-c-${release} -sh autogen.sh -XXX doxygen - -XXX Add generated files to git? - -cd .. -tar czf json-c-${release}.tar.gz json-c-${release} - -XXX upload tarball to ??? - -=================================== - -Post-release checklist: - -git branch master -Add new section to CHANGES -Update the version in Doxyfile -Update the version in configure.in -Update the libjson_la_LDFLAGS line in Makefile.am to the new version. - http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html - + +Release checklist: + +release=0.12 +git clone https://github.com/json-c/json-c json-c-${release} +cd json-c-${release} + +Check that the compile works on Linux +Check that the compile works on NetBSD +Check that the compile works on Windows +Check ChangeLog to see if anything should be added. +Make any fixes/changes *before* branching. + + git branch json-c-${release} + git checkout json-c-${release} + +------------ + +Update the version in json_c_version.h +Update the version in Doxyfile +Update the version in configure.ac + Use ${release}. + +Update the libjson_la_LDFLAGS line in Makefile.am to the new version. + Generally, unless we're doing a major release, change: + -version-info x:y:z + to + -version-info x:y+1:z + +------------ + +Generate the configure script and other files: + sh autogen.sh + git add -f Makefile.in aclocal.m4 config.guess \ + config.sub configure depcomp install-sh \ + ltmain.sh missing tests/Makefile.in \ + INSTALL + + # check for anything else to be added: + git status --ignored + git commit + +------------ + +Generate the doxygen documentation: + doxygen + git add -f doc + git commit doc + +------------ + +cd .. +echo .git > excludes +echo autom4te.cache >> excludes +tar -czf json-c-${release}.tar.gz -X excludes json-c-${release} + +echo doc >> excludes +tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release} + +------------ + +Tag the branch: +cd json-c-${release} +git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}" + +git push origin json-c-${release} +git push --tags + +------------ + +Go to Amazon S3 service at: + https://console.aws.amazon.com/s3/ + +Upload the two tarballs in the json-c_releases folder. + When uploading, use "Reduced Redundancy", and make the uploaded files publicly accessible. + +Logout of Amazon S3, and verify that the files are visible. + https://s3.amazonaws.com/json-c_releases/releases/index.html + +=================================== + +Post-release checklist: + +git checkout master +Add new section to ChangeLog +Update the version in json_c_version.h +Update the version in Doxyfile +Update the version in configure.ac + Use ${release}.99 to indicate a version "newer" than anything on the branch. + +Leave the libjson_la_LDFLAGS line in Makefile.am alone. + For more details see: + http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html + +------------ + +Update the gh-pages branch with new docs: + +cd json-c-${release} +git checkout json-c-${release} +cd .. + +git clone -b gh-pages https://github.com/json-c/json-c json-c-pages +cd json-c-pages +mkdir json-c-${release} +cp -R ../json-c-${release}/doc json-c-${release}/. +cp ../json-c-${release}/README-WIN32.html json-c-${release}/. +git add json-c-${release} +git commit + +vi index.html + Add/change links to current release. + +git commit index.html + +git push + +------------ + +Update checksums on wiki page. + +cd .. +openssl sha -sha256 json-c*gz +openssl md5 json-c*gz + +Copy and paste this output into the wiki page at: + https://github.com/json-c/json-c/wiki + +------------ + +Send an email to the mailing list. + diff --git a/json-c/src/arraylist.c b/json-c/src/arraylist.c index 9a673d6..7e39078 100644 --- a/json-c/src/arraylist.c +++ b/json-c/src/arraylist.c @@ -1,101 +1,108 @@ -/* - * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#include "config.h" - -#if STDC_HEADERS -# include -# include -#endif /* STDC_HEADERS */ - -#if defined HAVE_STRINGS_H && !defined _STRING_H && !defined __USE_BSD -# include -#endif /* HAVE_STRINGS_H */ - -#include "bits.h" -#include "arraylist.h" - -struct array_list* -array_list_new(array_list_free_fn *free_fn) -{ - struct array_list *arr; - - arr = (struct array_list*)calloc(1, sizeof(struct array_list)); - if(!arr) return NULL; - arr->size = ARRAY_LIST_DEFAULT_SIZE; - arr->length = 0; - arr->free_fn = free_fn; - if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { - free(arr); - return NULL; - } - return arr; -} - -extern void -array_list_free(struct array_list *arr) -{ - int i; - for(i = 0; i < arr->length; i++) - if(arr->array[i]) arr->free_fn(arr->array[i]); - free(arr->array); - free(arr); -} - -void* -array_list_get_idx(struct array_list *arr, int i) -{ - if(i >= arr->length) return NULL; - return arr->array[i]; -} - -static int array_list_expand_internal(struct array_list *arr, int max) -{ - void *t; - int new_size; - - if(max < arr->size) return 0; - new_size = json_max(arr->size << 1, 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_put_idx(struct array_list *arr, int idx, void *data) -{ - if(array_list_expand_internal(arr, idx)) return -1; - if(arr->array[idx]) arr->free_fn(arr->array[idx]); - arr->array[idx] = data; - if(arr->length <= idx) arr->length = idx + 1; - return 0; -} - -int -array_list_add(struct array_list *arr, void *data) -{ - return array_list_put_idx(arr, arr->length, data); -} - -void -array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *)) -{ - qsort(arr->array, arr->length, sizeof(arr->array[0]), - (int (*)(const void *, const void *))sort_fn); -} - -int -array_list_length(struct array_list *arr) -{ - return arr->length; -} +/* + * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#ifdef STDC_HEADERS +# include +# include +#endif /* STDC_HEADERS */ + +#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD) +# include +#endif /* HAVE_STRINGS_H */ + +#include "arraylist.h" + +struct array_list* +array_list_new(array_list_free_fn *free_fn) +{ + struct array_list *arr; + + arr = (struct array_list*)calloc(1, sizeof(struct array_list)); + if(!arr) return NULL; + arr->size = ARRAY_LIST_DEFAULT_SIZE; + arr->length = 0; + arr->free_fn = free_fn; + if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { + free(arr); + return NULL; + } + return arr; +} + +extern void +array_list_free(struct array_list *arr) +{ + int i; + for(i = 0; i < arr->length; i++) + if(arr->array[i]) arr->free_fn(arr->array[i]); + free(arr->array); + free(arr); +} + +void* +array_list_get_idx(struct array_list *arr, int i) +{ + if(i >= arr->length) return NULL; + return arr->array[i]; +} + +static int array_list_expand_internal(struct array_list *arr, int max) +{ + void *t; + int new_size; + + if(max < arr->size) return 0; + new_size = arr->size << 1; + if (new_size < max) + new_size = 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_put_idx(struct array_list *arr, int idx, void *data) +{ + if(array_list_expand_internal(arr, idx+1)) return -1; + if(arr->array[idx]) arr->free_fn(arr->array[idx]); + arr->array[idx] = data; + if(arr->length <= idx) arr->length = idx + 1; + return 0; +} + +int +array_list_add(struct array_list *arr, void *data) +{ + return array_list_put_idx(arr, arr->length, data); +} + +void +array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *)) +{ + qsort(arr->array, arr->length, sizeof(arr->array[0]), sort_fn); +} + +void* array_list_bsearch(const void **key, struct array_list *arr, + int (*sort_fn)(const void *, const void *)) +{ + return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]), + sort_fn); +} + +int +array_list_length(struct array_list *arr) +{ + return arr->length; +} diff --git a/json-c/src/arraylist.h b/json-c/src/arraylist.h index 4f3113c..1f68410 100644 --- a/json-c/src/arraylist.h +++ b/json-c/src/arraylist.h @@ -1,56 +1,61 @@ -/* - * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _arraylist_h_ -#define _arraylist_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define ARRAY_LIST_DEFAULT_SIZE 32 - -typedef void (array_list_free_fn) (void *data); - -struct array_list -{ - void **array; - int length; - int size; - array_list_free_fn *free_fn; -}; - -extern struct array_list* -array_list_new(array_list_free_fn *free_fn); - -extern void -array_list_free(struct array_list *al); - -extern void* -array_list_get_idx(struct array_list *al, int i); - -extern int -array_list_put_idx(struct array_list *al, int i, void *data); - -extern int -array_list_add(struct array_list *al, void *data); - -extern int -array_list_length(struct array_list *al); - -extern void -array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *)); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _arraylist_h_ +#define _arraylist_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARRAY_LIST_DEFAULT_SIZE 32 + +typedef void (array_list_free_fn) (void *data); + +struct array_list +{ + void **array; + int length; + int size; + array_list_free_fn *free_fn; +}; + +extern struct array_list* +array_list_new(array_list_free_fn *free_fn); + +extern void +array_list_free(struct array_list *al); + +extern void* +array_list_get_idx(struct array_list *al, int i); + +extern int +array_list_put_idx(struct array_list *al, int i, void *data); + +extern int +array_list_add(struct array_list *al, void *data); + +extern int +array_list_length(struct array_list *al); + +extern void +array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *)); + +extern void* array_list_bsearch(const void **key, + struct array_list *arr, + int (*sort_fn)(const void *, const void *)); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/autogen.sh b/json-c/src/autogen.sh index c67b903..51d9e8e 100644 --- a/json-c/src/autogen.sh +++ b/json-c/src/autogen.sh @@ -1 +1,13 @@ -autoreconf -v --install || exit 1 +#!/bin/sh +autoreconf -v --install || exit 1 + +# If there are any options, assume the user wants to run configure. +# To run configure w/o any options, use ./autogen.sh --configure +if [ $# -gt 0 ] ; then + case "$1" in + --conf*) + shift 1 + ;; + esac + exec ./configure "$@" +fi diff --git a/json-c/src/bits.h b/json-c/src/bits.h index c8cbbc8..8b87307 100644 --- a/json-c/src/bits.h +++ b/json-c/src/bits.h @@ -1,28 +1,35 @@ -/* - * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _bits_h_ -#define _bits_h_ - -#ifndef json_min -#define json_min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef json_max -#define json_max(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) -#define error_ptr(error) ((void*)error) -#define error_description(error) (json_tokener_errors[error]) -#define is_error(ptr) (ptr == NULL) - -#endif +/** + * @file + * @deprecated Use json_util.h instead. + * + * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _bits_h_ +#define _bits_h_ + +/** + * @deprecated + */ +#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) +/** + * @deprecated + */ +#define error_ptr(error) ((void*)error) +/** + * @deprecated + */ +#define error_description(error) (json_tokener_get_error(error)) +/** + * @deprecated + */ +#define is_error(ptr) (ptr == NULL) + +#endif diff --git a/json-c/src/config.h.in b/json-c/src/config.h.in index 04f5dc5..e84ae72 100644 --- a/json-c/src/config.h.in +++ b/json-c/src/config.h.in @@ -1,127 +1,177 @@ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `open' function. */ -#undef HAVE_OPEN - -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#undef HAVE_REALLOC - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strncasecmp' function. */ -#undef HAVE_STRNCASECMP - -/* Define to 1 if you have the `strndup' function. */ -#undef HAVE_STRNDUP - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `vasprintf' function. */ -#undef HAVE_VASPRINTF - -/* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF - -/* Define to 1 if you have the `vsnprintf' function. */ -#undef HAVE_VSNPRINTF - -/* Define to 1 if you have the `vsyslog' function. */ -#undef HAVE_VSYSLOG - -/* Public define for json_inttypes.h */ -#undef JSON_C_HAVE_INTTYPES_H - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION - -/* 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 does not define. */ -#undef size_t +/* 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. */ +#undef HAVE_DECL_INFINITY + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#undef HAVE_DECL_ISINF + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#undef HAVE_DECL_ISNAN + +/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ +#undef HAVE_DECL_NAN + +/* Define to 1 if you have the declaration of `_finite', and to 0 if you + don't. */ +#undef HAVE_DECL__FINITE + +/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't. + */ +#undef HAVE_DECL__ISNAN + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `open' function. */ +#undef HAVE_OPEN + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsyslog' function. */ +#undef HAVE_VSYSLOG + +/* Public define for json_inttypes.h */ +#undef JSON_C_HAVE_INTTYPES_H + +/* 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 */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* 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 does not define. */ +#undef size_t diff --git a/json-c/src/config.h.win32 b/json-c/src/config.h.win32 index ec3a84a..de6bc3c 100644 --- a/json-c/src/config.h.win32 +++ b/json-c/src/config.h.win32 @@ -1,26 +1,50 @@ -/* - * $Id: config.h.win32,v 1.2 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -/* config.h.win32 Generated by configure. */ - -#define PACKAGE_STRING "JSON C Library 0.2" -#define PACKAGE_BUGREPORT "json-c@googlegroups.com" -#define PACKAGE_NAME "JSON C Library" -#define PACKAGE_TARNAME "json-c" -#define PACKAGE_VERSION "0.2" - /* 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 +#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 +#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 +#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 +#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 header file. */ +#define HAVE_DLFCN_H 1 + /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ +#define HAVE_DOPRNT 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_ENDIAN_H /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 @@ -31,6 +55,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 +/* Define to 1 if you have the 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 @@ -39,23 +66,32 @@ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `open' function. */ -#undef HAVE_OPEN +#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 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. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 -/* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRNDUP +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 @@ -66,9 +102,15 @@ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H @@ -81,14 +123,60 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + /* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF +#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 1 if you have the `strncasecmp' function. */ -#undef HAVE_STRNCASECMP +/* 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.12.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.12.99" /* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.12.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 does not define. */ +/* #undef size_t */ diff --git a/json-c/src/configure.in b/json-c/src/configure.in deleted file mode 100644 index b2c3cbe..0000000 --- a/json-c/src/configure.in +++ /dev/null @@ -1,41 +0,0 @@ -AC_PREREQ(2.52) - -# Process this file with autoconf to produce a configure script. -AC_INIT([json-c], 0.10, [json-c@googlegroups.com]) - -AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) - -AC_PROG_MAKE_SET - -# Checks for programs. - -# Checks for libraries. - -# Checks for header files. -AM_CONFIG_HEADER(config.h) -AM_CONFIG_HEADER(json_config.h) -AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/param.h] stdarg.h) -AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_SIZE_T - -# Checks for library functions. -AC_FUNC_VPRINTF -AC_FUNC_MEMCMP -AC_FUNC_MALLOC -AC_FUNC_REALLOC -AC_CHECK_FUNCS(strndup strerror vsnprintf vasprintf open vsyslog strncasecmp) - -AM_PROG_LIBTOOL - -AC_CONFIG_FILES([ -Makefile -json.pc -tests/Makefile -]) - -AC_OUTPUT - diff --git a/json-c/src/debug.c b/json-c/src/debug.c index e0294ca..e6a8fec 100644 --- a/json-c/src/debug.c +++ b/json-c/src/debug.c @@ -1,98 +1,83 @@ -/* - * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#include "config.h" - -#include -#include -#include -#include - -#if HAVE_SYSLOG_H -# include -#endif /* HAVE_SYSLOG_H */ - -#if HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ - -#if HAVE_SYS_PARAM_H -#include -#endif /* HAVE_SYS_PARAM_H */ - -#include "debug.h" - -static int _syslog = 0; -static int _debug = 0; - -void mc_set_debug(int debug) { _debug = debug; } -int mc_get_debug(void) { return _debug; } - -extern void mc_set_syslog(int syslog) -{ - _syslog = syslog; -} - -void mc_abort(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); -#if HAVE_VSYSLOG - if(_syslog) { - vsyslog(LOG_ERR, msg, ap); - } else -#endif - vprintf(msg, ap); - va_end(ap); - exit(1); -} - - -void mc_debug(const char *msg, ...) -{ - va_list ap; - if(_debug) { - va_start(ap, msg); -#if HAVE_VSYSLOG - if(_syslog) { - vsyslog(LOG_DEBUG, msg, ap); - } else -#endif - vprintf(msg, ap); - va_end(ap); - } -} - -void mc_error(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); -#if HAVE_VSYSLOG - if(_syslog) { - vsyslog(LOG_ERR, msg, ap); - } else -#endif - vfprintf(stderr, msg, ap); - va_end(ap); -} - -void mc_info(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); -#if HAVE_VSYSLOG - if(_syslog) { - vsyslog(LOG_INFO, msg, ap); - } else -#endif - vfprintf(stderr, msg, ap); - va_end(ap); -} +/* + * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#if HAVE_SYSLOG_H +# include +#endif /* HAVE_SYSLOG_H */ + +#if HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ + +#include "debug.h" + +static int _syslog = 0; +static int _debug = 0; + +void mc_set_debug(int debug) { _debug = debug; } +int mc_get_debug(void) { return _debug; } + +extern void mc_set_syslog(int syslog) +{ + _syslog = syslog; +} + +void mc_debug(const char *msg, ...) +{ + va_list ap; + if(_debug) { + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_DEBUG, msg, ap); + } else +#endif + vprintf(msg, ap); + va_end(ap); + } +} + +void mc_error(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_ERR, msg, ap); + } else +#endif + vfprintf(stderr, msg, ap); + va_end(ap); +} + +void mc_info(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_INFO, msg, ap); + } else +#endif + vfprintf(stderr, msg, ap); + va_end(ap); +} diff --git a/json-c/src/debug.h b/json-c/src/debug.h index 1e09701..adcb482 100644 --- a/json-c/src/debug.h +++ b/json-c/src/debug.h @@ -1,72 +1,71 @@ -/* - * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _DEBUG_H_ -#define _DEBUG_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern void mc_set_debug(int debug); -extern int mc_get_debug(void); - -extern void mc_set_syslog(int syslog); -extern void mc_abort(const char *msg, ...); -extern void mc_debug(const char *msg, ...); -extern void mc_error(const char *msg, ...); -extern void mc_info(const char *msg, ...); - -#ifndef __STRING -#define __STRING(x) #x -#endif - -#ifndef PARSER_BROKEN_FIXED - -#define JASSERT(cond) do {} while(0) - -#else - -#define JASSERT(cond) do { \ - if (!(cond)) { \ - mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \ - *(int *)0 = 1;\ - abort(); \ - }\ - } while(0) - -#endif - -#define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__) -#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__) - -#ifdef MC_MAINTAINER_MODE -#define MC_SET_DEBUG(x) mc_set_debug(x) -#define MC_GET_DEBUG() mc_get_debug() -#define MC_SET_SYSLOG(x) mc_set_syslog(x) -#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) -#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) -#else -#define MC_SET_DEBUG(x) if (0) mc_set_debug(x) -#define MC_GET_DEBUG() (0) -#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) -#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) -#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) -#endif - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void mc_set_debug(int debug); +extern int mc_get_debug(void); + +extern void mc_set_syslog(int syslog); + +extern void mc_debug(const char *msg, ...); +extern void mc_error(const char *msg, ...); +extern void mc_info(const char *msg, ...); + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef PARSER_BROKEN_FIXED + +#define JASSERT(cond) do {} while(0) + +#else + +#define JASSERT(cond) do { \ + if (!(cond)) { \ + mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \ + *(int *)0 = 1;\ + abort(); \ + }\ + } while(0) + +#endif + +#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__) + +#ifdef MC_MAINTAINER_MODE +#define MC_SET_DEBUG(x) mc_set_debug(x) +#define MC_GET_DEBUG() mc_get_debug() +#define MC_SET_SYSLOG(x) mc_set_syslog(x) +#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) +#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) +#else +#define MC_SET_DEBUG(x) if (0) mc_set_debug(x) +#define MC_GET_DEBUG() (0) +#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) +#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) +#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/json.h b/json-c/src/json.h index d49715b..3bc68df 100644 --- a/json-c/src/json.h +++ b/json-c/src/json.h @@ -1,33 +1,33 @@ -/* - * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _json_h_ -#define _json_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bits.h" -#include "debug.h" -#include "linkhash.h" -#include "arraylist.h" -#include "json_util.h" -#include "json_object.h" -#include "json_tokener.h" -#include "json_object_iterator.h" - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_h_ +#define _json_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "debug.h" +#include "linkhash.h" +#include "arraylist.h" +#include "json_util.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_object_iterator.h" +#include "json_c_version.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/json.pc.in b/json-c/src/json.pc.in deleted file mode 100644 index b3d140b..0000000 --- a/json-c/src/json.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: json -Description: JSON implementation in C -Version: @VERSION@ -Requires: -Libs: -L${libdir} -ljson -Cflags: -I${includedir}/json diff --git a/json-c/src/json_config.h.in b/json-c/src/json_config.h.in index 7888e02..6efdeb6 100644 --- a/json-c/src/json_config.h.in +++ b/json-c/src/json_config.h.in @@ -1,3 +1,3 @@ - -/* Define to 1 if you have the header file. */ -#undef JSON_C_HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef JSON_C_HAVE_INTTYPES_H diff --git a/json-c/src/json_inttypes.h b/json-c/src/json_inttypes.h index d34b11b..17667f0 100644 --- a/json-c/src/json_inttypes.h +++ b/json-c/src/json_inttypes.h @@ -1,32 +1,19 @@ - -#ifndef _json_inttypes_h_ -#define _json_inttypes_h_ - -#include "json_config.h" - -#if defined(_MSC_VER) && _MSC_VER >= 1600 - -/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */ -/* -typedef __int32 int32_t; -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX ((int32_t)_I32_MAX) -typedef __int64 int64_t; -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX ((int64_t)_I64_MAX) -*/ -#define PRId64 "I64d" -#define SCNd64 "I64d" - -#include - -#else - -#ifdef JSON_C_HAVE_INTTYPES_H -#include -#endif -/* inttypes.h includes stdint.h */ - -#endif - -#endif + +#ifndef _json_inttypes_h_ +#define _json_inttypes_h_ + +#include "json_config.h" + +#ifdef JSON_C_HAVE_INTTYPES_H +/* inttypes.h includes stdint.h */ +#include + +#else +#include + +#define PRId64 "I64d" +#define SCNd64 "I64d" + +#endif + +#endif diff --git a/json-c/src/json_object.c b/json-c/src/json_object.c index 84af414..2b66f76 100644 --- a/json-c/src/json_object.c +++ b/json-c/src/json_object.c @@ -1,588 +1,935 @@ -/* - * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "debug.h" -#include "printbuf.h" -#include "linkhash.h" -#include "arraylist.h" -#include "json_inttypes.h" -#include "json_object.h" -#include "json_object_private.h" -#include "json_util.h" - -#if !HAVE_STRNDUP - char* strndup(const char* str, size_t n); -#endif /* !HAVE_STRNDUP */ - -// 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); - - -/* ref count debugging */ - -#ifdef REFCOUNT_DEBUG - -static struct lh_table *json_object_table; - -static void json_object_init(void) __attribute__ ((constructor)); -static void json_object_init(void) { - MC_DEBUG("json_object_init: creating object table\n"); - json_object_table = lh_kptr_table_new(128, "json_object_table", NULL); -} - -static void json_object_fini(void) __attribute__ ((destructor)); -static void json_object_fini(void) { - struct lh_entry *ent; - if(MC_GET_DEBUG()) { - if (json_object_table->count) { - MC_DEBUG("json_object_fini: %d referenced objects at exit\n", - json_object_table->count); - lh_foreach(json_object_table, ent) { - struct json_object* obj = (struct json_object*)ent->v; - MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); - } - } - } - MC_DEBUG("json_object_fini: freeing object table\n"); - lh_table_free(json_object_table); -} -#endif /* REFCOUNT_DEBUG */ - - -/* string escaping */ - -static int json_escape_str(struct printbuf *pb, char *str, int len) -{ - int pos = 0, start_offset = 0; - unsigned char c; - while (len--) { - c = str[pos]; - switch(c) { - case '\b': - case '\n': - case '\r': - case '\t': - case '"': - case '\\': - case '/': - if(pos - start_offset > 0) - printbuf_memappend(pb, str + start_offset, pos - start_offset); - if(c == '\b') printbuf_memappend(pb, "\\b", 2); - else if(c == '\n') printbuf_memappend(pb, "\\n", 2); - else if(c == '\r') printbuf_memappend(pb, "\\r", 2); - else if(c == '\t') printbuf_memappend(pb, "\\t", 2); - else if(c == '"') printbuf_memappend(pb, "\\\"", 2); - else if(c == '\\') printbuf_memappend(pb, "\\\\", 2); - else if(c == '/') printbuf_memappend(pb, "\\/", 2); - start_offset = ++pos; - break; - default: - if(c < ' ') { - if(pos - start_offset > 0) - printbuf_memappend(pb, str + start_offset, pos - start_offset); - sprintbuf(pb, "\\u00%c%c", - json_hex_chars[c >> 4], - json_hex_chars[c & 0xf]); - start_offset = ++pos; - } else pos++; - } - } - if(pos - start_offset > 0) - printbuf_memappend(pb, str + start_offset, pos - start_offset); - return 0; -} - - -/* reference counting */ - -extern struct json_object* json_object_get(struct json_object *jso) -{ - if(jso) { - jso->_ref_count++; - } - return jso; -} - -extern void json_object_put(struct json_object *jso) -{ - if(jso) { - jso->_ref_count--; - if(!jso->_ref_count) jso->_delete(jso); - } -} - - -/* generic object construction and destruction parts */ - -static void json_object_generic_delete(struct json_object* jso) -{ -#ifdef REFCOUNT_DEBUG - MC_DEBUG("json_object_delete_%s: %p\n", - json_type_to_name(jso->o_type), jso); - lh_table_delete(json_object_table, jso); -#endif /* REFCOUNT_DEBUG */ - printbuf_free(jso->_pb); - free(jso); -} - -static struct json_object* json_object_new(enum json_type o_type) -{ - struct json_object *jso; - - jso = (struct json_object*)calloc(sizeof(struct json_object), 1); - if(!jso) return NULL; - jso->o_type = o_type; - jso->_ref_count = 1; - jso->_delete = &json_object_generic_delete; -#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); -#endif /* REFCOUNT_DEBUG */ - return jso; -} - - -/* type checking functions */ - -int json_object_is_type(struct json_object *jso, enum json_type type) -{ - if (!jso) - return (type == json_type_null); - return (jso->o_type == type); -} - -enum json_type json_object_get_type(struct json_object *jso) -{ - if (!jso) - return json_type_null; - return jso->o_type; -} - -/* json_object_to_json_string */ - -const char* json_object_to_json_string(struct json_object *jso) -{ - if(!jso) return "null"; - if(!jso->_pb) { - if(!(jso->_pb = printbuf_new())) return NULL; - } else { - printbuf_reset(jso->_pb); - } - if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL; - return jso->_pb->buf; -} - - -/* json_object_object */ - -static int json_object_object_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - int i=0; - struct json_object_iter iter; - sprintbuf(pb, "{"); - - /* CAW: scope operator to make ANSI correctness */ - /* CAW: switched to json_object_object_foreachC which uses an iterator struct */ - json_object_object_foreachC(jso, iter) { - if(i) sprintbuf(pb, ","); - sprintbuf(pb, " \""); - json_escape_str(pb, iter.key, strlen(iter.key)); - sprintbuf(pb, "\": "); - if(iter.val == NULL) sprintbuf(pb, "null"); - else iter.val->_to_json_string(iter.val, pb); - i++; - } - - return sprintbuf(pb, " }"); -} - -static void json_object_lh_entry_free(struct lh_entry *ent) -{ - free(ent->k); - json_object_put((struct json_object*)ent->v); -} - -static void json_object_object_delete(struct json_object* jso) -{ - lh_table_free(jso->o.c_object); - json_object_generic_delete(jso); -} - -struct json_object* json_object_new_object(void) -{ - struct json_object *jso = json_object_new(json_type_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 = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, - NULL, &json_object_lh_entry_free); - return jso; -} - -struct lh_table* json_object_get_object(struct json_object *jso) -{ - if(!jso) return NULL; - switch(jso->o_type) { - case json_type_object: - return jso->o.c_object; - default: - return NULL; - } -} - -void json_object_object_add(struct json_object* jso, const char *key, - struct json_object *val) -{ - lh_table_delete(jso->o.c_object, key); - lh_table_insert(jso->o.c_object, strdup(key), val); -} - -struct json_object* json_object_object_get(struct json_object* jso, const char *key) -{ - struct json_object *result; - json_object_object_get_ex(jso, key, &result); - return result; -} - -json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value) -{ - if (NULL == jso) return FALSE; - - switch(jso->o_type) { - case json_type_object: - return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value); - default: - if (value != NULL) { - *value = NULL; - } - return FALSE; - } -} - -void json_object_object_del(struct json_object* jso, const char *key) -{ - lh_table_delete(jso->o.c_object, key); -} - - -/* json_object_boolean */ - -static int json_object_boolean_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - if(jso->o.c_boolean) return sprintbuf(pb, "true"); - else return sprintbuf(pb, "false"); -} - -struct json_object* json_object_new_boolean(json_bool b) -{ - struct json_object *jso = json_object_new(json_type_boolean); - if(!jso) return NULL; - jso->_to_json_string = &json_object_boolean_to_json_string; - jso->o.c_boolean = b; - return jso; -} - -json_bool json_object_get_boolean(struct json_object *jso) -{ - if(!jso) return FALSE; - switch(jso->o_type) { - case json_type_boolean: - return jso->o.c_boolean; - case json_type_int: - return (jso->o.c_int64 != 0); - case json_type_double: - return (jso->o.c_double != 0); - case json_type_string: - return (jso->o.c_string.len != 0); - default: - return FALSE; - } -} - - -/* json_object_int */ - -static int json_object_int_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - return sprintbuf(pb, "%"PRId64, jso->o.c_int64); -} - -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_int64 = i; - return jso; -} - -int32_t json_object_get_int(struct json_object *jso) -{ - int64_t cint64; - enum json_type o_type; - - if(!jso) return 0; - - o_type = jso->o_type; - cint64 = jso->o.c_int64; - - if (o_type == json_type_string) - { - /* - * Parse strings into 64-bit numbers, then use the - * 64-to-32-bit number handling below. - */ - if (json_parse_int64(jso->o.c_string.str, &cint64) != 0) - return 0; /* whoops, it didn't work. */ - o_type = json_type_int; - } - - switch(o_type) { - case json_type_int: - /* Make sure we return the correct values for out of range numbers. */ - if (cint64 <= INT32_MIN) - return INT32_MIN; - else if (cint64 >= INT32_MAX) - return INT32_MAX; - else - return (int32_t)cint64; - case json_type_double: - return (int32_t)jso->o.c_double; - case json_type_boolean: - return jso->o.c_boolean; - default: - return 0; - } -} - -struct json_object* json_object_new_int64(int64_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_int64 = i; - return jso; -} - -int64_t json_object_get_int64(struct json_object *jso) -{ - int64_t cint; - - if(!jso) return 0; - switch(jso->o_type) { - case json_type_int: - return jso->o.c_int64; - case json_type_double: - return (int64_t)jso->o.c_double; - case json_type_boolean: - return jso->o.c_boolean; - case json_type_string: - if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint; - default: - return 0; - } -} - - -/* json_object_double */ - -static int json_object_double_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - return sprintbuf(pb, "%lf", jso->o.c_double); -} - -struct json_object* json_object_new_double(double d) -{ - struct json_object *jso = json_object_new(json_type_double); - if(!jso) return NULL; - jso->_to_json_string = &json_object_double_to_json_string; - jso->o.c_double = d; - return jso; -} - -double json_object_get_double(struct json_object *jso) -{ - double cdouble; - - if(!jso) return 0.0; - switch(jso->o_type) { - case json_type_double: - return jso->o.c_double; - case json_type_int: - return jso->o.c_int64; - case json_type_boolean: - return jso->o.c_boolean; - case json_type_string: - if(sscanf(jso->o.c_string.str, "%lf", &cdouble) == 1) return cdouble; - default: - return 0.0; - } -} - - -/* json_object_string */ - -static int json_object_string_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - sprintbuf(pb, "\""); - json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len); - sprintbuf(pb, "\""); - return 0; -} - -static void json_object_string_delete(struct json_object* jso) -{ - free(jso->o.c_string.str); - json_object_generic_delete(jso); -} - -struct json_object* json_object_new_string(const char *s) -{ - 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; - jso->o.c_string.str = strdup(s); - jso->o.c_string.len = strlen(s); - return jso; -} - -struct json_object* json_object_new_string_len(const char *s, int len) -{ - 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; - jso->o.c_string.str = malloc(len); - memcpy(jso->o.c_string.str, (void *)s, len); - jso->o.c_string.len = len; - return jso; -} - -const char* json_object_get_string(struct json_object *jso) -{ - if(!jso) return NULL; - switch(jso->o_type) { - case json_type_string: - return jso->o.c_string.str; - default: - return json_object_to_json_string(jso); - } -} - -int json_object_get_string_len(struct json_object *jso) { - if(!jso) return 0; - switch(jso->o_type) { - case json_type_string: - return jso->o.c_string.len; - default: - return 0; - } -} - - -/* json_object_array */ - -static int json_object_array_to_json_string(struct json_object* jso, - struct printbuf *pb) -{ - int i; - sprintbuf(pb, "["); - for(i=0; i < json_object_array_length(jso); i++) { - struct json_object *val; - if(i) { sprintbuf(pb, ", "); } - else { sprintbuf(pb, " "); } - - val = json_object_array_get_idx(jso, i); - if(val == NULL) { sprintbuf(pb, "null"); } - else { val->_to_json_string(val, pb); } - } - return sprintbuf(pb, " ]"); -} - -static void json_object_array_entry_free(void *data) -{ - json_object_put((struct json_object*)data); -} - -static void json_object_array_delete(struct json_object* jso) -{ - array_list_free(jso->o.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); - 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); - return jso; -} - -struct array_list* json_object_get_array(struct json_object *jso) -{ - if(!jso) return NULL; - switch(jso->o_type) { - case json_type_array: - return jso->o.c_array; - default: - return NULL; - } -} - -void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)) -{ - array_list_sort(jso->o.c_array, sort_fn); -} - -int json_object_array_length(struct json_object *jso) -{ - return array_list_length(jso->o.c_array); -} - -int json_object_array_add(struct json_object *jso,struct json_object *val) -{ - return array_list_add(jso->o.c_array, val); -} - -int json_object_array_put_idx(struct json_object *jso, int idx, - struct json_object *val) -{ - return array_list_put_idx(jso->o.c_array, idx, val); -} - -struct json_object* json_object_array_get_idx(struct json_object *jso, - int idx) -{ - return (struct json_object*)array_list_get_idx(jso->o.c_array, idx); -} - +/* + * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "printbuf.h" +#include "linkhash.h" +#include "arraylist.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_object_private.h" +#include "json_util.h" +#include "math_compat.h" + +#if !defined(HAVE_STRDUP) && defined(_MSC_VER) + /* MSC has the version as _strdup */ +# define strdup _strdup +#elif !defined(HAVE_STRDUP) +# error You do not have strdup on your system. +#endif /* HAVE_STRDUP */ + +#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) + /* MSC has the version as _snprintf */ +# define snprintf _snprintf +#elif !defined(HAVE_SNPRINTF) +# error You do not have snprintf on your system. +#endif /* HAVE_SNPRINTF */ + +// 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); + +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; +static json_object_to_json_string_fn json_object_int_to_json_string; +static json_object_to_json_string_fn json_object_double_to_json_string; +static json_object_to_json_string_fn json_object_string_to_json_string; +static json_object_to_json_string_fn json_object_array_to_json_string; + + +/* ref count debugging */ + +#ifdef REFCOUNT_DEBUG + +static struct lh_table *json_object_table; + +static void json_object_init(void) __attribute__ ((constructor)); +static void json_object_init(void) { + MC_DEBUG("json_object_init: creating object table\n"); + json_object_table = lh_kptr_table_new(128, "json_object_table", NULL); +} + +static void json_object_fini(void) __attribute__ ((destructor)); +static void json_object_fini(void) +{ + struct lh_entry *ent; + if (MC_GET_DEBUG()) + { + if (json_object_table->count) + { + MC_DEBUG("json_object_fini: %d referenced objects at exit\n", + json_object_table->count); + lh_foreach(json_object_table, ent) + { + struct json_object* obj = (struct json_object*)ent->v; + MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); + } + } + } + MC_DEBUG("json_object_fini: freeing object table\n"); + lh_table_free(json_object_table); +} +#endif /* REFCOUNT_DEBUG */ + + +/* string escaping */ + +static int json_escape_str(struct printbuf *pb, char *str, int len) +{ + int pos = 0, start_offset = 0; + unsigned char c; + while (len--) + { + c = str[pos]; + switch(c) + { + case '\b': + case '\n': + case '\r': + case '\t': + case '\f': + case '"': + case '\\': + case '/': + if(pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + + if(c == '\b') printbuf_memappend(pb, "\\b", 2); + else if(c == '\n') printbuf_memappend(pb, "\\n", 2); + else if(c == '\r') printbuf_memappend(pb, "\\r", 2); + else if(c == '\t') printbuf_memappend(pb, "\\t", 2); + else if(c == '\f') printbuf_memappend(pb, "\\f", 2); + else if(c == '"') printbuf_memappend(pb, "\\\"", 2); + else if(c == '\\') printbuf_memappend(pb, "\\\\", 2); + else if(c == '/') printbuf_memappend(pb, "\\/", 2); + + start_offset = ++pos; + break; + default: + if(c < ' ') + { + if(pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + sprintbuf(pb, "\\u00%c%c", + json_hex_chars[c >> 4], + json_hex_chars[c & 0xf]); + start_offset = ++pos; + } else + pos++; + } + } + if (pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + return 0; +} + + +/* reference counting */ + +extern struct json_object* json_object_get(struct json_object *jso) +{ + if (jso) + jso->_ref_count++; + return jso; +} + +int json_object_put(struct json_object *jso) +{ + if(jso) + { + jso->_ref_count--; + if(!jso->_ref_count) + { + if (jso->_user_delete) + jso->_user_delete(jso, jso->_userdata); + jso->_delete(jso); + return 1; + } + } + return 0; +} + + +/* generic object construction and destruction parts */ + +static void json_object_generic_delete(struct json_object* jso) +{ +#ifdef REFCOUNT_DEBUG + MC_DEBUG("json_object_delete_%s: %p\n", + json_type_to_name(jso->o_type), jso); + lh_table_delete(json_object_table, jso); +#endif /* REFCOUNT_DEBUG */ + printbuf_free(jso->_pb); + free(jso); +} + +static struct json_object* json_object_new(enum json_type o_type) +{ + struct json_object *jso; + + jso = (struct json_object*)calloc(sizeof(struct json_object), 1); + if (!jso) + return NULL; + jso->o_type = o_type; + jso->_ref_count = 1; + jso->_delete = &json_object_generic_delete; +#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); +#endif /* REFCOUNT_DEBUG */ + return jso; +} + + +/* type checking functions */ + +int json_object_is_type(struct json_object *jso, enum json_type type) +{ + if (!jso) + return (type == json_type_null); + return (jso->o_type == type); +} + +enum json_type json_object_get_type(struct json_object *jso) +{ + if (!jso) + return json_type_null; + return jso->o_type; +} + +/* set a custom conversion to string */ + +void json_object_set_serializer(json_object *jso, + json_object_to_json_string_fn to_string_func, + void *userdata, + json_object_delete_fn *user_delete) +{ + // First, clean up any previously existing user info + if (jso->_user_delete) + { + jso->_user_delete(jso, jso->_userdata); + } + jso->_userdata = NULL; + jso->_user_delete = NULL; + + if (to_string_func == NULL) + { + // Reset to the standard serialization function + switch(jso->o_type) + { + case json_type_null: + jso->_to_json_string = NULL; + break; + case json_type_boolean: + jso->_to_json_string = &json_object_boolean_to_json_string; + break; + case json_type_double: + jso->_to_json_string = &json_object_double_to_json_string; + break; + case json_type_int: + jso->_to_json_string = &json_object_int_to_json_string; + break; + case json_type_object: + jso->_to_json_string = &json_object_object_to_json_string; + break; + case json_type_array: + jso->_to_json_string = &json_object_array_to_json_string; + break; + case json_type_string: + jso->_to_json_string = &json_object_string_to_json_string; + break; + } + return; + } + + jso->_to_json_string = to_string_func; + jso->_userdata = userdata; + jso->_user_delete = user_delete; +} + + +/* extended conversion to string */ + +const char* json_object_to_json_string_ext(struct json_object *jso, int flags) +{ + if (!jso) + return "null"; + + if ((!jso->_pb) && !(jso->_pb = printbuf_new())) + return NULL; + + printbuf_reset(jso->_pb); + + if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0) + return NULL; + + return jso->_pb->buf; +} + +/* backwards-compatible conversion to string */ + +const char* json_object_to_json_string(struct json_object *jso) +{ + return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED); +} + +static void indent(struct printbuf *pb, int level, int flags) +{ + if (flags & JSON_C_TO_STRING_PRETTY) + { + if (flags & JSON_C_TO_STRING_PRETTY_TAB) + { + printbuf_memset(pb, -1, '\t', level); + } + else + { + printbuf_memset(pb, -1, ' ', level * 2); + } + } +} + +/* json_object_object */ + +static int json_object_object_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + int had_children = 0; + struct json_object_iter iter; + + sprintbuf(pb, "{" /*}*/); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + json_object_object_foreachC(jso, iter) + { + if (had_children) + { + sprintbuf(pb, ","); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + } + had_children = 1; + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, " "); + indent(pb, level+1, flags); + sprintbuf(pb, "\""); + json_escape_str(pb, iter.key, strlen(iter.key)); + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, "\": "); + else + sprintbuf(pb, "\":"); + if(iter.val == NULL) + sprintbuf(pb, "null"); + else + iter.val->_to_json_string(iter.val, pb, level+1,flags); + } + if (flags & JSON_C_TO_STRING_PRETTY) + { + if (had_children) + sprintbuf(pb, "\n"); + indent(pb,level,flags); + } + if (flags & JSON_C_TO_STRING_SPACED) + return sprintbuf(pb, /*{*/ " }"); + else + return sprintbuf(pb, /*{*/ "}"); +} + + +static void json_object_lh_entry_free(struct lh_entry *ent) +{ + free(ent->k); + json_object_put((struct json_object*)ent->v); +} + +static void json_object_object_delete(struct json_object* jso) +{ + lh_table_free(jso->o.c_object); + json_object_generic_delete(jso); +} + +struct json_object* json_object_new_object(void) +{ + struct json_object *jso = json_object_new(json_type_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 = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, + NULL, &json_object_lh_entry_free); + if (!jso->o.c_object) + { + json_object_generic_delete(jso); + errno = ENOMEM; + return NULL; + } + return jso; +} + +struct lh_table* json_object_get_object(struct json_object *jso) +{ + if (!jso) + return NULL; + switch(jso->o_type) + { + case json_type_object: + return jso->o.c_object; + default: + return NULL; + } +} + +void json_object_object_add(struct json_object* jso, const char *key, + struct json_object *val) +{ + // We lookup the entry and replace the value, rather than just deleting + // and re-adding it, so the existing key remains valid. + json_object *existing_value = NULL; + struct lh_entry *existing_entry; + existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key); + if (!existing_entry) + { + lh_table_insert(jso->o.c_object, strdup(key), val); + return; + } + existing_value = (json_object *)existing_entry->v; + if (existing_value) + json_object_put(existing_value); + existing_entry->v = val; +} + +int json_object_object_length(struct json_object *jso) +{ + return lh_table_length(jso->o.c_object); +} + +struct json_object* json_object_object_get(struct json_object* jso, const char *key) +{ + struct json_object *result = NULL; + json_object_object_get_ex(jso, key, &result); + return result; +} + +json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value) +{ + if (value != NULL) + *value = NULL; + + if (NULL == jso) + return FALSE; + + switch(jso->o_type) + { + case json_type_object: + return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value); + default: + if (value != NULL) + *value = NULL; + return FALSE; + } +} + +void json_object_object_del(struct json_object* jso, const char *key) +{ + lh_table_delete(jso->o.c_object, key); +} + + +/* json_object_boolean */ + +static int json_object_boolean_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + if (jso->o.c_boolean) + return sprintbuf(pb, "true"); + else + return sprintbuf(pb, "false"); +} + +struct json_object* json_object_new_boolean(json_bool b) +{ + struct json_object *jso = json_object_new(json_type_boolean); + if (!jso) + return NULL; + jso->_to_json_string = &json_object_boolean_to_json_string; + jso->o.c_boolean = b; + return jso; +} + +json_bool json_object_get_boolean(struct json_object *jso) +{ + if (!jso) + return FALSE; + switch(jso->o_type) + { + case json_type_boolean: + return jso->o.c_boolean; + case json_type_int: + return (jso->o.c_int64 != 0); + case json_type_double: + return (jso->o.c_double != 0); + case json_type_string: + return (jso->o.c_string.len != 0); + default: + return FALSE; + } +} + + +/* json_object_int */ + +static int json_object_int_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + return sprintbuf(pb, "%"PRId64, jso->o.c_int64); +} + +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_int64 = i; + return jso; +} + +int32_t json_object_get_int(struct json_object *jso) +{ + int64_t cint64; + enum json_type o_type; + + if(!jso) return 0; + + o_type = jso->o_type; + cint64 = jso->o.c_int64; + + if (o_type == json_type_string) + { + /* + * Parse strings into 64-bit numbers, then use the + * 64-to-32-bit number handling below. + */ + if (json_parse_int64(jso->o.c_string.str, &cint64) != 0) + return 0; /* whoops, it didn't work. */ + o_type = json_type_int; + } + + switch(o_type) { + case json_type_int: + /* Make sure we return the correct values for out of range numbers. */ + if (cint64 <= INT32_MIN) + return INT32_MIN; + else if (cint64 >= INT32_MAX) + return INT32_MAX; + else + return (int32_t)cint64; + case json_type_double: + return (int32_t)jso->o.c_double; + case json_type_boolean: + return jso->o.c_boolean; + default: + return 0; + } +} + +struct json_object* json_object_new_int64(int64_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_int64 = i; + return jso; +} + +int64_t json_object_get_int64(struct json_object *jso) +{ + int64_t cint; + + if (!jso) + return 0; + switch(jso->o_type) + { + case json_type_int: + return jso->o.c_int64; + case json_type_double: + return (int64_t)jso->o.c_double; + case json_type_boolean: + return jso->o.c_boolean; + case json_type_string: + if (json_parse_int64(jso->o.c_string.str, &cint) == 0) + return cint; + default: + return 0; + } +} + + +/* json_object_double */ + +static int json_object_double_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + char buf[128], *p, *q; + int size; + /* Although JSON RFC does not support + NaN or Infinity as numeric values + ECMA 262 section 9.8.1 defines + how to handle these cases as strings */ + if(isnan(jso->o.c_double)) + size = snprintf(buf, sizeof(buf), "NaN"); + else if(isinf(jso->o.c_double)) + if(jso->o.c_double > 0) + size = snprintf(buf, sizeof(buf), "Infinity"); + else + size = snprintf(buf, sizeof(buf), "-Infinity"); + else + size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double); + + p = strchr(buf, ','); + if (p) { + *p = '.'; + } else { + p = strchr(buf, '.'); + } + if (p && (flags & JSON_C_TO_STRING_NOZERO)) { + /* last useful digit, always keep 1 zero */ + p++; + for (q=p ; *q ; q++) { + if (*q!='0') p=q; + } + /* drop trailing zeroes */ + *(++p) = 0; + size = p-buf; + } + printbuf_memappend(pb, buf, size); + return size; +} + +struct json_object* json_object_new_double(double d) +{ + struct json_object *jso = json_object_new(json_type_double); + if (!jso) + return NULL; + jso->_to_json_string = &json_object_double_to_json_string; + jso->o.c_double = d; + return jso; +} + +struct json_object* json_object_new_double_s(double d, const char *ds) +{ + struct json_object *jso = json_object_new_double(d); + if (!jso) + return NULL; + + char *new_ds = strdup(ds); + if (!new_ds) + { + json_object_generic_delete(jso); + errno = ENOMEM; + return NULL; + } + json_object_set_serializer(jso, json_object_userdata_to_json_string, + new_ds, json_object_free_userdata); + return jso; +} + +int json_object_userdata_to_json_string(struct json_object *jso, + struct printbuf *pb, int level, int flags) +{ + int userdata_len = strlen((const char *)jso->_userdata); + printbuf_memappend(pb, (const char *)jso->_userdata, userdata_len); + return userdata_len; +} + +void json_object_free_userdata(struct json_object *jso, void *userdata) +{ + free(userdata); +} + +double json_object_get_double(struct json_object *jso) +{ + double cdouble; + char *errPtr = NULL; + + if(!jso) return 0.0; + switch(jso->o_type) { + case json_type_double: + return jso->o.c_double; + case json_type_int: + return jso->o.c_int64; + case json_type_boolean: + return jso->o.c_boolean; + case json_type_string: + errno = 0; + cdouble = strtod(jso->o.c_string.str,&errPtr); + + /* if conversion stopped at the first character, return 0.0 */ + if (errPtr == jso->o.c_string.str) + return 0.0; + + /* + * Check that the conversion terminated on something sensible + * + * For example, { "pay" : 123AB } would parse as 123. + */ + if (*errPtr != '\0') + return 0.0; + + /* + * If strtod encounters a string which would exceed the + * capacity of a double, it returns +/- HUGE_VAL and sets + * errno to ERANGE. But +/- HUGE_VAL is also a valid result + * from a conversion, so we need to check errno. + * + * Underflow also sets errno to ERANGE, but it returns 0 in + * that case, which is what we will return anyway. + * + * See CERT guideline ERR30-C + */ + if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && + (ERANGE == errno)) + cdouble = 0.0; + return cdouble; + default: + return 0.0; + } +} + + +/* json_object_string */ + +static int json_object_string_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + sprintbuf(pb, "\""); + json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len); + sprintbuf(pb, "\""); + return 0; +} + +static void json_object_string_delete(struct json_object* jso) +{ + free(jso->o.c_string.str); + json_object_generic_delete(jso); +} + +struct json_object* json_object_new_string(const char *s) +{ + 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; + jso->o.c_string.str = strdup(s); + if (!jso->o.c_string.str) + { + json_object_generic_delete(jso); + errno = ENOMEM; + return NULL; + } + jso->o.c_string.len = strlen(s); + return jso; +} + +struct json_object* json_object_new_string_len(const char *s, int len) +{ + 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; + jso->o.c_string.str = (char*)malloc(len + 1); + if (!jso->o.c_string.str) + { + json_object_generic_delete(jso); + errno = ENOMEM; + return NULL; + } + memcpy(jso->o.c_string.str, (void *)s, len); + jso->o.c_string.str[len] = '\0'; + jso->o.c_string.len = len; + return jso; +} + +const char* json_object_get_string(struct json_object *jso) +{ + if (!jso) + return NULL; + switch(jso->o_type) + { + case json_type_string: + return jso->o.c_string.str; + default: + return json_object_to_json_string(jso); + } +} + +int json_object_get_string_len(struct json_object *jso) +{ + if (!jso) + return 0; + switch(jso->o_type) + { + case json_type_string: + return jso->o.c_string.len; + default: + return 0; + } +} + + +/* json_object_array */ + +static int json_object_array_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + int had_children = 0; + int ii; + sprintbuf(pb, "["); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + for(ii=0; ii < json_object_array_length(jso); ii++) + { + struct json_object *val; + if (had_children) + { + sprintbuf(pb, ","); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + } + had_children = 1; + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, " "); + indent(pb, level + 1, flags); + val = json_object_array_get_idx(jso, ii); + if(val == NULL) + sprintbuf(pb, "null"); + else + val->_to_json_string(val, pb, level+1, flags); + } + if (flags & JSON_C_TO_STRING_PRETTY) + { + if (had_children) + sprintbuf(pb, "\n"); + indent(pb,level,flags); + } + + if (flags & JSON_C_TO_STRING_SPACED) + return sprintbuf(pb, " ]"); + else + return sprintbuf(pb, "]"); +} + +static void json_object_array_entry_free(void *data) +{ + json_object_put((struct json_object*)data); +} + +static void json_object_array_delete(struct json_object* jso) +{ + array_list_free(jso->o.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); + 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); + return jso; +} + +struct array_list* json_object_get_array(struct json_object *jso) +{ + if (!jso) + return NULL; + switch(jso->o_type) + { + case json_type_array: + return jso->o.c_array; + default: + return NULL; + } +} + +void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)) +{ + array_list_sort(jso->o.c_array, sort_fn); +} + +struct json_object* json_object_array_bsearch( + const struct json_object *key, + const struct json_object *jso, + int (*sort_fn)(const void *, const void *)) +{ + struct json_object **result; + + result = (struct json_object **)array_list_bsearch( + (const void **)&key, jso->o.c_array, sort_fn); + + if (!result) + return NULL; + return *result; +} + +int json_object_array_length(struct json_object *jso) +{ + return array_list_length(jso->o.c_array); +} + +int json_object_array_add(struct json_object *jso,struct json_object *val) +{ + return array_list_add(jso->o.c_array, val); +} + +int json_object_array_put_idx(struct json_object *jso, int idx, + struct json_object *val) +{ + return array_list_put_idx(jso->o.c_array, idx, val); +} + +struct json_object* json_object_array_get_idx(struct json_object *jso, + int idx) +{ + return (struct json_object*)array_list_get_idx(jso->o.c_array, idx); +} + diff --git a/json-c/src/json_object.h b/json-c/src/json_object.h index f7ec9ea..cc2da47 100644 --- a/json-c/src/json_object.h +++ b/json-c/src/json_object.h @@ -1,454 +1,644 @@ -/* - * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _json_object_h_ -#define _json_object_h_ - -#include "json_inttypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define JSON_OBJECT_DEF_HASH_ENTRIES 16 - -#undef FALSE -#define FALSE ((json_bool)0) - -#undef TRUE -#define TRUE ((json_bool)1) - -extern const char *json_number_chars; -extern const char *json_hex_chars; - -/* CAW: added for ANSI C iteration correctness */ -struct json_object_iter -{ - char *key; - struct json_object *val; - struct lh_entry *entry; -}; - -/* forward structure definitions */ - -typedef int json_bool; -typedef struct printbuf printbuf; -typedef struct lh_table lh_table; -typedef struct array_list array_list; -typedef struct json_object json_object; -typedef struct json_object_iter json_object_iter; -typedef struct json_tokener json_tokener; - -/* supported object types */ - -typedef enum json_type { - /* If you change this, be sure to update json_type_to_name() too */ - json_type_null, - json_type_boolean, - json_type_double, - json_type_int, - json_type_object, - json_type_array, - json_type_string, -} json_type; - -/* reference counting functions */ - -/** - * Increment the reference count of json_object, thereby grabbing shared - * ownership of obj. - * - * @param obj the json_object instance - */ -extern 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. - * - * @param obj the json_object instance - */ -extern void json_object_put(struct json_object *obj); - - -/** - * Check if the json_object is of a given type - * @param obj the json_object instance - * @param type one of: - json_type_null (i.e. obj == NULL), - json_type_boolean, - json_type_double, - json_type_int, - json_type_object, - json_type_array, - json_type_string, - */ -extern int json_object_is_type(struct json_object *obj, enum json_type type); - -/** - * Get the type of the json_object. See also json_type_to_name() to turn this - * into a string suitable, for instance, for logging. - * - * @param obj the json_object instance - * @returns type being one of: - json_type_null (i.e. obj == NULL), - json_type_boolean, - json_type_double, - json_type_int, - json_type_object, - json_type_array, - json_type_string, - */ -extern enum json_type json_object_get_type(struct json_object *obj); - - -/** Stringify object to json format - * @param obj the json_object instance - * @returns a string in JSON format - */ -extern const char* json_object_to_json_string(struct json_object *obj); - - -/* object type methods */ - -/** Create a new empty object with a reference count of 1. The caller of - * this object initially has sole ownership. Remember, when using - * json_object_object_add or json_object_array_put_idx, ownership will - * transfer to the object/array. Call json_object_get if you want to maintain - * shared ownership or also add this object as a child of multiple objects or - * arrays. Any ownerships you acquired but did not transfer must be released - * through json_object_put. - * - * @returns a json_object of type json_type_object - */ -extern struct json_object* json_object_new_object(void); - -/** Get the hashtable of a json_object of type json_type_object - * @param obj the json_object instance - * @returns a linkhash - */ -extern struct lh_table* json_object_get_object(struct json_object *obj); - -/** 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. - * - * 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. - * - * @param obj the json_object instance - * @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 - */ -extern void json_object_object_add(struct json_object* obj, const char *key, - struct json_object *val); - -/** Get the json_object associate with a given object field - * - * *No* reference counts will be changed. There is no need to manually adjust - * reference counts through the json_object_put/json_object_get methods unless - * you need to have the child (value) reference maintain a different lifetime - * than the owning parent (obj). Ownership of the returned value is retained - * by obj (do not do json_object_put unless you have done a json_object_get). - * If you delete the value from obj (json_object_object_del) and wish to access - * the returned reference afterwards, make sure you have first gotten shared - * ownership through json_object_get (& don't forget to do a json_object_put - * or transfer ownership to prevent a memory leak). - * - * @param obj the json_object instance - * @param key the object field name - * @returns the json_object associated with the given field name - * @deprecated Please use json_object_object_get_ex - */ -extern struct json_object* json_object_object_get(struct json_object* obj, - const char *key); - -/** Get the json_object associated with a given object field. - * - * This returns true if the key is found, false in all other cases (including - * if obj isn't a json_type_object). - * - * *No* reference counts will be changed. There is no need to manually adjust - * reference counts through the json_object_put/json_object_get methods unless - * you need to have the child (value) reference maintain a different lifetime - * than the owning parent (obj). Ownership of value is retained by obj. - * - * @param obj the json_object instance - * @param key the object field name - * @param value a pointer where to store a reference to the json_object - * associated with the given field name. - * - * It is safe to pass a NULL value. - * @returns whether or not the key exists - */ -extern json_bool json_object_object_get_ex(struct json_object* obj, - const char *key, - struct json_object **value); - -/** Delete the given json_object field - * - * The reference count will be decremented for the deleted object. If there - * are no more owners of the value represented by this key, then the value is - * freed. Otherwise, the reference to the value will remain in memory. - * - * @param obj the json_object instance - * @param key the object field name - */ -extern void json_object_object_del(struct json_object* obj, const char *key); - -/** Iterate through all keys and values of an object - * @param obj the json_object instance - * @param key the local name for the char* key variable defined in the body - * @param val the local name for the json_object* object variable defined in - * the body - */ -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) - -# define json_object_object_foreach(obj,key,val) \ - char *key; struct json_object *val; \ - for(struct lh_entry *entry = json_object_get_object(obj)->head; ({ if(entry) { key = (char*)entry->k; val = (struct json_object*)entry->v; } ; entry; }); entry = entry->next ) - -#else /* ANSI C or MSC */ - -# define json_object_object_foreach(obj,key,val) \ - char *key; struct json_object *val; struct lh_entry *entry; \ - for(entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, val = (struct json_object*)entry->v, entry) : 0); entry = entry->next) - -#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */ - -/** Iterate through all keys and values of an object (ANSI C Safe) - * @param obj the json_object instance - * @param iter the object iterator - */ -#define json_object_object_foreachC(obj,iter) \ - for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next) - -/* Array type methods */ - -/** Create a new empty json_object of type json_type_array - * @returns a json_object of type json_type_array - */ -extern struct json_object* json_object_new_array(void); - -/** Get the arraylist of a json_object of type json_type_array - * @param obj the json_object instance - * @returns an arraylist - */ -extern struct array_list* json_object_get_array(struct json_object *obj); - -/** Get the length of a json_object of type json_type_array - * @param obj the json_object instance - * @returns an int - */ -extern int json_object_array_length(struct json_object *obj); - -/** Sorts the elements of jso of type json_type_array -* -* Pointers to the json_object pointers will be passed as the two arguments -* to @sort_fn -* -* @param obj the json_object instance -* @param sort_fn a sorting function -*/ -extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)); - -/** Add an element to the end of a json_object of type json_type_array - * - * 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 you must wrap the passed object with json_object_get - * - * @param obj the json_object instance - * @param val the json_object to be added - */ -extern int json_object_array_add(struct json_object *obj, - struct json_object *val); - -/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) - * - * 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 you must wrap the passed object with json_object_get - * - * The reference count of a replaced object will be decremented. - * - * The array size will be automatically be expanded to the size of the - * index if the index is larger than the current size. - * - * @param obj the json_object instance - * @param idx the index to insert the element at - * @param val the json_object to be added - */ -extern int json_object_array_put_idx(struct json_object *obj, int idx, - struct json_object *val); - -/** Get the element at specificed index of the array (a json_object of type json_type_array) - * @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) - */ -extern struct json_object* json_object_array_get_idx(struct json_object *obj, - int idx); - -/* json_bool type methods */ - -/** Create a new empty json_object of type json_type_boolean - * @param b a json_bool TRUE or FALSE (0 or 1) - * @returns a json_object of type json_type_boolean - */ -extern struct json_object* json_object_new_boolean(json_bool b); - -/** Get the json_bool value of a json_object - * - * The type is coerced to a json_bool if the passed object is not a json_bool. - * integer and double objects will return FALSE if there value is zero - * or TRUE otherwise. If the passed object is a string it will return - * TRUE if it has a non zero length. If any other object type is passed - * TRUE will be returned if the object is not NULL. - * - * @param obj the json_object instance - * @returns a json_bool - */ -extern json_bool json_object_get_boolean(struct json_object *obj); - - -/* int type methods */ - -/** Create a new empty json_object of type json_type_int - * Note that values are stored as 64-bit values internally. - * To ensure the full range is maintained, use json_object_new_int64 instead. - * @param i the integer - * @returns a json_object of type json_type_int - */ -extern struct json_object* json_object_new_int(int32_t i); - - -/** Create a new empty json_object of type json_type_int - * @param i the integer - * @returns a json_object of type json_type_int - */ -extern struct json_object* json_object_new_int64(int64_t i); - - -/** Get the int value of a json_object - * - * The type is coerced to a int if the passed object is not a int. - * double objects will return their integer conversion. Strings will be - * parsed as an integer. If no conversion exists then 0 is returned - * and errno is set to EINVAL. null is equivalent to 0 (no error values set) - * - * Note that integers are stored internally as 64-bit values. - * If the value of too big or too small to fit into 32-bit, INT32_MAX or - * INT32_MIN are returned, respectively. - * - * @param obj the json_object instance - * @returns an int - */ -extern int32_t json_object_get_int(struct json_object *obj); - -/** Get the int value of a json_object - * - * The type is coerced to a int64 if the passed object is not a int64. - * double objects will return their int64 conversion. Strings will be - * parsed as an int64. If no conversion exists then 0 is returned. - * - * NOTE: Set errno to 0 directly before a call to this function to determine - * whether or not conversion was successful (it does not clear the value for - * you). - * - * @param obj the json_object instance - * @returns an int64 - */ -extern int64_t json_object_get_int64(struct json_object *obj); - - -/* double type methods */ - -/** Create a new empty json_object of type json_type_double - * @param d the double - * @returns a json_object of type json_type_double - */ -extern struct json_object* json_object_new_double(double d); - -/** Get the double floating point value of a json_object - * - * The type is coerced to a double if the passed object is not a double. - * integer objects will return their double conversion. Strings will be - * parsed as a double. If no conversion exists then 0.0 is returned and - * errno is set to EINVAL. null is equivalent to 0 (no error values set) - * - * If the value is too big to fit in a double, then the value is set to - * the closest infinity with errno set to ERANGE. If strings cannot be - * converted to their double value, then EINVAL is set & NaN is returned. - * - * Arrays of length 0 are interpreted as 0 (with no error flags set). - * Arrays of length 1 are effectively cast to the equivalent object and - * converted using the above rules. All other arrays set the error to - * EINVAL & return NaN. - * - * NOTE: Set errno to 0 directly before a call to this function to - * determine whether or not conversion was successful (it does not clear - * the value for you). - * - * @param obj the json_object instance - * @returns a double floating point number - */ -extern double json_object_get_double(struct json_object *obj); - - -/* string type methods */ - -/** Create a new empty json_object of type json_type_string - * - * A copy of the string is made and the memory is managed by the json_object - * - * @param s the string - * @returns a json_object of type json_type_string - */ -extern struct json_object* json_object_new_string(const char *s); - -extern struct json_object* json_object_new_string_len(const char *s, int len); - -/** Get the string value of a json_object - * - * If the passed object is not of type json_type_string then the JSON - * representation of the object is returned. - * - * The returned string memory is managed by the json_object and will - * be freed when the reference count of the json_object drops to zero. - * - * @param obj the json_object instance - * @returns a string - */ -extern const char* json_object_get_string(struct json_object *obj); - -/** Get the string length of a json_object - * - * If the passed object is not of type json_type_string then zero - * will be returned. - * - * @param obj the json_object instance - * @returns int - */ -extern int json_object_get_string_len(struct json_object *obj); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_object_h_ +#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 +#else +#define THIS_FUNCTION_IS_DEPRECATED(func) func +#endif + +#include "json_inttypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define JSON_OBJECT_DEF_HASH_ENTRIES 16 + +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes the output + * to have no extra whitespace or formatting applied. + */ +#define JSON_C_TO_STRING_PLAIN 0 +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes the output to have + * minimal whitespace inserted to make things slightly more readable. + */ +#define JSON_C_TO_STRING_SPACED (1<<0) +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes + * the output to be formatted. + * + * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/ + * for an example of the format. + */ +#define JSON_C_TO_STRING_PRETTY (1<<1) +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes + * the output to be formatted. + * + * Instead of a "Two Space Tab" this gives a single tab character. + */ +#define JSON_C_TO_STRING_PRETTY_TAB (1<<3) +/** + * A flag to drop trailing zero for float values + */ +#define JSON_C_TO_STRING_NOZERO (1<<2) + +#undef FALSE +#define FALSE ((json_bool)0) + +#undef TRUE +#define TRUE ((json_bool)1) + +extern const char *json_number_chars; +extern const char *json_hex_chars; + +/* CAW: added for ANSI C iteration correctness */ +struct json_object_iter +{ + char *key; + struct json_object *val; + struct lh_entry *entry; +}; + +/* forward structure definitions */ + +typedef int json_bool; +typedef struct printbuf printbuf; +typedef struct lh_table lh_table; +typedef struct array_list array_list; +typedef struct json_object json_object; +typedef struct json_object_iter json_object_iter; +typedef struct json_tokener json_tokener; + +/** + * Type of custom user delete functions. See json_object_set_serializer. + */ +typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata); + +/** + * Type of a custom serialization function. See json_object_set_serializer. + */ +typedef int (json_object_to_json_string_fn)(struct json_object *jso, + struct printbuf *pb, + int level, + int flags); + +/* supported object types */ + +typedef enum json_type { + /* If you change this, be sure to update json_type_to_name() too */ + json_type_null, + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string +} json_type; + +/* reference counting functions */ + +/** + * Increment the reference count of json_object, thereby grabbing shared + * ownership of obj. + * + * @param obj the json_object instance + */ +extern 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. + * + * @param obj the json_object instance + * @returns 1 if the object was freed. + */ +int json_object_put(struct json_object *obj); + +/** + * Check if the json_object is of a given type + * @param obj the json_object instance + * @param type one of: + json_type_null (i.e. obj == NULL), + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string + */ +extern int json_object_is_type(struct json_object *obj, enum json_type type); + +/** + * Get the type of the json_object. See also json_type_to_name() to turn this + * into a string suitable, for instance, for logging. + * + * @param obj the json_object instance + * @returns type being one of: + json_type_null (i.e. obj == NULL), + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string + */ +extern enum json_type json_object_get_type(struct json_object *obj); + + +/** Stringify object to json format. + * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED) + * The pointer you get is an internal of your json object. You don't + * have to free it, later use of json_object_put() should be sufficient. + * If you can not ensure there's no concurrent access to *obj use + * strdup(). + * @param obj the json_object instance + * @returns a string in JSON format + */ +extern const char* json_object_to_json_string(struct json_object *obj); + +/** Stringify object to json format + * @see json_object_to_json_string() for details on how to free string. + * @param obj the json_object instance + * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants + * @returns a string in JSON format + */ +extern const char* json_object_to_json_string_ext(struct json_object *obj, int +flags); + +/** + * Set a custom serialization function to be used when this particular object + * is converted to a string by json_object_to_json_string. + * + * If a custom serializer is already set on this object, any existing + * user_delete function is called before the new one is set. + * + * If to_string_func is NULL, the other parameters are ignored + * and the default behaviour is reset. + * + * The userdata parameter is optional and may be passed as NULL. If provided, + * it is passed to to_string_func as-is. This parameter may be NULL even + * if user_delete is non-NULL. + * + * The user_delete parameter is optional and may be passed as NULL, even if + * the userdata parameter is non-NULL. It will be called just before the + * json_object is deleted, after it's reference count goes to zero + * (see json_object_put()). + * If this is not provided, it is up to the caller to free the userdata at + * an appropriate time. (i.e. after the json_object is deleted) + * + * @param jso the object to customize + * @param to_string_func the custom serialization function + * @param userdata an optional opaque cookie + * @param user_delete an optional function from freeing userdata + */ +extern void json_object_set_serializer(json_object *jso, + json_object_to_json_string_fn to_string_func, + void *userdata, + json_object_delete_fn *user_delete); + +/** + * Simply call free on the userdata pointer. + * Can be used with json_object_set_serializer(). + * + * @param jso unused + * @param userdata the pointer that is passed to free(). + */ +json_object_delete_fn json_object_free_userdata; + +/** + * Copy the jso->_userdata string over to pb as-is. + * Can be used with json_object_set_serializer(). + * + * @param jso The object whose _userdata is used. + * @param pb The destination buffer. + * @param level Ignored. + * @param flags Ignored. + */ +json_object_to_json_string_fn json_object_userdata_to_json_string; + + +/* object type methods */ + +/** Create a new empty object with a reference count of 1. The caller of + * this object initially has sole ownership. Remember, when using + * json_object_object_add or json_object_array_put_idx, ownership will + * transfer to the object/array. Call json_object_get if you want to maintain + * shared ownership or also add this object as a child of multiple objects or + * arrays. Any ownerships you acquired but did not transfer must be released + * through json_object_put. + * + * @returns a json_object of type json_type_object + */ +extern struct json_object* json_object_new_object(void); + +/** Get the hashtable of a json_object of type json_type_object + * @param obj the json_object instance + * @returns a linkhash + */ +extern struct lh_table* json_object_get_object(struct json_object *obj); + +/** Get the size of an object in terms of the number of fields it has. + * @param obj the json_object whose length to return + */ +extern int json_object_object_length(struct json_object* obj); + +/** 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. + * + * 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. + * + * @param obj the json_object instance + * @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 + */ +extern void json_object_object_add(struct json_object* obj, const char *key, + struct json_object *val); + +/** Get the json_object associate with a given object field + * + * *No* reference counts will be changed. There is no need to manually adjust + * reference counts through the json_object_put/json_object_get methods unless + * you need to have the child (value) reference maintain a different lifetime + * than the owning parent (obj). Ownership of the returned value is retained + * by obj (do not do json_object_put unless you have done a json_object_get). + * If you delete the value from obj (json_object_object_del) and wish to access + * the returned reference afterwards, make sure you have first gotten shared + * ownership through json_object_get (& don't forget to do a json_object_put + * or transfer ownership to prevent a memory leak). + * + * @param obj the json_object instance + * @param key the object field name + * @returns the json_object associated with the given field name + * @deprecated Please use json_object_object_get_ex + */ +THIS_FUNCTION_IS_DEPRECATED(extern struct json_object* json_object_object_get(struct json_object* obj, + const char *key)); + +/** Get the json_object associated with a given object field. + * + * This returns true if the key is found, false in all other cases (including + * if obj isn't a json_type_object). + * + * *No* reference counts will be changed. There is no need to manually adjust + * reference counts through the json_object_put/json_object_get methods unless + * you need to have the child (value) reference maintain a different lifetime + * than the owning parent (obj). Ownership of value is retained by obj. + * + * @param obj the json_object instance + * @param key the object field name + * @param value a pointer where to store a reference to the json_object + * associated with the given field name. + * + * It is safe to pass a NULL value. + * @returns whether or not the key exists + */ +extern json_bool json_object_object_get_ex(struct json_object* obj, + const char *key, + struct json_object **value); + +/** Delete the given json_object field + * + * The reference count will be decremented for the deleted object. If there + * are no more owners of the value represented by this key, then the value is + * freed. Otherwise, the reference to the value will remain in memory. + * + * @param obj the json_object instance + * @param key the object field name + */ +extern void json_object_object_del(struct json_object* obj, const char *key); + +/** + * Iterate through all keys and values of an object. + * + * Adding keys to the object while iterating is NOT allowed. + * + * Deleting an existing key, or replacing an existing key with a + * new value IS allowed. + * + * @param obj the json_object instance + * @param key the local name for the char* key variable defined in the body + * @param val the local name for the json_object* object variable defined in + * the body + */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L + +# define json_object_object_foreach(obj,key,val) \ + char *key = NULL; \ + struct json_object *val __attribute__((__unused__)) = NULL; \ + for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \ + ({ if(entry ## key) { \ + key = (char*)entry ## key->k; \ + val = (struct json_object*)entry ## key->v; \ + entry_next ## key = entry ## key->next; \ + } ; entry ## key; }); \ + entry ## key = entry_next ## key ) + +#else /* ANSI C or MSC */ + +# define json_object_object_foreach(obj,key,val) \ + char *key;\ + struct json_object *val; \ + struct lh_entry *entry ## key; \ + struct lh_entry *entry_next ## key = NULL; \ + for(entry ## key = json_object_get_object(obj)->head; \ + (entry ## key ? ( \ + key = (char*)entry ## key->k, \ + val = (struct json_object*)entry ## key->v, \ + entry_next ## key = entry ## key->next, \ + entry ## key) : 0); \ + entry ## key = entry_next ## key) + +#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */ + +/** Iterate through all keys and values of an object (ANSI C Safe) + * @param obj the json_object instance + * @param iter the object iterator + */ +#define json_object_object_foreachC(obj,iter) \ + for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next) + +/* Array type methods */ + +/** Create a new empty json_object of type json_type_array + * @returns a json_object of type json_type_array + */ +extern struct json_object* json_object_new_array(void); + +/** Get the arraylist of a json_object of type json_type_array + * @param obj the json_object instance + * @returns an arraylist + */ +extern struct array_list* json_object_get_array(struct json_object *obj); + +/** Get the length of a json_object of type json_type_array + * @param obj the json_object instance + * @returns an int + */ +extern int json_object_array_length(struct json_object *obj); + +/** Sorts the elements of jso of type json_type_array +* +* Pointers to the json_object pointers will be passed as the two arguments +* to @sort_fn +* +* @param obj the json_object instance +* @param sort_fn a sorting function +*/ +extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)); + +/** Binary search a sorted array for a specified key object. + * + * It depends on your compare function what's sufficient as a key. + * Usually you create some dummy object with the parameter compared in + * it, to identify the right item you're actually looking for. + * + * @see json_object_array_sort() for hints on the compare function. + * + * @param key a dummy json_object with the right key + * @param jso the array object we're searching + * @param sort_fn the sort/compare function + * + * @return the wanted json_object instance + */ +extern struct json_object* json_object_array_bsearch( + const struct json_object *key, + const struct json_object *jso, + int (*sort_fn)(const void *, const void *)); + +/** Add an element to the end of a json_object of type json_type_array + * + * 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 you must wrap the passed object with json_object_get + * + * @param obj the json_object instance + * @param val the json_object to be added + */ +extern int json_object_array_add(struct json_object *obj, + struct json_object *val); + +/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) + * + * 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 you must wrap the passed object with json_object_get + * + * The reference count of a replaced object will be decremented. + * + * The array size will be automatically be expanded to the size of the + * index if the index is larger than the current size. + * + * @param obj the json_object instance + * @param idx the index to insert the element at + * @param val the json_object to be added + */ +extern int json_object_array_put_idx(struct json_object *obj, int idx, + struct json_object *val); + +/** Get the element at specificed index of the array (a json_object of type json_type_array) + * @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) + */ +extern struct json_object* json_object_array_get_idx(struct json_object *obj, + int idx); + +/* json_bool type methods */ + +/** Create a new empty json_object of type json_type_boolean + * @param b a json_bool TRUE or FALSE (1 or 0) + * @returns a json_object of type json_type_boolean + */ +extern struct json_object* json_object_new_boolean(json_bool b); + +/** Get the json_bool value of a json_object + * + * The type is coerced to a json_bool if the passed object is not a json_bool. + * integer and double objects will return FALSE if there value is zero + * or TRUE otherwise. If the passed object is a string it will return + * TRUE if it has a non zero length. If any other object type is passed + * TRUE will be returned if the object is not NULL. + * + * @param obj the json_object instance + * @returns a json_bool + */ +extern json_bool json_object_get_boolean(struct json_object *obj); + + +/* int type methods */ + +/** Create a new empty json_object of type json_type_int + * Note that values are stored as 64-bit values internally. + * To ensure the full range is maintained, use json_object_new_int64 instead. + * @param i the integer + * @returns a json_object of type json_type_int + */ +extern struct json_object* json_object_new_int(int32_t i); + + +/** Create a new empty json_object of type json_type_int + * @param i the integer + * @returns a json_object of type json_type_int + */ +extern struct json_object* json_object_new_int64(int64_t i); + + +/** Get the int value of a json_object + * + * The type is coerced to a int if the passed object is not a int. + * double objects will return their integer conversion. Strings will be + * parsed as an integer. If no conversion exists then 0 is returned + * and errno is set to EINVAL. null is equivalent to 0 (no error values set) + * + * Note that integers are stored internally as 64-bit values. + * If the value of too big or too small to fit into 32-bit, INT32_MAX or + * INT32_MIN are returned, respectively. + * + * @param obj the json_object instance + * @returns an int + */ +extern int32_t json_object_get_int(struct json_object *obj); + +/** Get the int value of a json_object + * + * The type is coerced to a int64 if the passed object is not a int64. + * double objects will return their int64 conversion. Strings will be + * parsed as an int64. If no conversion exists then 0 is returned. + * + * NOTE: Set errno to 0 directly before a call to this function to determine + * whether or not conversion was successful (it does not clear the value for + * you). + * + * @param obj the json_object instance + * @returns an int64 + */ +extern int64_t json_object_get_int64(struct json_object *obj); + + +/* double type methods */ + +/** Create a new empty json_object of type json_type_double + * @param d the double + * @returns a json_object of type json_type_double + */ +extern struct json_object* json_object_new_double(double d); + +/** + * Create a new json_object of type json_type_double, using + * the exact serialized representation of the value. + * + * This allows for numbers that would otherwise get displayed + * inefficiently (e.g. 12.3 => "12.300000000000001") to be + * serialized with the more convenient form. + * + * Note: this is used by json_tokener_parse_ex() to allow for + * an exact re-serialization of a parsed object. + * + * An equivalent sequence of calls is: + * @code + * jso = json_object_new_double(d); + * json_object_set_serializer(d, json_object_userdata_to_json_string, + * strdup(ds), json_object_free_userdata) + * @endcode + * + * @param d the numeric value of the double. + * @param ds the string representation of the double. This will be copied. + */ +extern struct json_object* json_object_new_double_s(double d, const char *ds); + +/** Get the double floating point value of a json_object + * + * The type is coerced to a double if the passed object is not a double. + * integer objects will return their double conversion. Strings will be + * parsed as a double. If no conversion exists then 0.0 is returned and + * errno is set to EINVAL. null is equivalent to 0 (no error values set) + * + * If the value is too big to fit in a double, then the value is set to + * the closest infinity with errno set to ERANGE. If strings cannot be + * converted to their double value, then EINVAL is set & NaN is returned. + * + * Arrays of length 0 are interpreted as 0 (with no error flags set). + * Arrays of length 1 are effectively cast to the equivalent object and + * converted using the above rules. All other arrays set the error to + * EINVAL & return NaN. + * + * NOTE: Set errno to 0 directly before a call to this function to + * determine whether or not conversion was successful (it does not clear + * the value for you). + * + * @param obj the json_object instance + * @returns a double floating point number + */ +extern double json_object_get_double(struct json_object *obj); + + +/* string type methods */ + +/** Create a new empty json_object of type json_type_string + * + * A copy of the string is made and the memory is managed by the json_object + * + * @param s the string + * @returns a json_object of type json_type_string + */ +extern struct json_object* json_object_new_string(const char *s); + +extern struct json_object* json_object_new_string_len(const char *s, int len); + +/** Get the string value of a json_object + * + * If the passed object is not of type json_type_string then the JSON + * representation of the object is returned. + * + * The returned string memory is managed by the json_object and will + * be freed when the reference count of the json_object drops to zero. + * + * @param obj the json_object instance + * @returns a string + */ +extern const char* json_object_get_string(struct json_object *obj); + +/** Get the string length of a json_object + * + * If the passed object is not of type json_type_string then zero + * will be returned. + * + * @param obj the json_object instance + * @returns int + */ +extern int json_object_get_string_len(struct json_object *obj); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/json_object_iterator.c b/json-c/src/json_object_iterator.c index 7066649..39dbc9b 100644 --- a/json-c/src/json_object_iterator.c +++ b/json-c/src/json_object_iterator.c @@ -1,168 +1,168 @@ -/** -******************************************************************************* -* @file json_object_iterator.c -* -* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. -* -* This library is free software; you can redistribute it and/or modify -* it under the terms of the MIT license. See COPYING for details. -* -* @brief json-c forces clients to use its private data -* structures for JSON Object iteration. This API -* implementation corrects that by abstracting the -* private json-c details. -* -******************************************************************************* -*/ - -#include - -#include "json.h" -#include "json_object_private.h" - -#include "json_object_iterator.h" - -/** - * How It Works - * - * For each JSON Object, json-c maintains a linked list of zero - * or more lh_entry (link-hash entry) structures inside the - * Object's link-hash table (lh_table). - * - * Each lh_entry structure on the JSON Object's linked list - * represents a single name/value pair. The "next" field of the - * last lh_entry in the list is set to NULL, which terminates - * the list. - * - * We represent a valid iterator that refers to an actual - * name/value pair via a pointer to the pair's lh_entry - * structure set as the iterator's opaque_ field. - * - * We follow json-c's current pair list representation by - * representing a valid "end" iterator (one that refers past the - * last pair) with a NULL value in the iterator's opaque_ field. - * - * A JSON Object without any pairs in it will have the "head" - * field of its lh_table structure set to NULL. For such an - * object, json_object_iter_begin will return an iterator with - * the opaque_ field set to NULL, which is equivalent to the - * "end" iterator. - * - * When iterating, we simply update the iterator's opaque_ field - * to point to the next lh_entry structure in the linked list. - * opaque_ will become NULL once we iterate past the last pair - * in the list, which makes the iterator equivalent to the "end" - * iterator. - */ - -/// Our current representation of the "end" iterator; -/// -/// @note May not always be NULL -static const void* kObjectEndIterValue = NULL; - -/** - * **************************************************************************** - */ -struct json_object_iterator -json_object_iter_begin(struct json_object* obj) -{ - struct json_object_iterator iter; - struct lh_table* pTable; - - /// @note json_object_get_object will return NULL if passed NULL - /// or a non-json_type_object instance - pTable = json_object_get_object(obj); - JASSERT(NULL != pTable); - - /// @note For a pair-less Object, head is NULL, which matches our - /// definition of the "end" iterator - iter.opaque_ = pTable->head; - return iter; -} - -/** - * **************************************************************************** - */ -struct json_object_iterator -json_object_iter_end(const struct json_object* obj) -{ - struct json_object_iterator iter; - - JASSERT(NULL != obj); - JASSERT(json_object_is_type(obj, json_type_object)); - - iter.opaque_ = kObjectEndIterValue; - - return iter; -} - -/** - * **************************************************************************** - */ -void -json_object_iter_next(struct json_object_iterator* iter) -{ - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); - - iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next; -} - - -/** - * **************************************************************************** - */ -const char* -json_object_iter_peek_name(const struct json_object_iterator* iter) -{ - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); - - return (const char*)(((struct lh_entry *)iter->opaque_)->k); -} - - -/** - * **************************************************************************** - */ -struct json_object* -json_object_iter_peek_value(const struct json_object_iterator* iter) -{ - JASSERT(NULL != iter); - JASSERT(kObjectEndIterValue != iter->opaque_); - - return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v); -} - - -/** - * **************************************************************************** - */ -json_bool -json_object_iter_equal(const struct json_object_iterator* iter1, - const struct json_object_iterator* iter2) -{ - JASSERT(NULL != iter1); - JASSERT(NULL != iter2); - - return (iter1->opaque_ == iter2->opaque_); -} - - -/** - * **************************************************************************** - */ -struct json_object_iterator -json_object_iter_init_default(void) -{ - struct json_object_iterator iter; - - /** - * @note Make this a negative, invalid value, such that - * accidental access to it would likely be trapped by the - * hardware as an invalid address. - */ - iter.opaque_ = NULL; - - return iter; -} +/** +******************************************************************************* +* @file json_object_iterator.c +* +* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. +* +* This library is free software; you can redistribute it and/or modify +* it under the terms of the MIT license. See COPYING for details. +* +* @brief json-c forces clients to use its private data +* structures for JSON Object iteration. This API +* implementation corrects that by abstracting the +* private json-c details. +* +******************************************************************************* +*/ + +#include + +#include "json.h" +#include "json_object_private.h" + +#include "json_object_iterator.h" + +/** + * How It Works + * + * For each JSON Object, json-c maintains a linked list of zero + * or more lh_entry (link-hash entry) structures inside the + * Object's link-hash table (lh_table). + * + * Each lh_entry structure on the JSON Object's linked list + * represents a single name/value pair. The "next" field of the + * last lh_entry in the list is set to NULL, which terminates + * the list. + * + * We represent a valid iterator that refers to an actual + * name/value pair via a pointer to the pair's lh_entry + * structure set as the iterator's opaque_ field. + * + * We follow json-c's current pair list representation by + * representing a valid "end" iterator (one that refers past the + * last pair) with a NULL value in the iterator's opaque_ field. + * + * A JSON Object without any pairs in it will have the "head" + * field of its lh_table structure set to NULL. For such an + * object, json_object_iter_begin will return an iterator with + * the opaque_ field set to NULL, which is equivalent to the + * "end" iterator. + * + * When iterating, we simply update the iterator's opaque_ field + * to point to the next lh_entry structure in the linked list. + * opaque_ will become NULL once we iterate past the last pair + * in the list, which makes the iterator equivalent to the "end" + * iterator. + */ + +/// Our current representation of the "end" iterator; +/// +/// @note May not always be NULL +static const void* kObjectEndIterValue = NULL; + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_begin(struct json_object* obj) +{ + struct json_object_iterator iter; + struct lh_table* pTable; + + /// @note json_object_get_object will return NULL if passed NULL + /// or a non-json_type_object instance + pTable = json_object_get_object(obj); + JASSERT(NULL != pTable); + + /// @note For a pair-less Object, head is NULL, which matches our + /// definition of the "end" iterator + iter.opaque_ = pTable->head; + return iter; +} + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_end(const struct json_object* obj) +{ + struct json_object_iterator iter; + + JASSERT(NULL != obj); + JASSERT(json_object_is_type(obj, json_type_object)); + + iter.opaque_ = kObjectEndIterValue; + + return iter; +} + +/** + * **************************************************************************** + */ +void +json_object_iter_next(struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next; +} + + +/** + * **************************************************************************** + */ +const char* +json_object_iter_peek_name(const struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + return (const char*)(((struct lh_entry *)iter->opaque_)->k); +} + + +/** + * **************************************************************************** + */ +struct json_object* +json_object_iter_peek_value(const struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v); +} + + +/** + * **************************************************************************** + */ +json_bool +json_object_iter_equal(const struct json_object_iterator* iter1, + const struct json_object_iterator* iter2) +{ + JASSERT(NULL != iter1); + JASSERT(NULL != iter2); + + return (iter1->opaque_ == iter2->opaque_); +} + + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_init_default(void) +{ + struct json_object_iterator iter; + + /** + * @note Make this a negative, invalid value, such that + * accidental access to it would likely be trapped by the + * hardware as an invalid address. + */ + iter.opaque_ = NULL; + + return iter; +} diff --git a/json-c/src/json_object_iterator.h b/json-c/src/json_object_iterator.h index f6e7ca6..2f21881 100644 --- a/json-c/src/json_object_iterator.h +++ b/json-c/src/json_object_iterator.h @@ -1,239 +1,239 @@ -/** -******************************************************************************* -* @file json_object_iterator.h -* -* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. -* -* This library is free software; you can redistribute it and/or modify -* it under the terms of the MIT license. See COPYING for details. -* -* @brief json-c forces clients to use its private data -* structures for JSON Object iteration. This API -* corrects that by abstracting the private json-c -* details. -* -* API attributes:
    -* * Thread-safe: NO
    -* * Reentrant: NO -* -******************************************************************************* -*/ - - -#ifndef JSON_OBJECT_ITERATOR_H -#define JSON_OBJECT_ITERATOR_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Forward declaration for the opaque iterator information. - */ -struct json_object_iter_info_; - -/** - * The opaque iterator that references a name/value pair within - * a JSON Object instance or the "end" iterator value. - */ -struct json_object_iterator { - const void* opaque_; -}; - - -/** - * forward declaration of json-c's JSON value instance structure - */ -struct json_object; - - -/** - * Initializes an iterator structure to a "default" value that - * is convenient for initializing an iterator variable to a - * default state (e.g., initialization list in a class' - * constructor). - * - * @code - * struct json_object_iterator iter = json_object_iter_init_default(); - * MyClass() : iter_(json_object_iter_init_default()) - * @endcode - * - * @note The initialized value doesn't reference any specific - * pair, is considered an invalid iterator, and MUST NOT - * be passed to any json-c API that expects a valid - * iterator. - * - * @note User and internal code MUST NOT make any assumptions - * about and dependencies on the value of the "default" - * iterator value. - * - * @return json_object_iterator - */ -struct json_object_iterator -json_object_iter_init_default(void); - -/** Retrieves an iterator to the first pair of the JSON Object. - * - * @warning Any modification of the underlying pair invalidates all - * iterators to that pair. - * - * @param obj JSON Object instance (MUST be of type json_object) - * - * @return json_object_iterator If the JSON Object has at - * least one pair, on return, the iterator refers - * to the first pair. If the JSON Object doesn't - * have any pairs, the returned iterator is - * equivalent to the "end" iterator for the same - * JSON Object instance. - * - * @code - * struct json_object_iterator it; - * struct json_object_iterator itEnd; - * struct json_object* obj; - * - * obj = json_tokener_parse("{'first':'george', 'age':100}"); - * it = json_object_iter_begin(obj); - * itEnd = json_object_iter_end(obj); - * - * while (!json_object_iter_equal(&it, &itEnd)) { - * printf("%s\n", - * json_object_iter_peek_name(&it)); - * json_object_iter_next(&it); - * } - * - * @endcode - */ -struct json_object_iterator -json_object_iter_begin(struct json_object* obj); - -/** Retrieves the iterator that represents the position beyond the - * last pair of the given JSON Object instance. - * - * @warning Do NOT write code that assumes that the "end" - * iterator value is NULL, even if it is so in a - * particular instance of the implementation. - * - * @note The reason we do not (and MUST NOT) provide - * "json_object_iter_is_end(json_object_iterator* iter)" - * type of API is because it would limit the underlying - * representation of name/value containment (or force us - * to add additional, otherwise unnecessary, fields to - * the iterator structure). The "end" iterator and the - * equality test method, on the other hand, permit us to - * cleanly abstract pretty much any reasonable underlying - * representation without burdening the iterator - * structure with unnecessary data. - * - * @note For performance reasons, memorize the "end" iterator prior - * to any loop. - * - * @param obj JSON Object instance (MUST be of type json_object) - * - * @return json_object_iterator On return, the iterator refers - * to the "end" of the Object instance's pairs - * (i.e., NOT the last pair, but "beyond the last - * pair" value) - */ -struct json_object_iterator -json_object_iter_end(const struct json_object* obj); - -/** Returns an iterator to the next pair, if any - * - * @warning Any modification of the underlying pair - * invalidates all iterators to that pair. - * - * @param iter [IN/OUT] Pointer to iterator that references a - * name/value pair; MUST be a valid, non-end iterator. - * WARNING: bad things will happen if invalid or "end" - * iterator is passed. Upon return will contain the - * reference to the next pair if there is one; if there - * are no more pairs, will contain the "end" iterator - * value, which may be compared against the return value - * of json_object_iter_end() for the same JSON Object - * instance. - */ -void -json_object_iter_next(struct json_object_iterator* iter); - - -/** Returns a const pointer to the name of the pair referenced - * by the given iterator. - * - * @param iter pointer to iterator that references a name/value - * pair; MUST be a valid, non-end iterator. - * - * @warning bad things will happen if an invalid or - * "end" iterator is passed. - * - * @return const char* Pointer to the name of the referenced - * name/value pair. The name memory belongs to the - * name/value pair, will be freed when the pair is - * deleted or modified, and MUST NOT be modified or - * freed by the user. - */ -const char* -json_object_iter_peek_name(const struct json_object_iterator* iter); - - -/** Returns a pointer to the json-c instance representing the - * value of the referenced name/value pair, without altering - * the instance's reference count. - * - * @param iter pointer to iterator that references a name/value - * pair; MUST be a valid, non-end iterator. - * - * @warning bad things will happen if invalid or - * "end" iterator is passed. - * - * @return struct json_object* Pointer to the json-c value - * instance of the referenced name/value pair; the - * value's reference count is not changed by this - * function: if you plan to hold on to this json-c node, - * take a look at json_object_get() and - * json_object_put(). IMPORTANT: json-c API represents - * the JSON Null value as a NULL json_object instance - * pointer. - */ -struct json_object* -json_object_iter_peek_value(const struct json_object_iterator* iter); - - -/** Tests two iterators for equality. Typically used to test - * for end of iteration by comparing an iterator to the - * corresponding "end" iterator (that was derived from the same - * JSON Object instance). - * - * @note The reason we do not (and MUST NOT) provide - * "json_object_iter_is_end(json_object_iterator* iter)" - * type of API is because it would limit the underlying - * representation of name/value containment (or force us - * to add additional, otherwise unnecessary, fields to - * the iterator structure). The equality test method, on - * the other hand, permits us to cleanly abstract pretty - * much any reasonable underlying representation. - * - * @param iter1 Pointer to first valid, non-NULL iterator - * @param iter2 POinter to second valid, non-NULL iterator - * - * @warning if a NULL iterator pointer or an uninitialized - * or invalid iterator, or iterators derived from - * different JSON Object instances are passed, bad things - * will happen! - * - * @return json_bool non-zero if iterators are equal (i.e., both - * reference the same name/value pair or are both at - * "end"); zero if they are not equal. - */ -json_bool -json_object_iter_equal(const struct json_object_iterator* iter1, - const struct json_object_iterator* iter2); - - -#ifdef __cplusplus -} -#endif - - -#endif // JSON_OBJECT_ITERATOR_H +/** +******************************************************************************* +* @file json_object_iterator.h +* +* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. +* +* This library is free software; you can redistribute it and/or modify +* it under the terms of the MIT license. See COPYING for details. +* +* @brief json-c forces clients to use its private data +* structures for JSON Object iteration. This API +* corrects that by abstracting the private json-c +* details. +* +* API attributes:
    +* * Thread-safe: NO
    +* * Reentrant: NO +* +******************************************************************************* +*/ + + +#ifndef JSON_OBJECT_ITERATOR_H +#define JSON_OBJECT_ITERATOR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Forward declaration for the opaque iterator information. + */ +struct json_object_iter_info_; + +/** + * The opaque iterator that references a name/value pair within + * a JSON Object instance or the "end" iterator value. + */ +struct json_object_iterator { + const void* opaque_; +}; + + +/** + * forward declaration of json-c's JSON value instance structure + */ +struct json_object; + + +/** + * Initializes an iterator structure to a "default" value that + * is convenient for initializing an iterator variable to a + * default state (e.g., initialization list in a class' + * constructor). + * + * @code + * struct json_object_iterator iter = json_object_iter_init_default(); + * MyClass() : iter_(json_object_iter_init_default()) + * @endcode + * + * @note The initialized value doesn't reference any specific + * pair, is considered an invalid iterator, and MUST NOT + * be passed to any json-c API that expects a valid + * iterator. + * + * @note User and internal code MUST NOT make any assumptions + * about and dependencies on the value of the "default" + * iterator value. + * + * @return json_object_iterator + */ +struct json_object_iterator +json_object_iter_init_default(void); + +/** Retrieves an iterator to the first pair of the JSON Object. + * + * @warning Any modification of the underlying pair invalidates all + * iterators to that pair. + * + * @param obj JSON Object instance (MUST be of type json_object) + * + * @return json_object_iterator If the JSON Object has at + * least one pair, on return, the iterator refers + * to the first pair. If the JSON Object doesn't + * have any pairs, the returned iterator is + * equivalent to the "end" iterator for the same + * JSON Object instance. + * + * @code + * struct json_object_iterator it; + * struct json_object_iterator itEnd; + * struct json_object* obj; + * + * obj = json_tokener_parse("{'first':'george', 'age':100}"); + * it = json_object_iter_begin(obj); + * itEnd = json_object_iter_end(obj); + * + * while (!json_object_iter_equal(&it, &itEnd)) { + * printf("%s\n", + * json_object_iter_peek_name(&it)); + * json_object_iter_next(&it); + * } + * + * @endcode + */ +struct json_object_iterator +json_object_iter_begin(struct json_object* obj); + +/** Retrieves the iterator that represents the position beyond the + * last pair of the given JSON Object instance. + * + * @warning Do NOT write code that assumes that the "end" + * iterator value is NULL, even if it is so in a + * particular instance of the implementation. + * + * @note The reason we do not (and MUST NOT) provide + * "json_object_iter_is_end(json_object_iterator* iter)" + * type of API is because it would limit the underlying + * representation of name/value containment (or force us + * to add additional, otherwise unnecessary, fields to + * the iterator structure). The "end" iterator and the + * equality test method, on the other hand, permit us to + * cleanly abstract pretty much any reasonable underlying + * representation without burdening the iterator + * structure with unnecessary data. + * + * @note For performance reasons, memorize the "end" iterator prior + * to any loop. + * + * @param obj JSON Object instance (MUST be of type json_object) + * + * @return json_object_iterator On return, the iterator refers + * to the "end" of the Object instance's pairs + * (i.e., NOT the last pair, but "beyond the last + * pair" value) + */ +struct json_object_iterator +json_object_iter_end(const struct json_object* obj); + +/** Returns an iterator to the next pair, if any + * + * @warning Any modification of the underlying pair + * invalidates all iterators to that pair. + * + * @param iter [IN/OUT] Pointer to iterator that references a + * name/value pair; MUST be a valid, non-end iterator. + * WARNING: bad things will happen if invalid or "end" + * iterator is passed. Upon return will contain the + * reference to the next pair if there is one; if there + * are no more pairs, will contain the "end" iterator + * value, which may be compared against the return value + * of json_object_iter_end() for the same JSON Object + * instance. + */ +void +json_object_iter_next(struct json_object_iterator* iter); + + +/** Returns a const pointer to the name of the pair referenced + * by the given iterator. + * + * @param iter pointer to iterator that references a name/value + * pair; MUST be a valid, non-end iterator. + * + * @warning bad things will happen if an invalid or + * "end" iterator is passed. + * + * @return const char* Pointer to the name of the referenced + * name/value pair. The name memory belongs to the + * name/value pair, will be freed when the pair is + * deleted or modified, and MUST NOT be modified or + * freed by the user. + */ +const char* +json_object_iter_peek_name(const struct json_object_iterator* iter); + + +/** Returns a pointer to the json-c instance representing the + * value of the referenced name/value pair, without altering + * the instance's reference count. + * + * @param iter pointer to iterator that references a name/value + * pair; MUST be a valid, non-end iterator. + * + * @warning bad things will happen if invalid or + * "end" iterator is passed. + * + * @return struct json_object* Pointer to the json-c value + * instance of the referenced name/value pair; the + * value's reference count is not changed by this + * function: if you plan to hold on to this json-c node, + * take a look at json_object_get() and + * json_object_put(). IMPORTANT: json-c API represents + * the JSON Null value as a NULL json_object instance + * pointer. + */ +struct json_object* +json_object_iter_peek_value(const struct json_object_iterator* iter); + + +/** Tests two iterators for equality. Typically used to test + * for end of iteration by comparing an iterator to the + * corresponding "end" iterator (that was derived from the same + * JSON Object instance). + * + * @note The reason we do not (and MUST NOT) provide + * "json_object_iter_is_end(json_object_iterator* iter)" + * type of API is because it would limit the underlying + * representation of name/value containment (or force us + * to add additional, otherwise unnecessary, fields to + * the iterator structure). The equality test method, on + * the other hand, permits us to cleanly abstract pretty + * much any reasonable underlying representation. + * + * @param iter1 Pointer to first valid, non-NULL iterator + * @param iter2 POinter to second valid, non-NULL iterator + * + * @warning if a NULL iterator pointer or an uninitialized + * or invalid iterator, or iterators derived from + * different JSON Object instances are passed, bad things + * will happen! + * + * @return json_bool non-zero if iterators are equal (i.e., both + * reference the same name/value pair or are both at + * "end"); zero if they are not equal. + */ +json_bool +json_object_iter_equal(const struct json_object_iterator* iter1, + const struct json_object_iterator* iter2); + + +#ifdef __cplusplus +} +#endif + + +#endif /* JSON_OBJECT_ITERATOR_H */ diff --git a/json-c/src/json_object_private.h b/json-c/src/json_object_private.h index 112ce76..6c13187 100644 --- a/json-c/src/json_object_private.h +++ b/json-c/src/json_object_private.h @@ -1,47 +1,47 @@ -/* - * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _json_object_private_h_ -#define _json_object_private_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (json_object_delete_fn)(struct json_object *o); -typedef int (json_object_to_json_string_fn)(struct json_object *o, - struct printbuf *pb); - -struct json_object -{ - enum json_type o_type; - json_object_delete_fn *_delete; - json_object_to_json_string_fn *_to_json_string; - int _ref_count; - struct printbuf *_pb; - union data { - json_bool c_boolean; - double c_double; - int64_t c_int64; - struct lh_table *c_object; - struct array_list *c_array; - struct { - char *str; - int len; - } c_string; - } o; -}; - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_object_private_h_ +#define _json_object_private_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (json_object_private_delete_fn)(struct json_object *o); + +struct json_object +{ + enum json_type o_type; + json_object_private_delete_fn *_delete; + json_object_to_json_string_fn *_to_json_string; + int _ref_count; + struct printbuf *_pb; + union data { + json_bool c_boolean; + double c_double; + int64_t c_int64; + struct lh_table *c_object; + struct array_list *c_array; + struct { + char *str; + int len; + } c_string; + } o; + json_object_delete_fn *_user_delete; + void *_userdata; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/json_tokener.c b/json-c/src/json_tokener.c index 1c82484..63172f9 100644 --- a/json-c/src/json_tokener.c +++ b/json-c/src/json_tokener.c @@ -1,733 +1,923 @@ -/* - * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - * - * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. - * The copyrights to the contents of this file are licensed under the MIT License - * (http://www.opensource.org/licenses/mit-license.php) - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "bits.h" -#include "debug.h" -#include "printbuf.h" -#include "arraylist.h" -#include "json_inttypes.h" -#include "json_object.h" -#include "json_tokener.h" -#include "json_util.h" - -#if !HAVE_STRNCASECMP && defined(_MSC_VER) - /* MSC has the version as _strnicmp */ -# define strncasecmp _strnicmp -#elif !HAVE_STRNCASECMP -# error You do not have strncasecmp on your system. -#endif /* HAVE_STRNCASECMP */ - - -static const char* json_null_str = "null"; -static const char* json_true_str = "true"; -static const char* json_false_str = "false"; - -// XXX after v0.10 this array will become static: -const char* json_tokener_errors[] = { - "success", - "continue", - "nesting too deep", - "unexpected end of data", - "unexpected character", - "null expected", - "boolean expected", - "number expected", - "array value separator ',' expected", - "quoted object property name expected", - "object property name separator ':' expected", - "object value separator ',' expected", - "invalid string sequence", - "expected comment", -}; - -const char *json_tokener_error_desc(enum json_tokener_error jerr) -{ - if (jerr < 0 || jerr > sizeof(json_tokener_errors)) - return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()"; - return json_tokener_errors[jerr]; -} - -enum json_tokener_error json_tokener_get_error(json_tokener *tok) -{ - return tok->err; -} - -/* Stuff for decoding unicode sequences */ -#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800) -#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00) -#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000) -static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD }; - - -struct json_tokener* json_tokener_new(void) -{ - struct json_tokener *tok; - - tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener)); - if (!tok) return NULL; - tok->pb = printbuf_new(); - json_tokener_reset(tok); - return tok; -} - -void json_tokener_free(struct json_tokener *tok) -{ - json_tokener_reset(tok); - if(tok) printbuf_free(tok->pb); - free(tok); -} - -static void json_tokener_reset_level(struct json_tokener *tok, int depth) -{ - tok->stack[depth].state = json_tokener_state_eatws; - tok->stack[depth].saved_state = json_tokener_state_start; - json_object_put(tok->stack[depth].current); - tok->stack[depth].current = NULL; - free(tok->stack[depth].obj_field_name); - tok->stack[depth].obj_field_name = NULL; -} - -void json_tokener_reset(struct json_tokener *tok) -{ - int i; - if (!tok) - return; - - for(i = tok->depth; i >= 0; i--) - json_tokener_reset_level(tok, i); - tok->depth = 0; - tok->err = json_tokener_success; -} - -struct json_object* json_tokener_parse(const char *str) -{ - enum json_tokener_error jerr_ignored; - struct json_object* obj; - obj = json_tokener_parse_verbose(str, &jerr_ignored); - return obj; -} - -struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error) -{ - struct json_tokener* tok; - struct json_object* obj; - - tok = json_tokener_new(); - if (!tok) - return NULL; - obj = json_tokener_parse_ex(tok, str, -1); - *error = tok->err; - if(tok->err != json_tokener_success) { - if (obj != NULL) - json_object_put(obj); - obj = NULL; - } - - json_tokener_free(tok); - return obj; -} - - -#if !HAVE_STRNDUP -/* CAW: compliant version of strndup() */ -char* strndup(const char* str, size_t n) -{ - if(str) { - size_t len = strlen(str); - size_t nn = json_min(len,n); - char* s = (char*)malloc(sizeof(char) * (nn + 1)); - - if(s) { - memcpy(s, str, nn); - s[nn] = '\0'; - } - - return s; - } - - return NULL; -} -#endif - - -#define state tok->stack[tok->depth].state -#define saved_state tok->stack[tok->depth].saved_state -#define current tok->stack[tok->depth].current -#define obj_field_name tok->stack[tok->depth].obj_field_name - -/* Optimization: - * json_tokener_parse_ex() consumed a lot of CPU in its main loop, - * iterating character-by character. A large performance boost is - * achieved by using tighter loops to locally handle units such as - * comments and strings. Loops that handle an entire token within - * their scope also gather entire strings and pass them to - * printbuf_memappend() in a single call, rather than calling - * printbuf_memappend() one char at a time. - * - * POP_CHAR() and ADVANCE_CHAR() macros are used for code that is - * common to both the main loop and the tighter loops. - */ - -/* POP_CHAR(dest, tok) macro: - * Not really a pop()...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 - */ -#define POP_CHAR(dest, tok) \ - (((tok)->char_offset == len) ? \ - (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \ - (((tok)->err = json_tokener_success), 0) \ - : \ - (((tok)->err = json_tokener_continue), 0) \ - ) : \ - (((dest) = *str), 1) \ - ) - -/* ADVANCE_CHAR() macro: - * Incrementes str & tok->char_offset. - * For convenience of existing conditionals, returns the old value of c (0 on eof) - * Implicit inputs: c var - */ -#define ADVANCE_CHAR(str, tok) \ - ( ++(str), ((tok)->char_offset)++, c) - - -/* End optimization macro defs */ - - -struct json_object* json_tokener_parse_ex(struct json_tokener *tok, - const char *str, int len) -{ - struct json_object *obj = NULL; - char c = '\1'; - - tok->char_offset = 0; - tok->err = json_tokener_success; - - while (POP_CHAR(c, tok)) { - - redo_char: - switch(state) { - - case json_tokener_state_eatws: - /* Advance until we change state */ - while (isspace((int)c)) { - if ((!ADVANCE_CHAR(str, tok)) || (!POP_CHAR(c, tok))) - goto out; - } - if(c == '/') { - printbuf_reset(tok->pb); - printbuf_memappend_fast(tok->pb, &c, 1); - state = json_tokener_state_comment_start; - } else { - state = saved_state; - goto redo_char; - } - break; - - case json_tokener_state_start: - switch(c) { - case '{': - state = json_tokener_state_eatws; - saved_state = json_tokener_state_object_field_start; - current = json_object_new_object(); - break; - case '[': - state = json_tokener_state_eatws; - saved_state = json_tokener_state_array; - current = json_object_new_array(); - break; - case 'N': - case 'n': - state = json_tokener_state_null; - printbuf_reset(tok->pb); - tok->st_pos = 0; - goto redo_char; - case '"': - case '\'': - state = json_tokener_state_string; - printbuf_reset(tok->pb); - tok->quote_char = c; - break; - case 'T': - case 't': - case 'F': - case 'f': - state = json_tokener_state_boolean; - printbuf_reset(tok->pb); - tok->st_pos = 0; - goto redo_char; -#if defined(__GNUC__) - case '0' ... '9': -#else - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': -#endif - case '-': - state = json_tokener_state_number; - printbuf_reset(tok->pb); - tok->is_double = 0; - goto redo_char; - default: - tok->err = json_tokener_error_parse_unexpected; - goto out; - } - break; - - case json_tokener_state_finish: - if(tok->depth == 0) goto out; - obj = json_object_get(current); - json_tokener_reset_level(tok, tok->depth); - tok->depth--; - goto redo_char; - - case json_tokener_state_null: - printbuf_memappend_fast(tok->pb, &c, 1); - if(strncasecmp(json_null_str, tok->pb->buf, - json_min(tok->st_pos+1, strlen(json_null_str))) == 0) { - if(tok->st_pos == strlen(json_null_str)) { - current = NULL; - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } else { - tok->err = json_tokener_error_parse_null; - goto out; - } - tok->st_pos++; - break; - - case json_tokener_state_comment_start: - if(c == '*') { - state = json_tokener_state_comment; - } else if(c == '/') { - state = json_tokener_state_comment_eol; - } else { - tok->err = json_tokener_error_parse_comment; - goto out; - } - printbuf_memappend_fast(tok->pb, &c, 1); - break; - - case json_tokener_state_comment: - { - /* Advance until we change state */ - const char *case_start = str; - while(c != '*') { - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start); - state = json_tokener_state_comment_end; - } - break; - - case json_tokener_state_comment_eol: - { - /* Advance until we change state */ - const char *case_start = str; - while(c != '\n') { - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); - state = json_tokener_state_eatws; - } - break; - - case json_tokener_state_comment_end: - printbuf_memappend_fast(tok->pb, &c, 1); - if(c == '/') { - MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); - state = json_tokener_state_eatws; - } else { - state = json_tokener_state_comment; - } - break; - - case json_tokener_state_string: - { - /* Advance until we change state */ - const char *case_start = str; - while(1) { - if(c == tok->quote_char) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - current = json_object_new_string(tok->pb->buf); - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - break; - } else if(c == '\\') { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - saved_state = json_tokener_state_string; - state = json_tokener_state_string_escape; - break; - } - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - } - break; - - case json_tokener_state_string_escape: - switch(c) { - case '"': - case '\\': - case '/': - printbuf_memappend_fast(tok->pb, &c, 1); - state = saved_state; - break; - case 'b': - case 'n': - case 'r': - case 't': - if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1); - else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1); - else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1); - else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1); - state = saved_state; - break; - case 'u': - tok->ucs_char = 0; - tok->st_pos = 0; - state = json_tokener_state_escape_unicode; - break; - default: - tok->err = json_tokener_error_parse_string; - goto out; - } - 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 */ - while(1) { - if(strchr(json_hex_chars, c)) { - tok->ucs_char += ((unsigned int)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 - * 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 ((tok->char_offset+1 != len) && - (tok->char_offset+2 != len) && - (str[1] == '\\') && - (str[2] == 'u')) - { - ADVANCE_CHAR(str, tok); - ADVANCE_CHAR(str, tok); - - /* Advance to the first char of the next sequence and - * continue processing with the next sequence. - */ - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - goto out; - } - tok->ucs_char = 0; - tok->st_pos = 0; - continue; /* other json_tokener_state_escape_unicode */ - } 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 { - tok->err = json_tokener_error_parse_string; - goto out; - } - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - if (got_hi_surrogate) /* Clean up any pending chars */ - printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); - goto out; - } - } - } - break; - - case json_tokener_state_boolean: - printbuf_memappend_fast(tok->pb, &c, 1); - if(strncasecmp(json_true_str, tok->pb->buf, - json_min(tok->st_pos+1, strlen(json_true_str))) == 0) { - if(tok->st_pos == strlen(json_true_str)) { - current = json_object_new_boolean(1); - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } else if(strncasecmp(json_false_str, tok->pb->buf, - json_min(tok->st_pos+1, strlen(json_false_str))) == 0) { - if(tok->st_pos == strlen(json_false_str)) { - current = json_object_new_boolean(0); - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - } else { - tok->err = json_tokener_error_parse_boolean; - goto out; - } - tok->st_pos++; - break; - - case json_tokener_state_number: - { - /* Advance until we change state */ - const char *case_start = str; - int case_len=0; - while(c && strchr(json_number_chars, c)) { - ++case_len; - if(c == '.' || c == 'e' || c == 'E') - tok->is_double = 1; - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, case_len); - goto out; - } - } - if (case_len>0) - printbuf_memappend_fast(tok->pb, case_start, case_len); - } - { - int64_t num64; - double numd; - if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { - current = json_object_new_int64(num64); - } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) { - current = json_object_new_double(numd); - } else { - tok->err = json_tokener_error_parse_number; - goto out; - } - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - goto redo_char; - } - break; - - case json_tokener_state_array: - if(c == ']') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else { - if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) { - tok->err = json_tokener_error_depth; - goto out; - } - state = json_tokener_state_array_add; - tok->depth++; - json_tokener_reset_level(tok, tok->depth); - goto redo_char; - } - break; - - case json_tokener_state_array_add: - json_object_array_add(current, obj); - saved_state = json_tokener_state_array_sep; - state = json_tokener_state_eatws; - goto redo_char; - - case json_tokener_state_array_sep: - if(c == ']') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if(c == ',') { - saved_state = json_tokener_state_array; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_array; - goto out; - } - break; - - case json_tokener_state_object_field_start: - if(c == '}') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if (c == '"' || c == '\'') { - tok->quote_char = c; - printbuf_reset(tok->pb); - state = json_tokener_state_object_field; - } else { - tok->err = json_tokener_error_parse_object_key_name; - goto out; - } - break; - - case json_tokener_state_object_field: - { - /* Advance until we change state */ - const char *case_start = str; - while(1) { - if(c == tok->quote_char) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - obj_field_name = strdup(tok->pb->buf); - saved_state = json_tokener_state_object_field_end; - state = json_tokener_state_eatws; - break; - } else if(c == '\\') { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - saved_state = json_tokener_state_object_field; - state = json_tokener_state_string_escape; - break; - } - if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) { - printbuf_memappend_fast(tok->pb, case_start, str-case_start); - goto out; - } - } - } - break; - - case json_tokener_state_object_field_end: - if(c == ':') { - saved_state = json_tokener_state_object_value; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_object_key_sep; - goto out; - } - break; - - case json_tokener_state_object_value: - if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) { - tok->err = json_tokener_error_depth; - goto out; - } - state = json_tokener_state_object_value_add; - tok->depth++; - json_tokener_reset_level(tok, tok->depth); - goto redo_char; - - case json_tokener_state_object_value_add: - json_object_object_add(current, obj_field_name, obj); - free(obj_field_name); - obj_field_name = NULL; - saved_state = json_tokener_state_object_sep; - state = json_tokener_state_eatws; - goto redo_char; - - case json_tokener_state_object_sep: - if(c == '}') { - saved_state = json_tokener_state_finish; - state = json_tokener_state_eatws; - } else if(c == ',') { - saved_state = json_tokener_state_object_field_start; - state = json_tokener_state_eatws; - } else { - tok->err = json_tokener_error_parse_object_value_sep; - goto out; - } - break; - - } - if (!ADVANCE_CHAR(str, tok)) - goto out; - } /* while(POP_CHAR) */ - - out: - if (!c) { /* We hit an eof char (0) */ - if(state != json_tokener_state_finish && - saved_state != json_tokener_state_finish) - tok->err = json_tokener_error_parse_eof; - } - - if (tok->err == json_tokener_success) - { - json_object *ret = json_object_get(current); - int ii; - - /* Partially reset, so we parse additional objects on subsequent calls. */ - for(ii = tok->depth; ii >= 0; ii--) - json_tokener_reset_level(tok, ii); - return ret; - } - - MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", - json_tokener_errors[tok->err], tok->char_offset); - return NULL; -} +/* + * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#include "config.h" + +#include +#include "math_compat.h" +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "printbuf.h" +#include "arraylist.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +#ifdef HAVE_LOCALE_H +#include +#endif /* HAVE_LOCALE_H */ + +#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) + +#if !HAVE_STRDUP && defined(_MSC_VER) + /* MSC has the version as _strdup */ +# define strdup _strdup +#elif !HAVE_STRDUP +# error You do not have strdup on your system. +#endif /* HAVE_STRDUP */ + +#if !HAVE_STRNCASECMP && defined(_MSC_VER) + /* MSC has the version as _strnicmp */ +# define strncasecmp _strnicmp +#elif !HAVE_STRNCASECMP +# error You do not have strncasecmp on your system. +#endif /* HAVE_STRNCASECMP */ + +/* Use C99 NAN by default; if not available, nan("") should work too. */ +#ifndef NAN +#define NAN nan("") +#endif /* !NAN */ + +static const char json_null_str[] = "null"; +static const int json_null_str_len = sizeof(json_null_str) - 1; +static const char json_inf_str[] = "Infinity"; +static const int json_inf_str_len = sizeof(json_inf_str) - 1; +static const char json_nan_str[] = "NaN"; +static const int json_nan_str_len = sizeof(json_nan_str) - 1; +static const char json_true_str[] = "true"; +static const int json_true_str_len = sizeof(json_true_str) - 1; +static const char json_false_str[] = "false"; +static const int json_false_str_len = sizeof(json_false_str) - 1; + +static const char* json_tokener_errors[] = { + "success", + "continue", + "nesting too deep", + "unexpected end of data", + "unexpected character", + "null expected", + "boolean expected", + "number expected", + "array value separator ',' expected", + "quoted object property name expected", + "object property name separator ':' expected", + "object value separator ',' expected", + "invalid string sequence", + "expected comment", + "buffer size overflow" +}; + +const char *json_tokener_error_desc(enum json_tokener_error jerr) +{ + int jerr_int = (int)jerr; + if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0]))) + return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()"; + return json_tokener_errors[jerr]; +} + +enum json_tokener_error json_tokener_get_error(json_tokener *tok) +{ + return tok->err; +} + +/* Stuff for decoding unicode sequences */ +#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800) +#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00) +#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000) +static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD }; + +struct json_tokener* json_tokener_new_ex(int depth) +{ + struct json_tokener *tok; + + tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener)); + if (!tok) return NULL; + tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec)); + if (!tok->stack) { + free(tok); + return NULL; + } + tok->pb = printbuf_new(); + tok->max_depth = depth; + json_tokener_reset(tok); + return tok; +} + +struct json_tokener* json_tokener_new(void) +{ + return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH); +} + +void json_tokener_free(struct json_tokener *tok) +{ + json_tokener_reset(tok); + if (tok->pb) printbuf_free(tok->pb); + if (tok->stack) free(tok->stack); + free(tok); +} + +static void json_tokener_reset_level(struct json_tokener *tok, int depth) +{ + tok->stack[depth].state = json_tokener_state_eatws; + tok->stack[depth].saved_state = json_tokener_state_start; + json_object_put(tok->stack[depth].current); + tok->stack[depth].current = NULL; + free(tok->stack[depth].obj_field_name); + tok->stack[depth].obj_field_name = NULL; +} + +void json_tokener_reset(struct json_tokener *tok) +{ + int i; + if (!tok) + return; + + for(i = tok->depth; i >= 0; i--) + json_tokener_reset_level(tok, i); + tok->depth = 0; + tok->err = json_tokener_success; +} + +struct json_object* json_tokener_parse(const char *str) +{ + enum json_tokener_error jerr_ignored; + struct json_object* obj; + obj = json_tokener_parse_verbose(str, &jerr_ignored); + return obj; +} + +struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error) +{ + struct json_tokener* tok; + struct json_object* obj; + + tok = json_tokener_new(); + if (!tok) + return NULL; + obj = json_tokener_parse_ex(tok, str, -1); + *error = tok->err; + if(tok->err != json_tokener_success) { + if (obj != NULL) + json_object_put(obj); + obj = NULL; + } + + json_tokener_free(tok); + return obj; +} + +#define state tok->stack[tok->depth].state +#define saved_state tok->stack[tok->depth].saved_state +#define current tok->stack[tok->depth].current +#define obj_field_name tok->stack[tok->depth].obj_field_name + +/* Optimization: + * json_tokener_parse_ex() consumed a lot of CPU in its main loop, + * iterating character-by character. A large performance boost is + * achieved by using tighter loops to locally handle units such as + * comments and strings. Loops that handle an entire token within + * their scope also gather entire strings and pass them to + * printbuf_memappend() in a single call, rather than calling + * printbuf_memappend() one char at a time. + * + * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is + * common to both the main loop and the tighter loops. + */ + +/* 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 + */ +#define PEEK_CHAR(dest, tok) \ + (((tok)->char_offset == len) ? \ + (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \ + (((tok)->err = json_tokener_success), 0) \ + : \ + (((tok)->err = json_tokener_continue), 0) \ + ) : \ + (((dest) = *str), 1) \ + ) + +/* ADVANCE_CHAR() macro: + * Incrementes str & tok->char_offset. + * For convenience of existing conditionals, returns the old value of c (0 on eof) + * Implicit inputs: c var + */ +#define ADVANCE_CHAR(str, tok) \ + ( ++(str), ((tok)->char_offset)++, c) + + +/* End optimization macro defs */ + + +struct json_object* json_tokener_parse_ex(struct json_tokener *tok, + const char *str, int len) +{ + struct json_object *obj = NULL; + char c = '\1'; +#ifdef HAVE_SETLOCALE + char *oldlocale=NULL, *tmplocale; + + tmplocale = setlocale(LC_NUMERIC, NULL); + if (tmplocale) oldlocale = strdup(tmplocale); + setlocale(LC_NUMERIC, "C"); +#endif + + tok->char_offset = 0; + tok->err = json_tokener_success; + + /* this interface is presently not 64-bit clean due to the int len argument + and the internal printbuf interface that takes 32-bit int len arguments + so the function limits the maximum string size to INT32_MAX (2GB). + If the function is called with len == -1 then strlen is called to check + the string length is less than INT32_MAX (2GB) */ + if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) { + tok->err = json_tokener_error_size; + return NULL; + } + + while (PEEK_CHAR(c, tok)) { + + redo_char: + switch(state) { + + case json_tokener_state_eatws: + /* Advance until we change state */ + while (isspace((int)c)) { + if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok))) + goto out; + } + if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) { + printbuf_reset(tok->pb); + printbuf_memappend_fast(tok->pb, &c, 1); + state = json_tokener_state_comment_start; + } else { + state = saved_state; + goto redo_char; + } + break; + + case json_tokener_state_start: + switch(c) { + case '{': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_object_field_start; + current = json_object_new_object(); + break; + case '[': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_array; + current = json_object_new_array(); + break; + case 'I': + case 'i': + state = json_tokener_state_inf; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case 'N': + case 'n': + state = json_tokener_state_null; // or NaN + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case '\'': + if (tok->flags & JSON_TOKENER_STRICT) { + /* in STRICT mode only double-quote are allowed */ + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + case '"': + state = json_tokener_state_string; + printbuf_reset(tok->pb); + tok->quote_char = c; + break; + case 'T': + case 't': + case 'F': + case 'f': + state = json_tokener_state_boolean; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; +#if defined(__GNUC__) + case '0' ... '9': +#else + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': +#endif + case '-': + state = json_tokener_state_number; + printbuf_reset(tok->pb); + tok->is_double = 0; + goto redo_char; + default: + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + break; + + case json_tokener_state_finish: + if(tok->depth == 0) goto out; + obj = json_object_get(current); + json_tokener_reset_level(tok, tok->depth); + tok->depth--; + goto redo_char; + + case json_tokener_state_inf: /* aka starts with 'i' */ + { + size_t size_inf; + int is_negative = 0; + + printbuf_memappend_fast(tok->pb, &c, 1); + size_inf = json_min(tok->st_pos+1, json_inf_str_len); + char *infbuf = tok->pb->buf; + if (*infbuf == '-') + { + infbuf++; + is_negative = 1; + } + if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_inf_str, infbuf, size_inf) == 0) || + (strncmp(json_inf_str, infbuf, size_inf) == 0) + ) + { + if (tok->st_pos == json_inf_str_len) + { + current = json_object_new_double(is_negative ? -INFINITY : INFINITY); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + tok->st_pos++; + } + break; + case json_tokener_state_null: /* aka starts with 'n' */ + { + int size; + int size_nan; + printbuf_memappend_fast(tok->pb, &c, 1); + size = json_min(tok->st_pos+1, json_null_str_len); + size_nan = json_min(tok->st_pos+1, json_nan_str_len); + if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_null_str, tok->pb->buf, size) == 0) + || (strncmp(json_null_str, tok->pb->buf, size) == 0) + ) { + if (tok->st_pos == json_null_str_len) { + current = NULL; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) || + (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0) + ) + { + if (tok->st_pos == json_nan_str_len) + { + current = json_object_new_double(NAN); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_null; + goto out; + } + tok->st_pos++; + } + break; + + case json_tokener_state_comment_start: + if(c == '*') { + state = json_tokener_state_comment; + } else if(c == '/') { + state = json_tokener_state_comment_eol; + } else { + tok->err = json_tokener_error_parse_comment; + goto out; + } + printbuf_memappend_fast(tok->pb, &c, 1); + break; + + case json_tokener_state_comment: + { + /* Advance until we change state */ + const char *case_start = str; + while(c != '*') { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start); + state = json_tokener_state_comment_end; + } + break; + + case json_tokener_state_comment_eol: + { + /* Advance until we change state */ + const char *case_start = str; + while(c != '\n') { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } + break; + + case json_tokener_state_comment_end: + printbuf_memappend_fast(tok->pb, &c, 1); + if(c == '/') { + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } else { + state = json_tokener_state_comment; + } + break; + + case json_tokener_state_string: + { + /* Advance until we change state */ + const char *case_start = str; + while(1) { + if(c == tok->quote_char) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + break; + } else if(c == '\\') { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + saved_state = json_tokener_state_string; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + } + break; + + case json_tokener_state_string_escape: + switch(c) { + case '"': + case '\\': + case '/': + printbuf_memappend_fast(tok->pb, &c, 1); + state = saved_state; + break; + case 'b': + case 'n': + case 'r': + case 't': + case 'f': + if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1); + else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1); + else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1); + else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1); + else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1); + state = saved_state; + break; + case 'u': + tok->ucs_char = 0; + tok->st_pos = 0; + state = json_tokener_state_escape_unicode; + break; + default: + tok->err = json_tokener_error_parse_string; + goto out; + } + 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 */ + while(1) { + if(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 + * 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 ((tok->char_offset+1 != len) && + (tok->char_offset+2 != len) && + (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; + continue; /* other json_tokener_state_escape_unicode */ + } 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 { + tok->err = json_tokener_error_parse_string; + goto out; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + if (got_hi_surrogate) /* Clean up any pending chars */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + goto out; + } + } + } + break; + + case json_tokener_state_boolean: + { + int size1, size2; + printbuf_memappend_fast(tok->pb, &c, 1); + size1 = json_min(tok->st_pos+1, json_true_str_len); + size2 = json_min(tok->st_pos+1, json_false_str_len); + if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_true_str, tok->pb->buf, size1) == 0) + || (strncmp(json_true_str, tok->pb->buf, size1) == 0) + ) { + if(tok->st_pos == json_true_str_len) { + current = json_object_new_boolean(1); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_false_str, tok->pb->buf, size2) == 0) + || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) { + if(tok->st_pos == json_false_str_len) { + current = json_object_new_boolean(0); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_boolean; + goto out; + } + tok->st_pos++; + } + break; + + case json_tokener_state_number: + { + /* Advance until we change state */ + 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)) { + ++case_len; + + /* non-digit characters checks */ + /* note: since the main loop condition to get here was + an input starting with 0-9 or '-', we are + protected from input starting with '.' or + e/E. */ + if (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; + } + 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; + } + 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; + } + + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, case_len); + goto out; + } + } + if (case_len>0) + printbuf_memappend_fast(tok->pb, case_start, case_len); + + // Check for -Infinity + if (tok->pb->buf[0] == '-' && case_len == 1 && + (c == 'i' || c == 'I')) + { + state = json_tokener_state_inf; + goto redo_char; + } + } + { + int64_t num64; + double numd; + if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { + if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) { + /* in strict mode, number must not start with 0 */ + tok->err = json_tokener_error_parse_number; + goto out; + } + current = json_object_new_int64(num64); + } + else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) + { + current = json_object_new_double_s(numd, tok->pb->buf); + } else { + tok->err = json_tokener_error_parse_number; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + break; + + case json_tokener_state_array_after_sep: + case json_tokener_state_array: + if(c == ']') { + if (state == json_tokener_state_array_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else { + if(tok->depth >= tok->max_depth-1) { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_array_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + } + break; + + case json_tokener_state_array_add: + json_object_array_add(current, obj); + saved_state = json_tokener_state_array_sep; + state = json_tokener_state_eatws; + goto redo_char; + + case json_tokener_state_array_sep: + if(c == ']') { + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if(c == ',') { + saved_state = json_tokener_state_array_after_sep; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_array; + goto out; + } + break; + + case json_tokener_state_object_field_start: + case json_tokener_state_object_field_start_after_sep: + if(c == '}') { + if (state == json_tokener_state_object_field_start_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if (c == '"' || c == '\'') { + tok->quote_char = c; + printbuf_reset(tok->pb); + state = json_tokener_state_object_field; + } else { + tok->err = json_tokener_error_parse_object_key_name; + goto out; + } + break; + + case json_tokener_state_object_field: + { + /* Advance until we change state */ + const char *case_start = str; + while(1) { + if(c == tok->quote_char) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + obj_field_name = strdup(tok->pb->buf); + saved_state = json_tokener_state_object_field_end; + state = json_tokener_state_eatws; + break; + } else if(c == '\\') { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + saved_state = json_tokener_state_object_field; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + } + break; + + case json_tokener_state_object_field_end: + if(c == ':') { + saved_state = json_tokener_state_object_value; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_object_key_sep; + goto out; + } + break; + + case json_tokener_state_object_value: + if(tok->depth >= tok->max_depth-1) { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_object_value_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + + case json_tokener_state_object_value_add: + json_object_object_add(current, obj_field_name, obj); + free(obj_field_name); + obj_field_name = NULL; + saved_state = json_tokener_state_object_sep; + state = json_tokener_state_eatws; + goto redo_char; + + case json_tokener_state_object_sep: + if(c == '}') { + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if(c == ',') { + saved_state = json_tokener_state_object_field_start_after_sep; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_object_value_sep; + goto out; + } + break; + + } + if (!ADVANCE_CHAR(str, tok)) + goto out; + } /* while(POP_CHAR) */ + + out: + if (c && + (state == json_tokener_state_finish) && + (tok->depth == 0) && + (tok->flags & JSON_TOKENER_STRICT)) { + /* unexpected char after JSON data */ + tok->err = json_tokener_error_parse_unexpected; + } + if (!c) { /* We hit an eof char (0) */ + if(state != json_tokener_state_finish && + saved_state != json_tokener_state_finish) + tok->err = json_tokener_error_parse_eof; + } + +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, oldlocale); + if (oldlocale) free(oldlocale); +#endif + + if (tok->err == json_tokener_success) + { + json_object *ret = json_object_get(current); + int ii; + + /* Partially reset, so we parse additional objects on subsequent calls. */ + for(ii = tok->depth; ii >= 0; ii--) + json_tokener_reset_level(tok, ii); + return ret; + } + + MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", + json_tokener_errors[tok->err], tok->char_offset); + return NULL; +} + +void json_tokener_set_flags(struct json_tokener *tok, int flags) +{ + tok->flags = flags; +} diff --git a/json-c/src/json_tokener.h b/json-c/src/json_tokener.h index d104c75..2c1363c 100644 --- a/json-c/src/json_tokener.h +++ b/json-c/src/json_tokener.h @@ -1,188 +1,208 @@ -/* - * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _json_tokener_h_ -#define _json_tokener_h_ - -#include -#include "json_object.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum json_tokener_error { - json_tokener_success, - json_tokener_continue, - json_tokener_error_depth, - json_tokener_error_parse_eof, - json_tokener_error_parse_unexpected, - json_tokener_error_parse_null, - json_tokener_error_parse_boolean, - json_tokener_error_parse_number, - json_tokener_error_parse_array, - json_tokener_error_parse_object_key_name, - json_tokener_error_parse_object_key_sep, - json_tokener_error_parse_object_value_sep, - json_tokener_error_parse_string, - json_tokener_error_parse_comment -}; - -enum json_tokener_state { - json_tokener_state_eatws, - json_tokener_state_start, - json_tokener_state_finish, - json_tokener_state_null, - json_tokener_state_comment_start, - json_tokener_state_comment, - json_tokener_state_comment_eol, - json_tokener_state_comment_end, - json_tokener_state_string, - json_tokener_state_string_escape, - json_tokener_state_escape_unicode, - json_tokener_state_boolean, - json_tokener_state_number, - json_tokener_state_array, - json_tokener_state_array_add, - json_tokener_state_array_sep, - json_tokener_state_object_field_start, - json_tokener_state_object_field, - json_tokener_state_object_field_end, - json_tokener_state_object_value, - json_tokener_state_object_value_add, - json_tokener_state_object_sep -}; - -struct json_tokener_srec -{ - enum json_tokener_state state, saved_state; - struct json_object *obj; - struct json_object *current; - char *obj_field_name; -}; - -#define JSON_TOKENER_MAX_DEPTH 32 - -struct json_tokener -{ - char *str; - struct printbuf *pb; - int depth, is_double, st_pos, char_offset; - enum json_tokener_error err; - unsigned int ucs_char; - char quote_char; - struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH]; -}; - -/** - * Given an error previously returned by json_tokener_get_error(), - * return a human readable description of the error. - * - * @return a generic error message is returned if an invalid error value is provided. - */ -const char *json_tokener_error_desc(enum json_tokener_error jerr); - -/** - * @b XXX do not use json_tokener_errors directly. - * After v0.10 this will be removed. - * - * See json_tokener_error_desc() instead. - */ -extern const char* json_tokener_errors[]; - -/** - * Retrieve the error caused by the last call to json_tokener_parse_ex(), - * or json_tokener_success if there is no error. - * - * When parsing a JSON string in pieces, if the tokener is in the middle - * of parsing this will return json_tokener_continue. - * - * See also json_tokener_error_desc(). - */ -enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); - -extern struct json_tokener* json_tokener_new(void); -extern void json_tokener_free(struct json_tokener *tok); -extern void json_tokener_reset(struct json_tokener *tok); -extern struct json_object* json_tokener_parse(const char *str); -extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); - -/** - * Parse a string and return a non-NULL json_object if a valid JSON value - * is found. The string does not need to be a JSON object or array; - * it can also be a string, number or boolean value. - * - * A partial JSON string can be parsed. If the parsing is incomplete, - * NULL will be returned and json_tokener_get_error() will be return - * json_tokener_continue. - * json_tokener_parse_ex() can then be called with additional bytes in str - * to continue the parsing. - * - * If json_tokener_parse_ex() returns NULL and the error anything other than - * json_tokener_continue, a fatal error has occurred and parsing must be - * halted. Then tok object must not be re-used until json_tokener_reset() is - * called. - * - * When a valid JSON value is parsed, a non-NULL json_object will be - * returned. Also, json_tokener_get_error() will return json_tokener_success. - * Be sure to check the type with json_object_is_type() or - * json_object_get_type() before using the object. - * - * @b XXX this shouldn't use internal fields: - * Trailing characters after the parsed value do not automatically cause an - * error. It is up to the caller to decide whether to treat this as an - * error or to handle the additional characters, perhaps by parsing another - * json value starting from that point. - * - * Extra characters can be detected by comparing the tok->char_offset 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. - * - * Example: - * @code -json_object *jobj = NULL; -const char *mystring = NULL; -int stringlen = 0; -enum json_tokener_error jerr; -do { - mystring = ... // get JSON string, e.g. read from file, etc... - stringlen = strlen(mystring); - jobj = json_tokener_parse_ex(tok, mystring, stringlen); -} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); -if (jerr != json_tokener_success) -{ - fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); - // Handle errors, as appropriate for your application. -} -if (tok->char_offset < stringlen) // XXX shouldn't access internal fields -{ - // Handle extra characters after parsed object as desired. - // e.g. issue an error, parse another object from that point, etc... -} -// Success, use jobj here. - -@endcode - * - * @param tok a json_tokener previously allocated with json_tokener_new() - * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. - * @param len the length of str - */ -extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok, - const char *str, int len); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_tokener_h_ +#define _json_tokener_h_ + +#include +#include "json_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum json_tokener_error { + json_tokener_success, + json_tokener_continue, + json_tokener_error_depth, + json_tokener_error_parse_eof, + json_tokener_error_parse_unexpected, + json_tokener_error_parse_null, + json_tokener_error_parse_boolean, + json_tokener_error_parse_number, + json_tokener_error_parse_array, + json_tokener_error_parse_object_key_name, + json_tokener_error_parse_object_key_sep, + json_tokener_error_parse_object_value_sep, + json_tokener_error_parse_string, + json_tokener_error_parse_comment, + json_tokener_error_size +}; + +enum json_tokener_state { + json_tokener_state_eatws, + json_tokener_state_start, + json_tokener_state_finish, + json_tokener_state_null, + json_tokener_state_comment_start, + json_tokener_state_comment, + json_tokener_state_comment_eol, + json_tokener_state_comment_end, + json_tokener_state_string, + json_tokener_state_string_escape, + json_tokener_state_escape_unicode, + json_tokener_state_boolean, + json_tokener_state_number, + json_tokener_state_array, + json_tokener_state_array_add, + json_tokener_state_array_sep, + json_tokener_state_object_field_start, + json_tokener_state_object_field, + json_tokener_state_object_field_end, + json_tokener_state_object_value, + json_tokener_state_object_value_add, + json_tokener_state_object_sep, + json_tokener_state_array_after_sep, + json_tokener_state_object_field_start_after_sep, + json_tokener_state_inf +}; + +struct json_tokener_srec +{ + enum json_tokener_state state, saved_state; + struct json_object *obj; + struct json_object *current; + char *obj_field_name; +}; + +#define JSON_TOKENER_DEFAULT_DEPTH 32 + +struct json_tokener +{ + char *str; + struct printbuf *pb; + int max_depth, depth, is_double, st_pos, char_offset; + enum json_tokener_error err; + unsigned int ucs_char; + char quote_char; + struct json_tokener_srec *stack; + int flags; +}; + +/** + * Be strict when parsing JSON input. Use caution with + * this flag as what is considered valid may become more + * restrictive from one release to the next, causing your + * code to fail on previously working input. + * + * This flag is not set by default. + * + * @see json_tokener_set_flags() + */ +#define JSON_TOKENER_STRICT 0x01 + +/** + * Given an error previously returned by json_tokener_get_error(), + * return a human readable description of the error. + * + * @return a generic error message is returned if an invalid error value is provided. + */ +const char *json_tokener_error_desc(enum json_tokener_error jerr); + +/** + * Retrieve the error caused by the last call to json_tokener_parse_ex(), + * or json_tokener_success if there is no error. + * + * When parsing a JSON string in pieces, if the tokener is in the middle + * of parsing this will return json_tokener_continue. + * + * See also json_tokener_error_desc(). + */ +enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); + +extern struct json_tokener* json_tokener_new(void); +extern struct json_tokener* json_tokener_new_ex(int depth); +extern void json_tokener_free(struct json_tokener *tok); +extern void json_tokener_reset(struct json_tokener *tok); +extern struct json_object* json_tokener_parse(const char *str); +extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); + +/** + * Set flags that control how parsing will be done. + */ +extern void json_tokener_set_flags(struct json_tokener *tok, int flags); + +/** + * Parse a string and return a non-NULL json_object if a valid JSON value + * is found. The string does not need to be a JSON object or array; + * it can also be a string, number or boolean value. + * + * A partial JSON string can be parsed. If the parsing is incomplete, + * NULL will be returned and json_tokener_get_error() will be return + * json_tokener_continue. + * json_tokener_parse_ex() can then be called with additional bytes in str + * to continue the parsing. + * + * If json_tokener_parse_ex() returns NULL and the error anything other than + * json_tokener_continue, a fatal error has occurred and parsing must be + * halted. Then tok object must not be re-used until json_tokener_reset() is + * called. + * + * When a valid JSON value is parsed, a non-NULL json_object will be + * returned. Also, json_tokener_get_error() will return json_tokener_success. + * Be sure to check the type with json_object_is_type() or + * json_object_get_type() before using the object. + * + * @b XXX this shouldn't use internal fields: + * Trailing characters after the parsed value do not automatically cause an + * error. It is up to the caller to decide whether to treat this as an + * error or to handle the additional characters, perhaps by parsing another + * json value starting from that point. + * + * Extra characters can be detected by comparing the tok->char_offset 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. + * + * 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). + * If the function is called with len == -1 then strlen is called to check + * the string length is less than INT32_MAX (2GB) + * + * Example: + * @code +json_object *jobj = NULL; +const char *mystring = NULL; +int stringlen = 0; +enum json_tokener_error jerr; +do { + mystring = ... // get JSON string, e.g. read from file, etc... + stringlen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, stringlen); +} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); +if (jerr != json_tokener_success) +{ + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + // Handle errors, as appropriate for your application. +} +if (tok->char_offset < stringlen) // XXX shouldn't access internal fields +{ + // Handle extra characters after parsed object as desired. + // e.g. issue an error, parse another object from that point, etc... +} +// Success, use jobj here. + +@endcode + * + * @param tok a json_tokener previously allocated with json_tokener_new() + * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. + * @param len the length of str + */ +extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok, + const char *str, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/json_util.c b/json-c/src/json_util.c index faf9abd..331e92d 100644 --- a/json-c/src/json_util.c +++ b/json-c/src/json_util.c @@ -1,234 +1,314 @@ -/* - * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#include "config.h" -#undef realloc - -#include -#include -#include -#include -#include -#include -#include - -#if HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#if HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - -#if HAVE_FCNTL_H -#include -#endif /* HAVE_FCNTL_H */ - -#if HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ - -#ifdef WIN32 -# define WIN32_LEAN_AND_MEAN -# include -# include -#endif /* defined(WIN32) */ - -#if !HAVE_OPEN && defined(WIN32) -# define open _open -#endif - - -#include "bits.h" -#include "debug.h" -#include "printbuf.h" -#include "json_inttypes.h" -#include "json_object.h" -#include "json_tokener.h" -#include "json_util.h" - -struct json_object* json_object_from_file(const char *filename) -{ - struct printbuf *pb; - struct json_object *obj; - char buf[JSON_FILE_BUF_SIZE]; - int fd, ret; - - if((fd = open(filename, O_RDONLY)) < 0) { - MC_ERROR("json_object_from_file: error reading file %s: %s\n", - filename, strerror(errno)); - return (struct json_object*)error_ptr(-1); - } - if(!(pb = printbuf_new())) { - close(fd); - MC_ERROR("json_object_from_file: printbuf_new failed\n"); - return (struct json_object*)error_ptr(-1); - } - while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { - printbuf_memappend(pb, buf, ret); - } - close(fd); - if(ret < 0) { - MC_ABORT("json_object_from_file: error reading file %s: %s\n", - filename, strerror(errno)); - printbuf_free(pb); - return (struct json_object*)error_ptr(-1); - } - obj = json_tokener_parse(pb->buf); - printbuf_free(pb); - return obj; -} - -int json_object_to_file(char *filename, struct json_object *obj) -{ - const char *json_str; - int fd, ret; - unsigned int wpos, wsize; - - if(!obj) { - MC_ERROR("json_object_to_file: object is null\n"); - return -1; - } - - if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { - MC_ERROR("json_object_to_file: error opening file %s: %s\n", - filename, strerror(errno)); - return -1; - } - - if(!(json_str = json_object_to_json_string(obj))) { - close(fd); - return -1; - } - - wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ - wpos = 0; - while(wpos < wsize) { - if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { - close(fd); - MC_ERROR("json_object_to_file: error writing file %s: %s\n", - filename, strerror(errno)); - return -1; - } - - /* because of the above check for ret < 0, we can safely cast and add */ - wpos += (unsigned int)ret; - } - - close(fd); - return 0; -} - -int json_parse_int64(const char *buf, int64_t *retval) -{ - int64_t num64; - const char *buf_skip_space; - int orig_has_neg; - if (sscanf(buf, "%" SCNd64, &num64) != 1) - { - MC_DEBUG("Failed to parse, sscanf != 1\n"); - return 1; - } - buf_skip_space = buf; - orig_has_neg = 0; - // Skip leading spaces - while (isspace((int)*buf_skip_space) && *buf_skip_space) - buf_skip_space++; - if (*buf_skip_space == '-') - { - buf_skip_space++; - orig_has_neg = 1; - } - // Skip leading zeros, but keep at least one digit - while (buf_skip_space[0] == '0' && buf_skip_space[1] != '\0') - buf_skip_space++; - if (buf_skip_space[0] == '0' && buf_skip_space[1] == '\0') - orig_has_neg = 0; // "-0" is the same as just plain "0" - - if (errno != ERANGE) - { - char buf_cmp[100]; - char *buf_cmp_start = buf_cmp; - int recheck_has_neg = 0; - int buf_cmp_len; -#ifdef _MSC_VER - _snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); -#else - snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); -#endif - if (*buf_cmp_start == '-') - { - recheck_has_neg = 1; - buf_cmp_start++; - } - // No need to skip leading spaces or zeros here. - - buf_cmp_len = strlen(buf_cmp_start); - /** - * If the sign is different, or - * some of the digits are different, or - * there is another digit present in the original string - * then we NOT successfully parsed the value. - */ - if (orig_has_neg != recheck_has_neg || - strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 || - (strlen(buf_skip_space) != buf_cmp_len && - isdigit((int)buf_skip_space[buf_cmp_len]) - ) - ) - { - errno = ERANGE; - } - } - if (errno == ERANGE) - { - if (orig_has_neg) - num64 = INT64_MIN; - else - num64 = INT64_MAX; - } - *retval = num64; - return 0; -} - -#if HAVE_REALLOC == 0 -void* rpl_realloc(void* p, size_t n) -{ - if (n == 0) - n = 1; - if (p == 0) - return malloc(n); - return realloc(p, n); -} -#endif - -#define NELEM(a) (sizeof(a) / sizeof(a[0])) -static const char* json_type_name[] = { - /* If you change this, be sure to update the enum json_type definition too */ - "null", - "boolean", - "double", - "int", - "object", - "array", - "string", -}; - -const char *json_type_to_name(enum json_type o_type) -{ - if (o_type < 0 || o_type >= NELEM(json_type_name)) - { - MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name)); - return NULL; - } - return json_type_name[o_type]; -} - +/* + * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" +#undef realloc + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +#include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_FCNTL_H +#include +#endif /* HAVE_FCNTL_H */ + +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# include +#endif /* defined(WIN32) */ + +#if !defined(HAVE_OPEN) && defined(WIN32) +# define open _open +#endif + +#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) + /* MSC has the version as _snprintf */ +# define snprintf _snprintf +#elif !defined(HAVE_SNPRINTF) +# error You do not have snprintf on your system. +#endif /* HAVE_SNPRINTF */ + +#include "debug.h" +#include "printbuf.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +static int sscanf_is_broken = 0; +static int sscanf_is_broken_testdone = 0; +static void sscanf_is_broken_test(void); + +/* + * Create a JSON object from already opened file descriptor. + * + * This function can be helpful, when you opened the file already, + * e.g. when you have a temp file. + * Note, that the fd must be readable at the actual position, i.e. + * use lseek(fd, 0, SEEK_SET) before. + */ +struct json_object* json_object_from_fd(int fd) +{ + struct printbuf *pb; + struct json_object *obj; + char buf[JSON_FILE_BUF_SIZE]; + int ret; + + if(!(pb = printbuf_new())) { + MC_ERROR("json_object_from_file: printbuf_new failed\n"); + return NULL; + } + while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { + printbuf_memappend(pb, buf, ret); + } + if(ret < 0) { + MC_ERROR("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno)); + printbuf_free(pb); + return NULL; + } + obj = json_tokener_parse(pb->buf); + printbuf_free(pb); + return obj; +} + +struct json_object* json_object_from_file(const char *filename) +{ + struct json_object *obj; + int fd; + + if((fd = open(filename, O_RDONLY)) < 0) { + MC_ERROR("json_object_from_file: error opening file %s: %s\n", + filename, strerror(errno)); + return NULL; + } + obj = json_object_from_fd(fd); + close(fd); + return obj; +} + +/* extended "format and write to file" function */ + +int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) +{ + const char *json_str; + int fd, ret; + unsigned int wpos, wsize; + + if(!obj) { + MC_ERROR("json_object_to_file: object is null\n"); + return -1; + } + + if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { + MC_ERROR("json_object_to_file: error opening file %s: %s\n", + filename, strerror(errno)); + return -1; + } + + if(!(json_str = json_object_to_json_string_ext(obj,flags))) { + close(fd); + return -1; + } + + wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ + wpos = 0; + while(wpos < wsize) { + if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { + close(fd); + MC_ERROR("json_object_to_file: error writing file %s: %s\n", + filename, strerror(errno)); + return -1; + } + + /* because of the above check for ret < 0, we can safely cast and add */ + wpos += (unsigned int)ret; + } + + close(fd); + return 0; +} + +// backwards compatible "format and write to file" function + +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); +} + +int json_parse_double(const char *buf, double *retval) +{ + return (sscanf(buf, "%lf", retval)==1 ? 0 : 1); +} + +/* + * Not all implementations of sscanf actually work properly. + * Check whether the one we're currently using does, and if + * it's broken, enable the workaround code. + */ +static void sscanf_is_broken_test() +{ + int64_t num64; + int ret_errno, is_int64_min, ret_errno2, is_int64_max; + + (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64); + ret_errno = errno; + is_int64_min = (num64 == INT64_MIN); + + (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64); + ret_errno2 = errno; + is_int64_max = (num64 == INT64_MAX); + + if (ret_errno != ERANGE || !is_int64_min || + ret_errno2 != ERANGE || !is_int64_max) + { + MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n"); + sscanf_is_broken = 1; + } +} + +int json_parse_int64(const char *buf, int64_t *retval) +{ + int64_t num64; + const char *buf_sig_digits; + int orig_has_neg; + int saved_errno; + + if (!sscanf_is_broken_testdone) + { + sscanf_is_broken_test(); + sscanf_is_broken_testdone = 1; + } + + // Skip leading spaces + while (isspace((int)*buf) && *buf) + buf++; + + errno = 0; // sscanf won't always set errno, so initialize + if (sscanf(buf, "%" SCNd64, &num64) != 1) + { + MC_DEBUG("Failed to parse, sscanf != 1\n"); + return 1; + } + + saved_errno = errno; + buf_sig_digits = buf; + orig_has_neg = 0; + if (*buf_sig_digits == '-') + { + buf_sig_digits++; + orig_has_neg = 1; + } + + // Not all sscanf implementations actually work + if (sscanf_is_broken && saved_errno != ERANGE) + { + char buf_cmp[100]; + char *buf_cmp_start = buf_cmp; + int recheck_has_neg = 0; + int buf_cmp_len; + + // Skip leading zeros, but keep at least one digit + while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0') + buf_sig_digits++; + if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 + orig_has_neg = 0; // "-0" is the same as just plain "0" + + snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); + if (*buf_cmp_start == '-') + { + recheck_has_neg = 1; + buf_cmp_start++; + } + // No need to skip leading spaces or zeros here. + + buf_cmp_len = strlen(buf_cmp_start); + /** + * If the sign is different, or + * some of the digits are different, or + * there is another digit present in the original string + * then we have NOT successfully parsed the value. + */ + if (orig_has_neg != recheck_has_neg || + strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 || + ((int)strlen(buf_sig_digits) != buf_cmp_len && + isdigit((int)buf_sig_digits[buf_cmp_len]) + ) + ) + { + saved_errno = ERANGE; + } + } + + // Not all sscanf impl's set the value properly when out of range. + // Always do this, even for properly functioning implementations, + // since it shouldn't slow things down much. + if (saved_errno == ERANGE) + { + if (orig_has_neg) + num64 = INT64_MIN; + else + num64 = INT64_MAX; + } + *retval = num64; + return 0; +} + +#ifndef HAVE_REALLOC +void* rpl_realloc(void* p, size_t n) +{ + if (n == 0) + n = 1; + if (p == 0) + return malloc(n); + return realloc(p, n); +} +#endif + +#define NELEM(a) (sizeof(a) / sizeof(a[0])) +static const char* json_type_name[] = { + /* If you change this, be sure to update the enum json_type definition too */ + "null", + "boolean", + "double", + "int", + "object", + "array", + "string", +}; + +const char *json_type_to_name(enum json_type o_type) +{ + int o_type_int = (int)o_type; + if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) + { + MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name)); + return NULL; + } + return json_type_name[o_type]; +} + diff --git a/json-c/src/json_util.h b/json-c/src/json_util.h index a77305e..8a910e0 100644 --- a/json-c/src/json_util.h +++ b/json-c/src/json_util.h @@ -1,38 +1,51 @@ -/* - * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _json_util_h_ -#define _json_util_h_ - -#include "json_object.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define JSON_FILE_BUF_SIZE 4096 - -/* utility functions */ -extern struct json_object* json_object_from_file(const char *filename); -extern int json_object_to_file(char *filename, struct json_object *obj); -extern int json_parse_int64(const char *buf, int64_t *retval); - -/** - * Return a string describing the type of the object. - * e.g. "int", or "object", etc... - */ -extern const char *json_type_to_name(enum json_type o_type); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_util_h_ +#define _json_util_h_ + +#include "json_object.h" + +#ifndef json_min +#define json_min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef json_max +#define json_max(a,b) ((a) > (b) ? (a) : (b)) +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#define JSON_FILE_BUF_SIZE 4096 + +/* utility functions */ +extern struct json_object* json_object_from_file(const char *filename); +extern struct json_object* json_object_from_fd(int fd); +extern int json_object_to_file(const char *filename, struct json_object *obj); +extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); +extern int json_parse_int64(const char *buf, int64_t *retval); +extern int json_parse_double(const char *buf, double *retval); + + +/** + * Return a string describing the type of the object. + * e.g. "int", or "object", etc... + */ +extern const char *json_type_to_name(enum json_type o_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/linkhash.c b/json-c/src/linkhash.c index ddedc12..8fd94d6 100644 --- a/json-c/src/linkhash.c +++ b/json-c/src/linkhash.c @@ -1,229 +1,609 @@ -/* - * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "linkhash.h" - -void lh_abort(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - vprintf(msg, ap); - va_end(ap); - exit(1); -} - -unsigned long lh_ptr_hash(const void *k) -{ - /* CAW: refactored to be 64bit nice */ - return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX); -} - -int lh_ptr_equal(const void *k1, const void *k2) -{ - return (k1 == k2); -} - -unsigned long lh_char_hash(const void *k) -{ - unsigned int h = 0; - const char* data = (const char*)k; - - while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME; - - return h; -} - -int lh_char_equal(const void *k1, const void *k2) -{ - return (strcmp((const char*)k1, (const char*)k2) == 0); -} - -struct lh_table* lh_table_new(int size, const char *name, - lh_entry_free_fn *free_fn, - lh_hash_fn *hash_fn, - lh_equal_fn *equal_fn) -{ - int i; - struct lh_table *t; - - t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); - if(!t) lh_abort("lh_table_new: calloc failed\n"); - t->count = 0; - t->size = size; - t->name = name; - t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry)); - if(!t->table) lh_abort("lh_table_new: calloc failed\n"); - t->free_fn = free_fn; - t->hash_fn = hash_fn; - t->equal_fn = equal_fn; - for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY; - return t; -} - -struct lh_table* lh_kchar_table_new(int size, const char *name, - lh_entry_free_fn *free_fn) -{ - return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal); -} - -struct lh_table* lh_kptr_table_new(int size, const char *name, - lh_entry_free_fn *free_fn) -{ - return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal); -} - -void lh_table_resize(struct lh_table *t, int new_size) -{ - struct lh_table *new_t; - struct lh_entry *ent; - - new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn); - ent = t->head; - while(ent) { - lh_table_insert(new_t, ent->k, ent->v); - ent = ent->next; - } - free(t->table); - t->table = new_t->table; - t->size = new_size; - t->head = new_t->head; - t->tail = new_t->tail; - t->resizes++; - free(new_t); -} - -void lh_table_free(struct lh_table *t) -{ - struct lh_entry *c; - for(c = t->head; c != NULL; c = c->next) { - if(t->free_fn) { - t->free_fn(c); - } - } - free(t->table); - free(t); -} - - -int lh_table_insert(struct lh_table *t, void *k, const void *v) -{ - unsigned long h, n; - - t->inserts++; - if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2); - - h = t->hash_fn(k); - n = h % t->size; - - while( 1 ) { - if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break; - t->collisions++; - if(++n == t->size) n = 0; - } - - t->table[n].k = k; - t->table[n].v = v; - t->count++; - - if(t->head == NULL) { - t->head = t->tail = &t->table[n]; - t->table[n].next = t->table[n].prev = NULL; - } else { - t->tail->next = &t->table[n]; - t->table[n].prev = t->tail; - t->table[n].next = NULL; - t->tail = &t->table[n]; - } - - return 0; -} - - -struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k) -{ - unsigned long h = t->hash_fn(k); - unsigned long n = h % t->size; - int count = 0; - - t->lookups++; - while( count < t->size ) { - if(t->table[n].k == LH_EMPTY) return NULL; - if(t->table[n].k != LH_FREED && - t->equal_fn(t->table[n].k, k)) return &t->table[n]; - if(++n == t->size) n = 0; - count++; - } - return NULL; -} - - -const void* lh_table_lookup(struct lh_table *t, const void *k) -{ - void *result; - lh_table_lookup_ex(t, k, &result); - return result; -} - -json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) -{ - struct lh_entry *e = lh_table_lookup_entry(t, k); - if (e != NULL) { - if (v != NULL) *v = (void *)e->v; - return TRUE; /* key found */ - } - if (v != NULL) *v = NULL; - return FALSE; /* key not found */ -} - -int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) -{ - ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ - - /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ - if(n < 0) { return -2; } - - if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1; - t->count--; - if(t->free_fn) t->free_fn(e); - t->table[n].v = NULL; - t->table[n].k = LH_FREED; - if(t->tail == &t->table[n] && t->head == &t->table[n]) { - t->head = t->tail = NULL; - } else if (t->head == &t->table[n]) { - t->head->next->prev = NULL; - t->head = t->head->next; - } else if (t->tail == &t->table[n]) { - t->tail->prev->next = NULL; - t->tail = t->tail->prev; - } else { - t->table[n].prev->next = t->table[n].next; - t->table[n].next->prev = t->table[n].prev; - } - t->table[n].next = t->table[n].prev = NULL; - return 0; -} - - -int lh_table_delete(struct lh_table *t, const void *k) -{ - struct lh_entry *e = lh_table_lookup_entry(t, k); - if(!e) return -1; - return lh_table_delete_entry(t, e); -} - +/* + * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ENDIAN_H +# include /* attempt to define endianness */ +#endif + +#ifdef _MSC_VER +# define WIN32_LEAN_AND_MEAN +# include /* Get InterlockedCompareExchange */ +#endif + +#include "random_seed.h" +#include "linkhash.h" + +void lh_abort(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + vprintf(msg, ap); + va_end(ap); + exit(1); +} + +unsigned long lh_ptr_hash(const void *k) +{ + /* CAW: refactored to be 64bit nice */ + return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX); +} + +int lh_ptr_equal(const void *k1, const void *k2) +{ + return (k1 == k2); +} + +/* + * hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * http://burtleburtle.net/bob/c/lookup3.c + * minor modifications to make functions static so no symbols are exported + * minor mofifications to compile with -Werror + */ + +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + const uint8_t *k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +unsigned long lh_char_hash(const void *k) +{ + static volatile int random_seed = -1; + + if (random_seed == -1) { + int seed; + /* we can't use -1 as it is the unitialized sentinel */ + while ((seed = json_c_get_random_seed()) == -1); +#if defined __GNUC__ + (void)__sync_val_compare_and_swap(&random_seed, -1, seed); +#elif defined _MSC_VER + InterlockedCompareExchange((LONG *)&random_seed, seed, -1); +#else +#warning "racy random seed initializtion if used by multiple threads" + random_seed = seed; /* potentially racy */ +#endif + } + + return hashlittle((const char*)k, strlen((const char*)k), random_seed); +} + +int lh_char_equal(const void *k1, const void *k2) +{ + return (strcmp((const char*)k1, (const char*)k2) == 0); +} + +struct lh_table* lh_table_new(int size, const char *name, + lh_entry_free_fn *free_fn, + lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn) +{ + int i; + struct lh_table *t; + + t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); + if(!t) lh_abort("lh_table_new: calloc failed\n"); + t->count = 0; + t->size = size; + t->name = name; + t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry)); + if(!t->table) lh_abort("lh_table_new: calloc failed\n"); + t->free_fn = free_fn; + t->hash_fn = hash_fn; + t->equal_fn = equal_fn; + for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY; + return t; +} + +struct lh_table* lh_kchar_table_new(int size, const char *name, + lh_entry_free_fn *free_fn) +{ + return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal); +} + +struct lh_table* lh_kptr_table_new(int size, const char *name, + lh_entry_free_fn *free_fn) +{ + return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal); +} + +void lh_table_resize(struct lh_table *t, int new_size) +{ + struct lh_table *new_t; + struct lh_entry *ent; + + new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn); + ent = t->head; + while(ent) { + lh_table_insert(new_t, ent->k, ent->v); + ent = ent->next; + } + free(t->table); + t->table = new_t->table; + t->size = new_size; + t->head = new_t->head; + t->tail = new_t->tail; + t->resizes++; + free(new_t); +} + +void lh_table_free(struct lh_table *t) +{ + struct lh_entry *c; + for(c = t->head; c != NULL; c = c->next) { + if(t->free_fn) { + t->free_fn(c); + } + } + free(t->table); + free(t); +} + + +int lh_table_insert(struct lh_table *t, void *k, const void *v) +{ + unsigned long h, n; + + t->inserts++; + if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2); + + h = t->hash_fn(k); + n = h % t->size; + + while( 1 ) { + if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break; + t->collisions++; + if ((int)++n == t->size) n = 0; + } + + t->table[n].k = k; + t->table[n].v = v; + t->count++; + + if(t->head == NULL) { + t->head = t->tail = &t->table[n]; + t->table[n].next = t->table[n].prev = NULL; + } else { + t->tail->next = &t->table[n]; + t->table[n].prev = t->tail; + t->table[n].next = NULL; + t->tail = &t->table[n]; + } + + return 0; +} + + +struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k) +{ + unsigned long h = t->hash_fn(k); + unsigned long n = h % t->size; + int count = 0; + + t->lookups++; + while( count < t->size ) { + if(t->table[n].k == LH_EMPTY) return NULL; + if(t->table[n].k != LH_FREED && + t->equal_fn(t->table[n].k, k)) return &t->table[n]; + if ((int)++n == t->size) n = 0; + count++; + } + return NULL; +} + + +const void* lh_table_lookup(struct lh_table *t, const void *k) +{ + void *result; + lh_table_lookup_ex(t, k, &result); + return result; +} + +json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) +{ + struct lh_entry *e = lh_table_lookup_entry(t, k); + if (e != NULL) { + if (v != NULL) *v = (void *)e->v; + return TRUE; /* key found */ + } + if (v != NULL) *v = NULL; + return FALSE; /* key not found */ +} + +int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) +{ + ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ + + /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ + if(n < 0) { return -2; } + + if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1; + t->count--; + if(t->free_fn) t->free_fn(e); + t->table[n].v = NULL; + t->table[n].k = LH_FREED; + if(t->tail == &t->table[n] && t->head == &t->table[n]) { + t->head = t->tail = NULL; + } else if (t->head == &t->table[n]) { + t->head->next->prev = NULL; + t->head = t->head->next; + } else if (t->tail == &t->table[n]) { + t->tail->prev->next = NULL; + t->tail = t->tail->prev; + } else { + t->table[n].prev->next = t->table[n].next; + t->table[n].next->prev = t->table[n].prev; + } + t->table[n].next = t->table[n].prev = NULL; + return 0; +} + + +int lh_table_delete(struct lh_table *t, const void *k) +{ + struct lh_entry *e = lh_table_lookup_entry(t, k); + if(!e) return -1; + return lh_table_delete_entry(t, e); +} + +int lh_table_length(struct lh_table *t) +{ + return t->count; +} diff --git a/json-c/src/linkhash.h b/json-c/src/linkhash.h index bbb5488..9ef0f50 100644 --- a/json-c/src/linkhash.h +++ b/json-c/src/linkhash.h @@ -1,291 +1,292 @@ -/* - * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - */ - -#ifndef _linkhash_h_ -#define _linkhash_h_ - -#include "json_object.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * golden prime used in hash functions - */ -#define LH_PRIME 0x9e370001UL - -/** - * The fraction of filled hash buckets until an insert will cause the table - * to be resized. - * This can range from just above 0 up to 1.0. - */ -#define LH_LOAD_FACTOR 0.66 - -/** - * sentinel pointer value for empty slots - */ -#define LH_EMPTY (void*)-1 - -/** - * sentinel pointer value for freed slots - */ -#define LH_FREED (void*)-2 - -struct lh_entry; - -/** - * callback function prototypes - */ -typedef void (lh_entry_free_fn) (struct lh_entry *e); -/** - * callback function prototypes - */ -typedef unsigned long (lh_hash_fn) (const void *k); -/** - * callback function prototypes - */ -typedef int (lh_equal_fn) (const void *k1, const void *k2); - -/** - * An entry in the hash table - */ -struct lh_entry { - /** - * The key. - */ - void *k; - /** - * The value. - */ - const void *v; - /** - * The next entry - */ - struct lh_entry *next; - /** - * The previous entry. - */ - struct lh_entry *prev; -}; - - -/** - * The hash table structure. - */ -struct lh_table { - /** - * Size of our hash. - */ - int size; - /** - * Numbers of entries. - */ - int count; - - /** - * Number of collisions. - */ - int collisions; - - /** - * Number of resizes. - */ - int resizes; - - /** - * Number of lookups. - */ - int lookups; - - /** - * Number of inserts. - */ - int inserts; - - /** - * Number of deletes. - */ - int deletes; - - /** - * Name of the hash table. - */ - const char *name; - - /** - * The first entry. - */ - struct lh_entry *head; - - /** - * The last entry. - */ - struct lh_entry *tail; - - struct lh_entry *table; - - /** - * A pointer onto the function responsible for freeing an entry. - */ - lh_entry_free_fn *free_fn; - lh_hash_fn *hash_fn; - lh_equal_fn *equal_fn; -}; - - -/** - * Pre-defined hash and equality functions - */ -extern unsigned long lh_ptr_hash(const void *k); -extern int lh_ptr_equal(const void *k1, const void *k2); - -extern unsigned long lh_char_hash(const void *k); -extern int lh_char_equal(const void *k1, const void *k2); - - -/** - * Convenience list iterator. - */ -#define lh_foreach(table, entry) \ -for(entry = table->head; entry; entry = entry->next) - -/** - * lh_foreach_safe allows calling of deletion routine while iterating. - */ -#define lh_foreach_safe(table, entry, tmp) \ -for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) - - - -/** - * Create a new linkhash table. - * @param size initial table size. The table is automatically resized - * although this incurs a performance penalty. - * @param name the table name. - * @param free_fn callback function used to free memory for entries - * when lh_table_free or lh_table_delete is called. - * If NULL is provided, then memory for keys and values - * must be freed by the caller. - * @param hash_fn function used to hash keys. 2 standard ones are defined: - * lh_ptr_hash and lh_char_hash for hashing pointer values - * and C strings respectively. - * @param equal_fn comparison function to compare keys. 2 standard ones defined: - * lh_ptr_hash and lh_char_hash for comparing pointer values - * and C strings respectively. - * @return a pointer onto the linkhash table. - */ -extern struct lh_table* lh_table_new(int size, const char *name, - lh_entry_free_fn *free_fn, - lh_hash_fn *hash_fn, - lh_equal_fn *equal_fn); - -/** - * Convenience function to create a new linkhash - * table with char keys. - * @param size initial table size. - * @param name table name. - * @param free_fn callback function used to free memory for entries. - * @return a pointer onto the linkhash table. - */ -extern struct lh_table* lh_kchar_table_new(int size, const char *name, - lh_entry_free_fn *free_fn); - - -/** - * Convenience function to create a new linkhash - * table with ptr keys. - * @param size initial table size. - * @param name table name. - * @param free_fn callback function used to free memory for entries. - * @return a pointer onto the linkhash table. - */ -extern struct lh_table* lh_kptr_table_new(int size, const char *name, - lh_entry_free_fn *free_fn); - - -/** - * Free a linkhash table. - * If a callback free function is provided then it is called for all - * entries in the table. - * @param t table to free. - */ -extern void lh_table_free(struct lh_table *t); - - -/** - * Insert a record into the table. - * @param t the table to insert into. - * @param k a pointer to the key to insert. - * @param v a pointer to the value to insert. - */ -extern int lh_table_insert(struct lh_table *t, void *k, const void *v); - - -/** - * Lookup a record into the table. - * @param t the table to lookup - * @param k a pointer to the key to lookup - * @return a pointer to the record structure of the value or NULL if it does not exist. - */ -extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); - -/** - * Lookup a record into the table - * @param t the table to lookup - * @param k a pointer to the key to lookup - * @return a pointer to the found value or NULL if it does not exist. - * @deprecated Use lh_table_lookup_ex instead. - */ -extern const void* lh_table_lookup(struct lh_table *t, const void *k); - -/** - * Lookup a record in the table - * @param t the table to lookup - * @param k a pointer to the key to lookup - * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist). - * @return whether or not the key was found - */ -extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v); - -/** - * Delete a record from the table. - * If a callback free function is provided then it is called for the - * for the item being deleted. - * @param t the table to delete from. - * @param e a pointer to the entry to delete. - * @return 0 if the item was deleted. - * @return -1 if it was not found. - */ -extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); - - -/** - * Delete a record from the table. - * If a callback free function is provided then it is called for the - * for the item being deleted. - * @param t the table to delete from. - * @param k a pointer to the key to delete. - * @return 0 if the item was deleted. - * @return -1 if it was not found. - */ -extern int lh_table_delete(struct lh_table *t, const void *k); - - -void lh_abort(const char *msg, ...); -void lh_table_resize(struct lh_table *t, int new_size); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _linkhash_h_ +#define _linkhash_h_ + +#include "json_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * golden prime used in hash functions + */ +#define LH_PRIME 0x9e370001UL + +/** + * The fraction of filled hash buckets until an insert will cause the table + * to be resized. + * This can range from just above 0 up to 1.0. + */ +#define LH_LOAD_FACTOR 0.66 + +/** + * sentinel pointer value for empty slots + */ +#define LH_EMPTY (void*)-1 + +/** + * sentinel pointer value for freed slots + */ +#define LH_FREED (void*)-2 + +struct lh_entry; + +/** + * callback function prototypes + */ +typedef void (lh_entry_free_fn) (struct lh_entry *e); +/** + * callback function prototypes + */ +typedef unsigned long (lh_hash_fn) (const void *k); +/** + * callback function prototypes + */ +typedef int (lh_equal_fn) (const void *k1, const void *k2); + +/** + * An entry in the hash table + */ +struct lh_entry { + /** + * The key. + */ + void *k; + /** + * The value. + */ + const void *v; + /** + * The next entry + */ + struct lh_entry *next; + /** + * The previous entry. + */ + struct lh_entry *prev; +}; + + +/** + * The hash table structure. + */ +struct lh_table { + /** + * Size of our hash. + */ + int size; + /** + * Numbers of entries. + */ + int count; + + /** + * Number of collisions. + */ + int collisions; + + /** + * Number of resizes. + */ + int resizes; + + /** + * Number of lookups. + */ + int lookups; + + /** + * Number of inserts. + */ + int inserts; + + /** + * Number of deletes. + */ + int deletes; + + /** + * Name of the hash table. + */ + const char *name; + + /** + * The first entry. + */ + struct lh_entry *head; + + /** + * The last entry. + */ + struct lh_entry *tail; + + struct lh_entry *table; + + /** + * A pointer onto the function responsible for freeing an entry. + */ + lh_entry_free_fn *free_fn; + lh_hash_fn *hash_fn; + lh_equal_fn *equal_fn; +}; + + +/** + * Pre-defined hash and equality functions + */ +extern unsigned long lh_ptr_hash(const void *k); +extern int lh_ptr_equal(const void *k1, const void *k2); + +extern unsigned long lh_char_hash(const void *k); +extern int lh_char_equal(const void *k1, const void *k2); + + +/** + * Convenience list iterator. + */ +#define lh_foreach(table, entry) \ +for(entry = table->head; entry; entry = entry->next) + +/** + * lh_foreach_safe allows calling of deletion routine while iterating. + */ +#define lh_foreach_safe(table, entry, tmp) \ +for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) + + + +/** + * Create a new linkhash table. + * @param size initial table size. The table is automatically resized + * although this incurs a performance penalty. + * @param name the table name. + * @param free_fn callback function used to free memory for entries + * when lh_table_free or lh_table_delete is called. + * If NULL is provided, then memory for keys and values + * must be freed by the caller. + * @param hash_fn function used to hash keys. 2 standard ones are defined: + * lh_ptr_hash and lh_char_hash for hashing pointer values + * and C strings respectively. + * @param equal_fn comparison function to compare keys. 2 standard ones defined: + * lh_ptr_hash and lh_char_hash for comparing pointer values + * and C strings respectively. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_table_new(int size, const char *name, + lh_entry_free_fn *free_fn, + lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn); + +/** + * Convenience function to create a new linkhash + * table with char keys. + * @param size initial table size. + * @param name table name. + * @param free_fn callback function used to free memory for entries. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_kchar_table_new(int size, const char *name, + lh_entry_free_fn *free_fn); + + +/** + * Convenience function to create a new linkhash + * table with ptr keys. + * @param size initial table size. + * @param name table name. + * @param free_fn callback function used to free memory for entries. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_kptr_table_new(int size, const char *name, + lh_entry_free_fn *free_fn); + + +/** + * Free a linkhash table. + * If a callback free function is provided then it is called for all + * entries in the table. + * @param t table to free. + */ +extern void lh_table_free(struct lh_table *t); + + +/** + * Insert a record into the table. + * @param t the table to insert into. + * @param k a pointer to the key to insert. + * @param v a pointer to the value to insert. + */ +extern int lh_table_insert(struct lh_table *t, void *k, const void *v); + + +/** + * Lookup a record into the table. + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @return a pointer to the record structure of the value or NULL if it does not exist. + */ +extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); + +/** + * Lookup a record into the table + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @return a pointer to the found value or NULL if it does not exist. + * @deprecated Use lh_table_lookup_ex instead. + */ +THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k)); + +/** + * Lookup a record in the table + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist). + * @return whether or not the key was found + */ +extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v); + +/** + * Delete a record from the table. + * If a callback free function is provided then it is called for the + * for the item being deleted. + * @param t the table to delete from. + * @param e a pointer to the entry to delete. + * @return 0 if the item was deleted. + * @return -1 if it was not found. + */ +extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); + + +/** + * Delete a record from the table. + * If a callback free function is provided then it is called for the + * for the item being deleted. + * @param t the table to delete from. + * @param k a pointer to the key to delete. + * @return 0 if the item was deleted. + * @return -1 if it was not found. + */ +extern int lh_table_delete(struct lh_table *t, const void *k); + +extern int lh_table_length(struct lh_table *t); + +void lh_abort(const char *msg, ...); +void lh_table_resize(struct lh_table *t, int new_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/json-c/src/printbuf.c b/json-c/src/printbuf.c index b951c7b..a9533a1 100644 --- a/json-c/src/printbuf.c +++ b/json-c/src/printbuf.c @@ -1,192 +1,193 @@ -/* - * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - * - * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. - * The copyrights to the contents of this file are licensed under the MIT License - * (http://www.opensource.org/licenses/mit-license.php) - */ - -#include "config.h" - -#include -#include -#include - -#if HAVE_STDARG_H -# include -#else /* !HAVE_STDARG_H */ -# error Not enough var arg support! -#endif /* HAVE_STDARG_H */ - -#include "bits.h" -#include "debug.h" -#include "printbuf.h" - -static int printbuf_extend(struct printbuf *p, int min_size); - -struct printbuf* printbuf_new(void) -{ - struct printbuf *p; - - p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); - if(!p) return NULL; - p->size = 32; - p->bpos = 0; - if(!(p->buf = (char*)malloc(p->size))) { - free(p); - return NULL; - } - return p; -} - - -/** - * Extend the buffer p so it has a size of at least min_size. - * - * If the current size is large enough, nothing is changed. - * - * Note: this does not check the available space! The caller - * is responsible for performing those calculations. - */ -static int printbuf_extend(struct printbuf *p, int min_size) -{ - char *t; - int new_size; - - if (p->size >= min_size) - return 0; - - new_size = json_max(p->size * 2, min_size + 8); -#ifdef PRINTBUF_DEBUG - MC_DEBUG("printbuf_memappend: realloc " - "bpos=%d min_size=%d old_size=%d new_size=%d\n", - p->bpos, min_size, p->size, new_size); -#endif /* PRINTBUF_DEBUG */ - if(!(t = (char*)realloc(p->buf, new_size))) - return -1; - p->size = new_size; - p->buf = t; - return 0; -} - -int printbuf_memappend(struct printbuf *p, const char *buf, int size) -{ - if (p->size <= p->bpos + size + 1) { - if (printbuf_extend(p, p->bpos + size + 1) < 0) - return -1; - } - memcpy(p->buf + p->bpos, buf, size); - p->bpos += size; - p->buf[p->bpos]= '\0'; - return size; -} - -int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) -{ - int size_needed; - - if (offset == -1) - offset = pb->bpos; - size_needed = offset + len; - if (pb->size < size_needed) - { - if (printbuf_extend(pb, size_needed) < 0) - return -1; - } - - memset(pb->buf + offset, charvalue, len); - if (pb->bpos < size_needed) - pb->bpos = size_needed; - - return 0; -} - -#if !HAVE_VSNPRINTF && defined(_MSC_VER) -# define vsnprintf _vsnprintf -#elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */ -# error Need vsnprintf! -#endif /* !HAVE_VSNPRINTF && defined(WIN32) */ - -#if !HAVE_VASPRINTF -/* CAW: compliant version of vasprintf */ -static int vasprintf(char **buf, const char *fmt, va_list ap) -{ -#ifndef WIN32 - static char _T_emptybuffer = '\0'; -#endif /* !defined(WIN32) */ - int chars; - char *b; - - if(!buf) { return -1; } - -#ifdef WIN32 - chars = _vscprintf(fmt, ap)+1; -#else /* !defined(WIN32) */ - /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite - our buffer like on some 64bit sun systems.... but hey, its time to move on */ - chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; - if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ -#endif /* defined(WIN32) */ - - b = (char*)malloc(sizeof(char)*chars); - if(!b) { return -1; } - - if((chars = vsprintf(b, fmt, ap)) < 0) - { - free(b); - } else { - *buf = b; - } - - return chars; -} -#endif /* !HAVE_VASPRINTF */ - -int sprintbuf(struct printbuf *p, const char *msg, ...) -{ - va_list ap; - char *t; - int size; - char buf[128]; - - /* user stack buffer first */ - va_start(ap, msg); - size = vsnprintf(buf, 128, msg, ap); - va_end(ap); - /* if string is greater than stack buffer, then use dynamic string - with vasprintf. Note: some implementation of vsnprintf return -1 - if output is truncated whereas some return the number of bytes that - would have been written - this code handles both cases. */ - if(size == -1 || size > 127) { - va_start(ap, msg); - if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } - va_end(ap); - printbuf_memappend(p, t, size); - free(t); - return size; - } else { - printbuf_memappend(p, buf, size); - return size; - } -} - -void printbuf_reset(struct printbuf *p) -{ - p->buf[0] = '\0'; - p->bpos = 0; -} - -void printbuf_free(struct printbuf *p) -{ - if(p) { - free(p->buf); - free(p); - } -} +/* + * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_STDARG_H +# include +#else /* !HAVE_STDARG_H */ +# error Not enough var arg support! +#endif /* HAVE_STDARG_H */ + +#include "debug.h" +#include "printbuf.h" + +static int printbuf_extend(struct printbuf *p, int min_size); + +struct printbuf* printbuf_new(void) +{ + struct printbuf *p; + + p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); + if(!p) return NULL; + p->size = 32; + p->bpos = 0; + if(!(p->buf = (char*)malloc(p->size))) { + free(p); + return NULL; + } + return p; +} + + +/** + * Extend the buffer p so it has a size of at least min_size. + * + * If the current size is large enough, nothing is changed. + * + * Note: this does not check the available space! The caller + * is responsible for performing those calculations. + */ +static int printbuf_extend(struct printbuf *p, int min_size) +{ + char *t; + int new_size; + + if (p->size >= min_size) + return 0; + + new_size = p->size * 2; + if (new_size < min_size + 8) + new_size = min_size + 8; +#ifdef PRINTBUF_DEBUG + MC_DEBUG("printbuf_memappend: realloc " + "bpos=%d min_size=%d old_size=%d new_size=%d\n", + p->bpos, min_size, p->size, new_size); +#endif /* PRINTBUF_DEBUG */ + if(!(t = (char*)realloc(p->buf, new_size))) + return -1; + p->size = new_size; + p->buf = t; + return 0; +} + +int printbuf_memappend(struct printbuf *p, const char *buf, int size) +{ + if (p->size <= p->bpos + size + 1) { + if (printbuf_extend(p, p->bpos + size + 1) < 0) + return -1; + } + memcpy(p->buf + p->bpos, buf, size); + p->bpos += size; + p->buf[p->bpos]= '\0'; + return size; +} + +int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) +{ + int size_needed; + + if (offset == -1) + offset = pb->bpos; + size_needed = offset + len; + if (pb->size < size_needed) + { + if (printbuf_extend(pb, size_needed) < 0) + return -1; + } + + memset(pb->buf + offset, charvalue, len); + if (pb->bpos < size_needed) + pb->bpos = size_needed; + + return 0; +} + +#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER) +# define vsnprintf _vsnprintf +#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */ +# error Need vsnprintf! +#endif /* !HAVE_VSNPRINTF && defined(WIN32) */ + +#if !defined(HAVE_VASPRINTF) +/* CAW: compliant version of vasprintf */ +static int vasprintf(char **buf, const char *fmt, va_list ap) +{ +#ifndef WIN32 + static char _T_emptybuffer = '\0'; +#endif /* !defined(WIN32) */ + int chars; + char *b; + + if(!buf) { return -1; } + +#ifdef WIN32 + chars = _vscprintf(fmt, ap)+1; +#else /* !defined(WIN32) */ + /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite + our buffer like on some 64bit sun systems.... but hey, its time to move on */ + chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; + if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ +#endif /* defined(WIN32) */ + + b = (char*)malloc(sizeof(char)*chars); + if(!b) { return -1; } + + if((chars = vsprintf(b, fmt, ap)) < 0) + { + free(b); + } else { + *buf = b; + } + + return chars; +} +#endif /* !HAVE_VASPRINTF */ + +int sprintbuf(struct printbuf *p, const char *msg, ...) +{ + va_list ap; + char *t; + int size; + char buf[128]; + + /* user stack buffer first */ + va_start(ap, msg); + size = vsnprintf(buf, 128, msg, ap); + va_end(ap); + /* if string is greater than stack buffer, then use dynamic string + with vasprintf. Note: some implementation of vsnprintf return -1 + if output is truncated whereas some return the number of bytes that + would have been written - this code handles both cases. */ + if(size == -1 || size > 127) { + va_start(ap, msg); + if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } + va_end(ap); + printbuf_memappend(p, t, size); + free(t); + return size; + } else { + printbuf_memappend(p, buf, size); + return size; + } +} + +void printbuf_reset(struct printbuf *p) +{ + p->buf[0] = '\0'; + p->bpos = 0; +} + +void printbuf_free(struct printbuf *p) +{ + if(p) { + free(p->buf); + free(p); + } +} diff --git a/json-c/src/printbuf.h b/json-c/src/printbuf.h index b1bde7f..e35d1e0 100644 --- a/json-c/src/printbuf.h +++ b/json-c/src/printbuf.h @@ -1,77 +1,77 @@ -/* - * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ - * - * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. - * Michael Clark - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See COPYING for details. - * - * - * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. - * The copyrights to the contents of this file are licensed under the MIT License - * (http://www.opensource.org/licenses/mit-license.php) - */ - -#ifndef _printbuf_h_ -#define _printbuf_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -struct printbuf { - char *buf; - int bpos; - int size; -}; - -extern struct printbuf* -printbuf_new(void); - -/* As an optimization, printbuf_memappend_fast is defined as a macro - * that handles copying data if the buffer is large enough; otherwise - * it invokes printbuf_memappend_real() which performs the heavy - * lifting of realloc()ing the buffer and copying data. - * Your code should not use printbuf_memappend directly--use - * printbuf_memappend_fast instead. - */ -extern int -printbuf_memappend(struct printbuf *p, const char *buf, int size); - -#define printbuf_memappend_fast(p, bufptr, bufsize) \ -do { \ - if ((p->size - p->bpos) > bufsize) { \ - memcpy(p->buf + p->bpos, (bufptr), bufsize); \ - p->bpos += bufsize; \ - p->buf[p->bpos]= '\0'; \ - } else { printbuf_memappend(p, (bufptr), bufsize); } \ -} while (0) - -#define printbuf_length(p) ((p)->bpos) - -/** - * Set len bytes of the buffer to charvalue, starting at offset offset. - * Similar to calling memset(x, charvalue, len); - * - * The memory allocated for the buffer is extended as necessary. - * - * If offset is -1, this starts at the end of the current data in the buffer. - */ -extern int -printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); - -extern int -sprintbuf(struct printbuf *p, const char *msg, ...); - -extern void -printbuf_reset(struct printbuf *p); - -extern void -printbuf_free(struct printbuf *p); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#ifndef _printbuf_h_ +#define _printbuf_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct printbuf { + char *buf; + int bpos; + int size; +}; + +extern struct printbuf* +printbuf_new(void); + +/* As an optimization, printbuf_memappend_fast is defined as a macro + * that handles copying data if the buffer is large enough; otherwise + * it invokes printbuf_memappend_real() which performs the heavy + * lifting of realloc()ing the buffer and copying data. + * Your code should not use printbuf_memappend directly--use + * printbuf_memappend_fast instead. + */ +extern int +printbuf_memappend(struct printbuf *p, const char *buf, int size); + +#define printbuf_memappend_fast(p, bufptr, bufsize) \ +do { \ + if ((p->size - p->bpos) > bufsize) { \ + memcpy(p->buf + p->bpos, (bufptr), bufsize); \ + p->bpos += bufsize; \ + p->buf[p->bpos]= '\0'; \ + } else { printbuf_memappend(p, (bufptr), bufsize); } \ +} while (0) + +#define printbuf_length(p) ((p)->bpos) + +/** + * Set len bytes of the buffer to charvalue, starting at offset offset. + * Similar to calling memset(x, charvalue, len); + * + * The memory allocated for the buffer is extended as necessary. + * + * If offset is -1, this starts at the end of the current data in the buffer. + */ +extern int +printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); + +extern int +sprintbuf(struct printbuf *p, const char *msg, ...); + +extern void +printbuf_reset(struct printbuf *p); + +extern void +printbuf_free(struct printbuf *p); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3