Browse Source

merge upstream/master

pull/362/head
Joel Winarske 8 years ago
parent
commit
1dbf999383
72 changed files with 701 additions and 395 deletions
  1. +8
    -1
      .gitignore
  2. +2
    -1
      .travis.yml
  3. +27
    -5
      CMakeLists.txt
  4. +3
    -0
      INSTALL
  5. +39
    -7
      Makefile.am
  6. +58
    -1
      README.md
  7. +2
    -1
      arraylist.c
  8. +24
    -4
      config.h.win32
  9. +23
    -1
      configure.ac
  10. +122
    -53
      json_object.c
  11. +85
    -48
      json_object.h
  12. +2
    -0
      json_object_private.h
  13. +2
    -1
      json_pointer.c
  14. +9
    -9
      json_tokener.h
  15. +58
    -40
      json_util.c
  16. +12
    -1
      json_util.h
  17. +4
    -4
      linkhash.c
  18. +1
    -0
      printbuf.c
  19. +1
    -1
      random_seed.c
  20. +36
    -0
      snprintf_compat.h
  21. +9
    -2
      strerror_override.c
  22. +25
    -0
      strerror_override.h
  23. +7
    -0
      strerror_override_private.h
  24. +1
    -1
      tests/Makefile.am
  25. +8
    -0
      tests/test-defs.sh
  26. +13
    -0
      tests/test1.c
  27. +2
    -0
      tests/test1.expected
  28. +2
    -0
      tests/test1Formatted_plain.expected
  29. +2
    -0
      tests/test1Formatted_pretty.expected
  30. +2
    -0
      tests/test1Formatted_spaced.expected
  31. +0
    -12
      tests/test4.test
  32. +1
    -0
      tests/test4.test
  33. +0
    -12
      tests/testReplaceExisting.test
  34. +1
    -0
      tests/testReplaceExisting.test
  35. +19
    -0
      tests/test_basic.test
  36. +0
    -12
      tests/test_cast.test
  37. +1
    -0
      tests/test_cast.test
  38. +0
    -12
      tests/test_charcase.test
  39. +1
    -0
      tests/test_charcase.test
  40. +0
    -12
      tests/test_compare.test
  41. +1
    -0
      tests/test_compare.test
  42. +26
    -0
      tests/test_double_serializer.c
  43. +6
    -0
      tests/test_double_serializer.expected
  44. +0
    -12
      tests/test_double_serializer.test
  45. +1
    -0
      tests/test_double_serializer.test
  46. +0
    -12
      tests/test_float.test
  47. +1
    -0
      tests/test_float.test
  48. +4
    -1
      tests/test_json_pointer.c
  49. +0
    -12
      tests/test_json_pointer.test
  50. +1
    -0
      tests/test_json_pointer.test
  51. +1
    -0
      tests/test_locale.c
  52. +0
    -12
      tests/test_locale.test
  53. +1
    -0
      tests/test_locale.test
  54. +0
    -12
      tests/test_null.test
  55. +1
    -0
      tests/test_null.test
  56. +0
    -12
      tests/test_parse.test
  57. +1
    -0
      tests/test_parse.test
  58. +0
    -12
      tests/test_parse_int64.test
  59. +1
    -0
      tests/test_parse_int64.test
  60. +0
    -12
      tests/test_printbuf.test
  61. +1
    -0
      tests/test_printbuf.test
  62. +0
    -12
      tests/test_set_serializer.test
  63. +1
    -0
      tests/test_set_serializer.test
  64. +0
    -12
      tests/test_set_value.test
  65. +1
    -0
      tests/test_set_value.test
  66. +24
    -1
      tests/test_util_file.c
  67. +14
    -0
      tests/test_util_file.expected
  68. +0
    -15
      tests/test_util_file.test
  69. +1
    -0
      tests/test_util_file.test
  70. +0
    -12
      tests/test_visit.test
  71. +1
    -0
      tests/test_visit.test
  72. +1
    -5
      vasprintf_compat.h

+ 8
- 1
.gitignore View File

@@ -72,7 +72,6 @@
*.dmg *.dmg
*.ipa *.ipa


/INSTALL
.deps/ .deps/
.libs/ .libs/
/aclocal.m4 /aclocal.m4
@@ -99,3 +98,11 @@
/missing /missing
/stamp-h1 /stamp-h1
/stamp-h2 /stamp-h2

# cmake auto-generated files
/CMakeCache.txt
/CMakeFiles
/cmake_install.cmake
/include
/libjson-c.a
/libjson-c.so

+ 2
- 1
.travis.yml View File

@@ -16,6 +16,7 @@ os:
before_install: before_install:
- echo $LANG - echo $LANG
- echo $LC_ALL - echo $LC_ALL
- set -e
install: install:
- sh autogen.sh - sh autogen.sh
@@ -28,4 +29,4 @@ script:
after_success: after_success:
- make check - make check
- cppcheck --quiet *.h *.c tests/
- if type cppcheck &> /dev/null ; then cppcheck --error-exitcode=1 --quiet *.h *.c tests/ ; fi

+ 27
- 5
CMakeLists.txt View File

@@ -11,12 +11,24 @@ if(MSVC)
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/config.h) file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/config.h)
file(COPY ./json_config.h.win32 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/) file(COPY ./json_config.h.win32 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h) file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h)
elseif(MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -D_GNU_SOURCE=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -D_GNU_SOURCE=1")
if (MSYS OR CMAKE_GENERATOR STREQUAL "Unix Makefiles")
execute_process(COMMAND echo ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND sh autogen.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND sh ./configure WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
file(COPY ./config.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
file(COPY ./json_config.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
else()
file(COPY ./config.h.win32 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/config.h)
file(COPY ./json_config.h.win32 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h.win32 ${CMAKE_CURRENT_BINARY_DIR}/include/json_config.h)
endif()
elseif(UNIX) elseif(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
if(CMAKE_COMPILER_IS_GNUCC)
add_definitions(-D_GNU_SOURCE)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -D_GNU_SOURCE")
execute_process(COMMAND echo ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) execute_process(COMMAND echo ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND sh autogen.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) execute_process(COMMAND sh autogen.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND ./configure WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) execute_process(COMMAND ./configure WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
@@ -56,16 +68,26 @@ set(JSON_C_SOURCES
./linkhash.c ./linkhash.c
./printbuf.c ./printbuf.c
./random_seed.c ./random_seed.c
./strerror_override.c
) )


add_library(json-c add_library(json-c
SHARED
${JSON_C_SOURCES}
${JSON_C_HEADERS}
)

add_library(json-c-static
STATIC
${JSON_C_SOURCES} ${JSON_C_SOURCES}
${JSON_C_HEADERS} ${JSON_C_HEADERS}
) )


set_property(TARGET json-c PROPERTY C_STANDARD 99) set_property(TARGET json-c PROPERTY C_STANDARD 99)
set_property(TARGET json-c-static PROPERTY C_STANDARD 99)
set_target_properties(json-c-static PROPERTIES OUTPUT_NAME json-c)


install(TARGETS json-c
install(TARGETS json-c json-c-static
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib


+ 3
- 0
INSTALL View File

@@ -0,0 +1,3 @@

See README.md for installation instructions.


+ 39
- 7
Makefile.am View File

@@ -1,6 +1,6 @@
EXTRA_DIST = README.md README.html README-WIN32.html EXTRA_DIST = README.md README.html README-WIN32.html
EXTRA_DIST += config.h.win32 json-c.vcproj json-c.vcxproj json-c.vcxproj.filters EXTRA_DIST += config.h.win32 json-c.vcproj json-c.vcxproj json-c.vcxproj.filters
EXTRA_DIST += Doxyfile doc
EXTRA_DIST += Doxyfile


dist-hook: dist-hook:
test -d "$(distdir)/doc" || mkdir "$(distdir)/doc" test -d "$(distdir)/doc" || mkdir "$(distdir)/doc"
@@ -35,7 +35,8 @@ libjson_cinclude_HEADERS = \
strdup_compat.h \ strdup_compat.h \
vasprintf_compat.h \ vasprintf_compat.h \
printbuf.h \ printbuf.h \
random_seed.h
random_seed.h \
strerror_override.h


libjson_c_la_LDFLAGS = -version-info 3:0:0 -no-undefined @JSON_BSYMBOLIC_LDFLAGS@ libjson_c_la_LDFLAGS = -version-info 3:0:0 -no-undefined @JSON_BSYMBOLIC_LDFLAGS@


@@ -51,16 +52,47 @@ libjson_c_la_SOURCES = \
json_visit.c \ json_visit.c \
linkhash.c \ linkhash.c \
printbuf.c \ printbuf.c \
random_seed.c
random_seed.c \
strerror_override.c \
strerror_override_private.h




DISTCLEANFILES=
DISTCLEANFILES+= \
config.h \
json-c-uninstalled.pc \
json-c.pc \
json_config.h

distclean-local: distclean-local:
-rm -rf $(testsubdir) -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
JSON_CLEANFILES=
JSON_CLEANFILES+= \
Makefile.in \
aclocal.m4 \
autom4te.cache/ \
compile \
config.guess \
config.h.in \
config.sub \
configure \
depcomp \
install-sh \
ltmain.sh \
missing \
test-driver \
tests/Makefile.in
JSON_CLEANFILES+= \
libtool \
stamp-h1 \
stamp-h2

# There's no built-in way to remove these after all the other
# maintainer-clean steps happen, so do it explicitly here.
really-clean:
$(MAKE) maintainer-clean
rm -rf ${JSON_CLEANFILES}


uninstall-local: uninstall-local:
rm -rf "$(DESTDIR)@includedir@/json-c" rm -rf "$(DESTDIR)@includedir@/json-c"


+ 58
- 1
README.md View File

@@ -4,6 +4,10 @@
JSON-C - A JSON implementation in C JSON-C - A JSON implementation in C
----------------------------------- -----------------------------------


Build Status
* [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/json-c/json-c?branch=master&svg=true)](https://ci.appveyor.com/project/hawicz/json-c)
* [![Travis Build Status](https://travis-ci.org/json-c/json-c.svg?branch=master)](https://travis-ci.org/json-c/json-c)

JSON-C implements a reference counting object model that allows you to easily 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 construct JSON objects in C, output them as JSON formatted strings and parse
JSON formatted strings back into the C representation of JSON objects. JSON formatted strings back into the C representation of JSON objects.
@@ -14,7 +18,9 @@ Building on Unix with `git`, `gcc` and `autotools`


Home page for json-c: https://github.com/json-c/json-c/wiki Home page for json-c: https://github.com/json-c/json-c/wiki


Prerequisites:
### Prerequisites:

See also the "Installing prerequisites" section below.


- `gcc`, `clang`, or another C compiler - `gcc`, `clang`, or another C compiler
- `libtool>=2.2.6b` - `libtool>=2.2.6b`
@@ -26,6 +32,8 @@ If you're not using a release tarball, you'll also need:


Make sure you have a complete `libtool` install, including `libtoolize`. Make sure you have a complete `libtool` install, including `libtoolize`.


### Build instructions:

`json-c` GitHub repo: https://github.com/json-c/json-c `json-c` GitHub repo: https://github.com/json-c/json-c


```sh ```sh
@@ -66,3 +74,52 @@ JSON_C_DIR=/path/to/json_c/install
CFLAGS += -I$(JSON_C_DIR)/include/json-c CFLAGS += -I$(JSON_C_DIR)/include/json-c
LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
``` ```


Install prerequisites
-----------------------

If you are on a relatively modern system, you'll likely be able to install
the prerequisites using your OS's packaging system.

### Install using apt (e.g. Ubuntu 16.04.2 LTS)
```sh
sudo apt install git
sudo apt install autoconf automake libtool
sudo apt install valgrind # optional
```

Then start from the "git clone" command, above.

### Manually install and build autoconf, automake and libtool

For older OS's that don't have up-to-date version of the packages will
require a bit more work. For example, CentOS release 5.11, etc...

```sh
curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
curl -O http://ftp.gnu.org/gnu/libtool/libtool-2.2.6b.tar.gz

tar xzf autoconf-2.69.tar.gz
tar xzf automake-1.15.tar.gz
tar xzf libtool-2.2.6b.tar.gz

export PATH=${HOME}/ac_install/bin:$PATH

(cd autoconf-2.69 && \
./configure --prefix ${HOME}/ac_install && \
make && \
make install)

(cd automake-1.15 && \
./configure --prefix ${HOME}/ac_install && \
make && \
make install)

(cd libtool-2.2.6b && \
./configure --prefix ${HOME}/ac_install && \
make && \
make install)
```


+ 2
- 1
arraylist.c View File

@@ -98,7 +98,8 @@ array_list_put_idx(struct array_list *arr, size_t idx, void *data)
{ {
if (idx > SIZE_T_MAX - 1 ) return -1; if (idx > SIZE_T_MAX - 1 ) return -1;
if(array_list_expand_internal(arr, idx+1)) return -1; if(array_list_expand_internal(arr, idx+1)) return -1;
if(arr->array[idx]) arr->free_fn(arr->array[idx]);
if(idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data; arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1; if(arr->length <= idx) arr->length = idx + 1;
return 0; return 0;


+ 24
- 4
config.h.win32 View File

@@ -8,24 +8,24 @@
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you /* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */ don't. */
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
#define HAVE_DECL_INFINITY 1 #define HAVE_DECL_INFINITY 1
#endif #endif
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. /* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/ */
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
#define HAVE_DECL_ISINF 1 #define HAVE_DECL_ISINF 1
#endif #endif
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. /* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/ */
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
#define HAVE_DECL_ISNAN 1 #define HAVE_DECL_ISNAN 1
#endif #endif
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ /* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#if defined(_MSC_VER) && _MSC_VER >= 1800
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || defined(__MINGW32__)
#define HAVE_DECL_NAN 1 #define HAVE_DECL_NAN 1
#endif #endif
@@ -76,7 +76,11 @@
#define HAVE_SETLOCALE 1 #define HAVE_SETLOCALE 1
/* Define to 1 if you have the `snprintf' function. */ /* Define to 1 if you have the `snprintf' function. */
#if defined(__MINGW32__)
#define HAVE_SNPRINTF 1
#else
#undef HAVE_SNPRINTF #undef HAVE_SNPRINTF
#endif
/* Define to 1 if you have the <stdarg.h> header file. */ /* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1 #define HAVE_STDARG_H 1
@@ -103,7 +107,11 @@
#define HAVE_STRING_H 1 #define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */ /* Define to 1 if you have the `strncasecmp' function. */
#if defined(__MINGW32__)
#define HAVE_STRNCASECMP 1
#else
#undef HAVE_STRNCASECMP #undef HAVE_STRNCASECMP
#endif
/* Define to 1 if you have the <syslog.h> header file. */ /* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H #undef HAVE_SYSLOG_H
@@ -112,7 +120,11 @@
#define HAVE_SYS_CDEFS_H 1 #define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/param.h> header file. */ /* Define to 1 if you have the <sys/param.h> header file. */
#if defined(__MINGW32__)
#define HAVE_SYS_PARAM_H 1
#else
#undef HAVE_SYS_PARAM_H #undef HAVE_SYS_PARAM_H
#endif
/* Define to 1 if you have the <sys/stat.h> header file. */ /* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 1
@@ -121,10 +133,18 @@
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#else
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
#endif
/* Define to 1 if you have the `vasprintf' function. */ /* Define to 1 if you have the `vasprintf' function. */
#if defined(__MINGW32__)
#define HAVE_VASPRINTF 1
#else
#undef HAVE_VASPRINTF #undef HAVE_VASPRINTF
#endif
/* Define to 1 if you have the `vprintf' function. */ /* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1 #define HAVE_VPRINTF 1


+ 23
- 1
configure.ac View File

@@ -7,6 +7,8 @@ AM_INIT_AUTOMAKE


AC_PROG_MAKE_SET AC_PROG_MAKE_SET


AC_CANONICAL_HOST

AC_ARG_ENABLE(rdrand, AC_ARG_ENABLE(rdrand,
AS_HELP_STRING([--enable-rdrand], AS_HELP_STRING([--enable-rdrand],
[Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]), [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]),
@@ -41,6 +43,18 @@ AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public defin
AC_C_CONST AC_C_CONST
AC_TYPE_SIZE_T AC_TYPE_SIZE_T


AC_CACHE_CHECK([for __thread support], ac_cv___thread, [dnl
AC_LINK_IFELSE([dnl
AC_LANG_PROGRAM([[#undef __thread
static __thread int a; int foo (int b) { return a + b; }]],
[[exit (foo (0));]])],
ac_cv___thread=yes, ac_cv___thread=no)
])
AS_IF([test "x$ac_cv___thread" != xno],
[AC_DEFINE(HAVE___THREAD, 1, [Have __thread])
AC_DEFINE(SPEC___THREAD, [__thread], [Specifier for __thread])]
)

# Checks for library functions. # Checks for library functions.
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_FUNC_MEMCMP AC_FUNC_MEMCMP
@@ -53,6 +67,14 @@ AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]]) AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]])
AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]]) AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]])


case "${host_os}" in
linux*)
AC_CHECK_FUNCS([uselocale])
;;
*) # Nothing
;;
esac

if test "$ac_cv_have_decl_isnan" = "yes" ; then if test "$ac_cv_have_decl_isnan" = "yes" ; then
AC_TRY_LINK([#include <math.h>], [float f = 0.0; return isnan(f)], [], [LIBS="$LIBS -lm"]) AC_TRY_LINK([#include <math.h>], [float f = 0.0; return isnan(f)], [], [LIBS="$LIBS -lm"])
fi fi
@@ -75,7 +97,7 @@ int main(int c,char* v) {return 0;}


AC_LANG_POP([C]) AC_LANG_POP([C])


AM_PROG_LIBTOOL
LT_INIT


# Check for the -Bsymbolic-functions linker flag # Check for the -Bsymbolic-functions linker flag
AC_ARG_ENABLE([Bsymbolic], AC_ARG_ENABLE([Bsymbolic],


+ 122
- 53
json_object.c View File

@@ -12,13 +12,14 @@


#include "config.h" #include "config.h"


#include "strerror_override.h"

#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <errno.h>


#include "debug.h" #include "debug.h"
#include "printbuf.h" #include "printbuf.h"
@@ -30,13 +31,7 @@
#include "json_util.h" #include "json_util.h"
#include "math_compat.h" #include "math_compat.h"
#include "strdup_compat.h" #include "strdup_compat.h"

#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 "snprintf_compat.h"


// Don't define this. It's not thread-safe. // Don't define this. It's not thread-safe.
/* #define REFCOUNT_DEBUG 1 */ /* #define REFCOUNT_DEBUG 1 */
@@ -143,11 +138,11 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl
default: default:
if(c < ' ') if(c < ' ')
{ {
char sbuf[7];
if(pos - start_offset > 0) if(pos - start_offset > 0)
printbuf_memappend(pb, printbuf_memappend(pb,
str + start_offset, str + start_offset,
pos - start_offset); pos - start_offset);
static char sbuf[7];
snprintf(sbuf, sizeof(sbuf), snprintf(sbuf, sizeof(sbuf),
"\\u00%c%c", "\\u00%c%c",
json_hex_chars[c >> 4], json_hex_chars[c >> 4],
@@ -589,7 +584,7 @@ static int json_object_int_to_json_string(struct json_object* jso,
int flags) int flags)
{ {
/* room for 19 digits, the sign char, and a null term */ /* room for 19 digits, the sign char, and a null term */
static char sbuf[21];
char sbuf[21];
snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64); snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64);
return printbuf_memappend (pb, sbuf, strlen(sbuf)); return printbuf_memappend (pb, sbuf, strlen(sbuf));
} }
@@ -634,6 +629,10 @@ int32_t json_object_get_int(const struct json_object *jso)
return INT32_MAX; return INT32_MAX;
return (int32_t) cint64; return (int32_t) cint64;
case json_type_double: case json_type_double:
if (jso->o.c_double <= INT32_MIN)
return INT32_MIN;
if (jso->o.c_double >= INT32_MAX)
return INT32_MAX;
return (int32_t)jso->o.c_double; return (int32_t)jso->o.c_double;
case json_type_boolean: case json_type_boolean:
return jso->o.c_boolean; return jso->o.c_boolean;
@@ -692,52 +691,122 @@ int json_object_set_int64(struct json_object *jso,int64_t new_value){


/* json_object_double */ /* json_object_double */


#ifdef HAVE___THREAD
// i.e. __thread or __declspec(thread)
static SPEC___THREAD char *tls_serialization_float_format = NULL;
#endif
static char *global_serialization_float_format = NULL;

int json_c_set_serialization_double_format(const char *double_format, int global_or_thread)
{
if (global_or_thread == JSON_C_OPTION_GLOBAL)
{
#ifdef HAVE___THREAD
if (tls_serialization_float_format)
{
free(tls_serialization_float_format);
tls_serialization_float_format = NULL;
}
#endif
if (global_serialization_float_format)
free(global_serialization_float_format);
global_serialization_float_format = double_format ? strdup(double_format) : NULL;
}
else if (global_or_thread == JSON_C_OPTION_THREAD)
{
#ifdef HAVE___THREAD
if (tls_serialization_float_format)
{
free(tls_serialization_float_format);
tls_serialization_float_format = NULL;
}
tls_serialization_float_format = double_format ? strdup(double_format) : NULL;
#else
_set_last_err("json_c_set_option: not compiled with __thread support\n");
return -1;
#endif
}
else
{
_set_last_err("json_c_set_option: invalid global_or_thread value: %d\n", global_or_thread);
return -1;
}
return 0;
}


static int json_object_double_to_json_string_format(struct json_object* jso, static int json_object_double_to_json_string_format(struct json_object* jso,
struct printbuf *pb, struct printbuf *pb,
int level, int level,
int flags, int flags,
const char *format) const char *format)
{ {
char buf[128], *p, *q;
int size;
double dummy; /* needed for modf() */
/* 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),
format ? format :
(modf(jso->o.c_double, &dummy) == 0) ? "%.17g.0" : "%.17g",
jso->o.c_double);
if(size < 0 || size >= (int)sizeof(buf))
size = (int)sizeof(buf);

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;
char buf[128], *p, *q;
int size;
double dummy; /* needed for modf() */
/* 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
{
const char *std_format = "%.17g";

#ifdef HAVE___THREAD
if (tls_serialization_float_format)
std_format = tls_serialization_float_format;
else
#endif
if (global_serialization_float_format)
std_format = global_serialization_float_format;
if (!format)
format = std_format;
size = snprintf(buf, sizeof(buf), format, jso->o.c_double);
if (modf(jso->o.c_double, &dummy) == 0 && size >= 0 && size < (int)sizeof(buf) - 2)
{
// Ensure it looks like a float, even if snprintf didn't.
strcat(buf, ".0");
size += 2;
}
}
// although unlikely, snprintf can fail
if (size < 0)
return -1;

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;
}

if (size >= (int)sizeof(buf))
// The standard formats are guaranteed not to overrun the buffer,
// but if a custom one happens to do so, just silently truncate.
size = sizeof(buf) - 1;
printbuf_memappend(pb, buf, size);
return size;
} }


static int json_object_double_to_json_string_default(struct json_object* jso, static int json_object_double_to_json_string_default(struct json_object* jso,
@@ -1072,7 +1141,7 @@ struct json_object* json_object_array_bsearch(


assert(json_object_get_type(jso) == json_type_array); assert(json_object_get_type(jso) == json_type_array);
result = (struct json_object **)array_list_bsearch( result = (struct json_object **)array_list_bsearch(
(const void **)&key, jso->o.c_array, sort_fn);
(const void **)(void *)&key, jso->o.c_array, sort_fn);


if (!result) if (!result)
return NULL; return NULL;
@@ -1139,7 +1208,7 @@ static int json_object_all_values_equal(struct json_object* jso1,
/* Iterate over jso1 keys and see if they exist and are equal in jso2 */ /* Iterate over jso1 keys and see if they exist and are equal in jso2 */
json_object_object_foreachC(jso1, iter) { json_object_object_foreachC(jso1, iter) {
if (!lh_table_lookup_ex(jso2->o.c_object, (void*)iter.key, if (!lh_table_lookup_ex(jso2->o.c_object, (void*)iter.key,
(void**)&sub))
(void**)(void *)&sub))
return 0; return 0;
if (!json_object_equal(iter.val, sub)) if (!json_object_equal(iter.val, sub))
return 0; return 0;
@@ -1148,7 +1217,7 @@ static int json_object_all_values_equal(struct json_object* jso1,
/* Iterate over jso2 keys to see if any exist that are not in jso1 */ /* Iterate over jso2 keys to see if any exist that are not in jso1 */
json_object_object_foreachC(jso2, iter) { json_object_object_foreachC(jso2, iter) {
if (!lh_table_lookup_ex(jso1->o.c_object, (void*)iter.key, if (!lh_table_lookup_ex(jso1->o.c_object, (void*)iter.key,
(void**)&sub))
(void**)(void *)&sub))
return 0; return 0;
} }




+ 85
- 48
json_object.h View File

@@ -21,6 +21,12 @@
#define THIS_FUNCTION_IS_DEPRECATED(func) func #define THIS_FUNCTION_IS_DEPRECATED(func) func
#endif #endif


#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport)
#else
#define JSON_EXPORT extern
#endif

#include <stddef.h> #include <stddef.h>
#include "json_inttypes.h" #include "json_inttypes.h"


@@ -105,6 +111,22 @@ extern "C" {
#undef TRUE #undef TRUE
#define TRUE ((json_bool)1) #define TRUE ((json_bool)1)


/**
* Set the global value of an option, which will apply to all
* current and future threads that have not set a thread-local value.
*
* @see json_c_set_serialization_double_format
*/
#define JSON_C_OPTION_GLOBAL (0)
/**
* Set a thread-local value of an option, overriding the global value.
* This will fail if json-c is not compiled with threading enabled, and
* with the __thread specifier (or equivalent) available.
*
* @see json_c_set_serialization_double_format
*/
#define JSON_C_OPTION_THREAD (1)

extern const char *json_number_chars; extern const char *json_number_chars;
extern const char *json_hex_chars; extern const char *json_hex_chars;


@@ -160,7 +182,7 @@ typedef enum json_type {
* *
* @param obj the json_object instance * @param obj the json_object instance
*/ */
extern struct json_object* json_object_get(struct json_object *obj);
JSON_EXPORT struct json_object* json_object_get(struct json_object *obj);


/** /**
* Decrement the reference count of json_object and free if it reaches zero. * Decrement the reference count of json_object and free if it reaches zero.
@@ -170,7 +192,7 @@ extern struct json_object* json_object_get(struct json_object *obj);
* @param obj the json_object instance * @param obj the json_object instance
* @returns 1 if the object was freed. * @returns 1 if the object was freed.
*/ */
int json_object_put(struct json_object *obj);
JSON_EXPORT int json_object_put(struct json_object *obj);


/** /**
* Check if the json_object is of a given type * Check if the json_object is of a given type
@@ -184,7 +206,7 @@ int json_object_put(struct json_object *obj);
json_type_array, json_type_array,
json_type_string json_type_string
*/ */
extern int json_object_is_type(const struct json_object *obj, enum json_type type);
JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_type type);


/** /**
* Get the type of the json_object. See also json_type_to_name() to turn this * Get the type of the json_object. See also json_type_to_name() to turn this
@@ -200,7 +222,7 @@ extern int json_object_is_type(const struct json_object *obj, enum json_type typ
json_type_array, json_type_array,
json_type_string json_type_string
*/ */
extern enum json_type json_object_get_type(const struct json_object *obj);
JSON_EXPORT enum json_type json_object_get_type(const struct json_object *obj);




/** Stringify object to json format. /** Stringify object to json format.
@@ -212,7 +234,7 @@ extern enum json_type json_object_get_type(const struct json_object *obj);
* @param obj the json_object instance * @param obj the json_object instance
* @returns a string in JSON format * @returns a string in JSON format
*/ */
extern const char* json_object_to_json_string(struct json_object *obj);
JSON_EXPORT const char* json_object_to_json_string(struct json_object *obj);


/** Stringify object to json format /** Stringify object to json format
* @see json_object_to_json_string() for details on how to free string. * @see json_object_to_json_string() for details on how to free string.
@@ -220,7 +242,7 @@ extern const char* json_object_to_json_string(struct json_object *obj);
* @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
* @returns a string in JSON format * @returns a string in JSON format
*/ */
extern const char* json_object_to_json_string_ext(struct json_object *obj, int
JSON_EXPORT const char* json_object_to_json_string_ext(struct json_object *obj, int
flags); flags);


/** Stringify object to json format /** Stringify object to json format
@@ -230,7 +252,7 @@ flags);
* @param length a pointer where, if not NULL, the length (without null) is stored * @param length a pointer where, if not NULL, the length (without null) is stored
* @returns a string in JSON format and the length if not NULL * @returns a string in JSON format and the length if not NULL
*/ */
extern const char* json_object_to_json_string_length(struct json_object *obj, int
JSON_EXPORT const char* json_object_to_json_string_length(struct json_object *obj, int
flags, size_t *length); flags, size_t *length);


/** /**
@@ -239,7 +261,7 @@ flags, size_t *length);
* *
* @param jso the object to return the userdata for * @param jso the object to return the userdata for
*/ */
extern void* json_object_get_userdata(json_object *jso);
JSON_EXPORT void* json_object_get_userdata(json_object *jso);


/** /**
* Set an opaque userdata value for an object * Set an opaque userdata value for an object
@@ -266,7 +288,7 @@ extern void* json_object_get_userdata(json_object *jso);
* @param userdata an optional opaque cookie * @param userdata an optional opaque cookie
* @param user_delete an optional function from freeing userdata * @param user_delete an optional function from freeing userdata
*/ */
extern void json_object_set_userdata(json_object *jso, void *userdata,
JSON_EXPORT void json_object_set_userdata(json_object *jso, void *userdata,
json_object_delete_fn *user_delete); json_object_delete_fn *user_delete);


/** /**
@@ -299,7 +321,7 @@ extern void json_object_set_userdata(json_object *jso, void *userdata,
* @param userdata an optional opaque cookie * @param userdata an optional opaque cookie
* @param user_delete an optional function from freeing userdata * @param user_delete an optional function from freeing userdata
*/ */
extern void json_object_set_serializer(json_object *jso,
JSON_EXPORT void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn to_string_func, json_object_to_json_string_fn to_string_func,
void *userdata, void *userdata,
json_object_delete_fn *user_delete); json_object_delete_fn *user_delete);
@@ -337,18 +359,18 @@ json_object_to_json_string_fn json_object_userdata_to_json_string;
* *
* @returns a json_object of type json_type_object * @returns a json_object of type json_type_object
*/ */
extern struct json_object* json_object_new_object(void);
JSON_EXPORT struct json_object* json_object_new_object(void);


/** Get the hashtable of a json_object of type json_type_object /** Get the hashtable of a json_object of type json_type_object
* @param obj the json_object instance * @param obj the json_object instance
* @returns a linkhash * @returns a linkhash
*/ */
extern struct lh_table* json_object_get_object(const struct json_object *obj);
JSON_EXPORT struct lh_table* json_object_get_object(const struct json_object *obj);


/** Get the size of an object in terms of the number of fields it has. /** Get the size of an object in terms of the number of fields it has.
* @param obj the json_object whose length to return * @param obj the json_object whose length to return
*/ */
extern int json_object_object_length(const struct json_object* obj);
JSON_EXPORT int json_object_object_length(const struct json_object* obj);


/** Add an object field to a json_object of type json_type_object /** Add an object field to a json_object of type json_type_object
* *
@@ -369,7 +391,7 @@ extern int json_object_object_length(const struct json_object* obj);
* @return On success, <code>0</code> is returned. * @return On success, <code>0</code> is returned.
* On error, a negative value is returned. * On error, a negative value is returned.
*/ */
extern int json_object_object_add(struct json_object* obj, const char *key,
JSON_EXPORT int json_object_object_add(struct json_object* obj, const char *key,
struct json_object *val); struct json_object *val);


/** Add an object field to a json_object of type json_type_object /** Add an object field to a json_object of type json_type_object
@@ -385,7 +407,7 @@ extern int json_object_object_add(struct json_object* obj, const char *key,
* @param opts process-modifying options. To specify multiple options, use * @param opts process-modifying options. To specify multiple options, use
* arithmetic or (OPT1|OPT2) * arithmetic or (OPT1|OPT2)
*/ */
extern int json_object_object_add_ex(struct json_object* obj,
JSON_EXPORT int json_object_object_add_ex(struct json_object* obj,
const char *const key, const char *const key,
struct json_object *const val, struct json_object *const val,
const unsigned opts); const unsigned opts);
@@ -411,7 +433,7 @@ extern int json_object_object_add_ex(struct json_object* obj,
* @returns the json_object associated with the given field name * @returns the json_object associated with the given field name
* @deprecated Please use json_object_object_get_ex * @deprecated Please use json_object_object_get_ex
*/ */
extern struct json_object* json_object_object_get(const struct json_object* obj,
JSON_EXPORT struct json_object* json_object_object_get(const struct json_object* obj,
const char *key); const char *key);


/** Get the json_object associated with a given object field. /** Get the json_object associated with a given object field.
@@ -432,7 +454,7 @@ extern struct json_object* json_object_object_get(const struct json_object* obj,
* It is safe to pass a NULL value. * It is safe to pass a NULL value.
* @returns whether or not the key exists * @returns whether or not the key exists
*/ */
extern json_bool json_object_object_get_ex(const struct json_object* obj,
JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object* obj,
const char *key, const char *key,
struct json_object **value); struct json_object **value);


@@ -445,7 +467,7 @@ extern json_bool json_object_object_get_ex(const struct json_object* obj,
* @param obj the json_object instance * @param obj the json_object instance
* @param key the object field name * @param key the object field name
*/ */
extern void json_object_object_del(struct json_object* obj, const char *key);
JSON_EXPORT void json_object_object_del(struct json_object* obj, const char *key);


/** /**
* Iterate through all keys and values of an object. * Iterate through all keys and values of an object.
@@ -504,19 +526,19 @@ extern void json_object_object_del(struct json_object* obj, const char *key);
/** Create a new empty json_object of type json_type_array /** Create a new empty json_object of type json_type_array
* @returns a 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);
JSON_EXPORT struct json_object* json_object_new_array(void);


/** Get the arraylist of a json_object of type json_type_array /** Get the arraylist of a json_object of type json_type_array
* @param obj the json_object instance * @param obj the json_object instance
* @returns an arraylist * @returns an arraylist
*/ */
extern struct array_list* json_object_get_array(const struct json_object *obj);
JSON_EXPORT struct array_list* json_object_get_array(const struct json_object *obj);


/** Get the length of a json_object of type json_type_array /** Get the length of a json_object of type json_type_array
* @param obj the json_object instance * @param obj the json_object instance
* @returns an int * @returns an int
*/ */
extern size_t json_object_array_length(const struct json_object *obj);
JSON_EXPORT size_t json_object_array_length(const struct json_object *obj);


/** Sorts the elements of jso of type json_type_array /** Sorts the elements of jso of type json_type_array
* *
@@ -526,7 +548,7 @@ extern size_t json_object_array_length(const struct json_object *obj);
* @param obj the json_object instance * @param obj the json_object instance
* @param sort_fn a sorting function * @param sort_fn a sorting function
*/ */
extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *));
JSON_EXPORT 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. /** Binary search a sorted array for a specified key object.
* *
@@ -542,7 +564,7 @@ extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const
* *
* @return the wanted json_object instance * @return the wanted json_object instance
*/ */
extern struct json_object* json_object_array_bsearch(
JSON_EXPORT struct json_object* json_object_array_bsearch(
const struct json_object *key, const struct json_object *key,
const struct json_object *jso, const struct json_object *jso,
int (*sort_fn)(const void *, const void *)); int (*sort_fn)(const void *, const void *));
@@ -556,7 +578,7 @@ extern struct json_object* json_object_array_bsearch(
* @param obj the json_object instance * @param obj the json_object instance
* @param val the json_object to be added * @param val the json_object to be added
*/ */
extern int json_object_array_add(struct json_object *obj,
JSON_EXPORT int json_object_array_add(struct json_object *obj,
struct json_object *val); struct json_object *val);


/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) /** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
@@ -574,7 +596,7 @@ extern int json_object_array_add(struct json_object *obj,
* @param idx the index to insert the element at * @param idx the index to insert the element at
* @param val the json_object to be added * @param val the json_object to be added
*/ */
extern int json_object_array_put_idx(struct json_object *obj, size_t idx,
JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx,
struct json_object *val); struct json_object *val);


/** Get the element at specificed index of the array (a json_object of type json_type_array) /** Get the element at specificed index of the array (a json_object of type json_type_array)
@@ -582,7 +604,7 @@ extern int json_object_array_put_idx(struct json_object *obj, size_t idx,
* @param idx the index to get the element at * @param idx the index to get the element at
* @returns the json_object at the specified index (or NULL) * @returns the json_object at the specified index (or NULL)
*/ */
extern struct json_object* json_object_array_get_idx(const struct json_object *obj,
JSON_EXPORT struct json_object* json_object_array_get_idx(const struct json_object *obj,
size_t idx); size_t idx);


/** Delete an elements from a specified index in an array (a json_object of type json_type_array) /** Delete an elements from a specified index in an array (a json_object of type json_type_array)
@@ -596,7 +618,7 @@ extern struct json_object* json_object_array_get_idx(const struct json_object *o
* @param count the number of elements to delete * @param count the number of elements to delete
* @returns 0 if the elements were successfully deleted * @returns 0 if the elements were successfully deleted
*/ */
extern int json_object_array_del_idx(struct json_object *obj, size_t idx, size_t count);
JSON_EXPORT int json_object_array_del_idx(struct json_object *obj, size_t idx, size_t count);


/* json_bool type methods */ /* json_bool type methods */


@@ -604,7 +626,7 @@ extern int json_object_array_del_idx(struct json_object *obj, size_t idx, size_t
* @param b a json_bool TRUE or FALSE (1 or 0) * @param b a json_bool TRUE or FALSE (1 or 0)
* @returns a json_object of type json_type_boolean * @returns a json_object of type json_type_boolean
*/ */
extern struct json_object* json_object_new_boolean(json_bool b);
JSON_EXPORT struct json_object* json_object_new_boolean(json_bool b);


/** Get the json_bool value of a json_object /** Get the json_bool value of a json_object
* *
@@ -617,7 +639,7 @@ extern struct json_object* json_object_new_boolean(json_bool b);
* @param obj the json_object instance * @param obj the json_object instance
* @returns a json_bool * @returns a json_bool
*/ */
extern json_bool json_object_get_boolean(const struct json_object *obj);
JSON_EXPORT json_bool json_object_get_boolean(const struct json_object *obj);




/** Set the json_bool value of a json_object /** Set the json_bool value of a json_object
@@ -630,7 +652,7 @@ extern json_bool json_object_get_boolean(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_boolean(struct json_object *obj,json_bool new_value);
JSON_EXPORT int json_object_set_boolean(struct json_object *obj,json_bool new_value);




/* int type methods */ /* int type methods */
@@ -641,14 +663,14 @@ extern int json_object_set_boolean(struct json_object *obj,json_bool new_value);
* @param i the integer * @param i the integer
* @returns a json_object of type json_type_int * @returns a json_object of type json_type_int
*/ */
extern struct json_object* json_object_new_int(int32_t i);
JSON_EXPORT struct json_object* json_object_new_int(int32_t i);




/** Create a new empty json_object of type json_type_int /** Create a new empty json_object of type json_type_int
* @param i the integer * @param i the integer
* @returns a json_object of type json_type_int * @returns a json_object of type json_type_int
*/ */
extern struct json_object* json_object_new_int64(int64_t i);
JSON_EXPORT struct json_object* json_object_new_int64(int64_t i);




/** Get the int value of a json_object /** Get the int value of a json_object
@@ -665,7 +687,7 @@ extern struct json_object* json_object_new_int64(int64_t i);
* @param obj the json_object instance * @param obj the json_object instance
* @returns an int * @returns an int
*/ */
extern int32_t json_object_get_int(const struct json_object *obj);
JSON_EXPORT int32_t json_object_get_int(const struct json_object *obj);


/** Set the int value of a json_object /** Set the int value of a json_object
* *
@@ -677,7 +699,7 @@ extern int32_t json_object_get_int(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_int(struct json_object *obj,int new_value);
JSON_EXPORT int json_object_set_int(struct json_object *obj,int new_value);




/** Get the int value of a json_object /** Get the int value of a json_object
@@ -693,7 +715,7 @@ extern int json_object_set_int(struct json_object *obj,int new_value);
* @param obj the json_object instance * @param obj the json_object instance
* @returns an int64 * @returns an int64
*/ */
extern int64_t json_object_get_int64(const struct json_object *obj);
JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj);




/** Set the int64_t value of a json_object /** Set the int64_t value of a json_object
@@ -706,7 +728,7 @@ extern int64_t json_object_get_int64(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_int64(struct json_object *obj,int64_t new_value);
JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value);




/* double type methods */ /* double type methods */
@@ -718,7 +740,7 @@ extern int json_object_set_int64(struct json_object *obj,int64_t new_value);
* @param d the double * @param d the double
* @returns a json_object of type json_type_double * @returns a json_object of type json_type_double
*/ */
extern struct json_object* json_object_new_double(double d);
JSON_EXPORT struct json_object* json_object_new_double(double d);


/** /**
* Create a new json_object of type json_type_double, using * Create a new json_object of type json_type_double, using
@@ -746,7 +768,22 @@ extern struct json_object* json_object_new_double(double d);
* @param d the numeric value of the double. * @param d the numeric value of the double.
* @param ds the string representation of the double. This will be copied. * @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);
JSON_EXPORT struct json_object* json_object_new_double_s(double d, const char *ds);

/**
* Set a global or thread-local json-c option, depending on whether
* JSON_C_OPTION_GLOBAL or JSON_C_OPTION_THREAD is passed.
* Thread-local options default to undefined, and inherit from the global
* value, even if the global value is changed after the thread is created.
* Attempting to set thread-local options when threading is not compiled in
* will result in an error. Be sure to check the return value.
*
* double_format is a "%g" printf format, such as "%.20g"
*
* @return -1 on errors, 0 on success.
*/
int json_c_set_serialization_double_format(const char *double_format, int global_or_thread);





/** Serialize a json_object of type json_type_double to a string. /** Serialize a json_object of type json_type_double to a string.
@@ -768,7 +805,7 @@ extern struct json_object* json_object_new_double_s(double d, const char *ds);
* @param level Ignored. * @param level Ignored.
* @param flags Ignored. * @param flags Ignored.
*/ */
extern int json_object_double_to_json_string(struct json_object* jso,
JSON_EXPORT int json_object_double_to_json_string(struct json_object* jso,
struct printbuf *pb, struct printbuf *pb,
int level, int level,
int flags); int flags);
@@ -796,7 +833,7 @@ extern int json_object_double_to_json_string(struct json_object* jso,
* @param obj the json_object instance * @param obj the json_object instance
* @returns a double floating point number * @returns a double floating point number
*/ */
extern double json_object_get_double(const struct json_object *obj);
JSON_EXPORT double json_object_get_double(const struct json_object *obj);




/** Set the double value of a json_object /** Set the double value of a json_object
@@ -809,7 +846,7 @@ extern double json_object_get_double(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_double(struct json_object *obj,double new_value);
JSON_EXPORT int json_object_set_double(struct json_object *obj,double new_value);






@@ -822,9 +859,9 @@ extern int json_object_set_double(struct json_object *obj,double new_value);
* @param s the string * @param s the string
* @returns a json_object of type json_type_string * @returns a json_object of type json_type_string
*/ */
extern struct json_object* json_object_new_string(const char *s);
JSON_EXPORT struct json_object* json_object_new_string(const char *s);


extern struct json_object* json_object_new_string_len(const char *s, int len);
JSON_EXPORT struct json_object* json_object_new_string_len(const char *s, int len);


/** Get the string value of a json_object /** Get the string value of a json_object
* *
@@ -842,7 +879,7 @@ extern struct json_object* json_object_new_string_len(const char *s, int len);
* @param obj the json_object instance * @param obj the json_object instance
* @returns a string or NULL * @returns a string or NULL
*/ */
extern const char* json_object_get_string(struct json_object *obj);
JSON_EXPORT const char* json_object_get_string(struct json_object *obj);


/** Get the string length of a json_object /** Get the string length of a json_object
* *
@@ -852,14 +889,14 @@ extern const char* json_object_get_string(struct json_object *obj);
* @param obj the json_object instance * @param obj the json_object instance
* @returns int * @returns int
*/ */
extern int json_object_get_string_len(const struct json_object *obj);
JSON_EXPORT int json_object_get_string_len(const struct json_object *obj);




/** Set the string value of a json_object with zero terminated strings /** Set the string value of a json_object with zero terminated strings
* equivalent to json_object_set_string_len (obj, new_value, strlen(new_value)) * equivalent to json_object_set_string_len (obj, new_value, strlen(new_value))
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_string(json_object* obj, const char* new_value);
JSON_EXPORT int json_object_set_string(json_object* obj, const char* new_value);


/** Set the string value of a json_object str /** Set the string value of a json_object str
* *
@@ -872,7 +909,7 @@ extern int json_object_set_string(json_object* obj, const char* new_value);
* @param len the length of new_value * @param len the length of new_value
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
extern int json_object_set_string_len(json_object* obj, const char* new_value, int len);
JSON_EXPORT int json_object_set_string_len(json_object* obj, const char* new_value, int len);


/** Check if two json_object's are equal /** Check if two json_object's are equal
* *
@@ -891,7 +928,7 @@ extern int json_object_set_string_len(json_object* obj, const char* new_value, i
* @param obj2 the second json_object instance * @param obj2 the second json_object instance
* @returns whether both objects are equal or not * @returns whether both objects are equal or not
*/ */
extern int json_object_equal(struct json_object *obj1,
JSON_EXPORT int json_object_equal(struct json_object *obj1,
struct json_object *obj2); struct json_object *obj2);


#ifdef __cplusplus #ifdef __cplusplus


+ 2
- 0
json_object_private.h View File

@@ -48,6 +48,8 @@ struct json_object
void *_userdata; void *_userdata;
}; };


void _set_last_err(const char *err_fmt, ...);

#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif


+ 2
- 1
json_pointer.c View File

@@ -8,10 +8,11 @@


#include "config.h" #include "config.h"


#include "strerror_override.h"

#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>




+ 9
- 9
json_tokener.h View File

@@ -116,19 +116,19 @@ const char *json_tokener_error_desc(enum json_tokener_error jerr);
* *
* See also json_tokener_error_desc(). * See also json_tokener_error_desc().
*/ */
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
JSON_EXPORT 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);
JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);


/** /**
* Set flags that control how parsing will be done. * Set flags that control how parsing will be done.
*/ */
extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
JSON_EXPORT 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 * Parse a string and return a non-NULL json_object if a valid JSON value
@@ -198,7 +198,7 @@ if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. * @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 * @param len the length of str
*/ */
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len); const char *str, int len);


#ifdef __cplusplus #ifdef __cplusplus


+ 58
- 40
json_util.c View File

@@ -12,13 +12,14 @@
#include "config.h" #include "config.h"
#undef realloc #undef realloc


#include "strerror_override.h"

#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <ctype.h> #include <ctype.h>


#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
@@ -47,12 +48,7 @@
# define open _open # define open _open
#endif #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 "snprintf_compat.h"


#include "debug.h" #include "debug.h"
#include "printbuf.h" #include "printbuf.h"
@@ -64,7 +60,8 @@
static int sscanf_is_broken = 0; static int sscanf_is_broken = 0;
static int sscanf_is_broken_testdone = 0; static int sscanf_is_broken_testdone = 0;
static void sscanf_is_broken_test(void); static void sscanf_is_broken_test(void);
static void _set_last_err(const char *err_fmt, ...);

static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);


static char _last_err[256] = ""; static char _last_err[256] = "";


@@ -75,7 +72,7 @@ const char *json_util_get_last_err()
return _last_err; return _last_err;
} }


static void _set_last_err(const char *err_fmt, ...)
void _set_last_err(const char *err_fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, err_fmt); va_start(ap, err_fmt);
@@ -127,42 +124,61 @@ struct json_object* json_object_from_file(const char *filename)


int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) 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;
int fd, ret;
int saved_errno;


if(!obj) {
_set_last_err("json_object_to_file: object is null\n");
return -1;
}
if (!obj) {
_set_last_err("json_object_to_file: object is null\n");
return -1;
}


if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
_set_last_err("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
return -1;
}
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
_set_last_err("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
return -1;
}
ret = _json_object_to_fd(fd, obj, flags, filename);
saved_errno = errno;
close(fd);
errno = saved_errno;
return ret;
}


if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
close(fd);
return -1;
}
int json_object_to_fd(int fd, struct json_object *obj, int flags)
{
if (!obj) {
_set_last_err("json_object_to_fd: object is null\n");
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);
_set_last_err("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
}
return _json_object_to_fd(fd, obj, flags, NULL);
}
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
{
int ret;
const char *json_str;
unsigned int wpos, wsize;


/* because of the above check for ret < 0, we can safely cast and add */
wpos += (unsigned int)ret;
}
filename = filename ? filename : "(fd)";


close(fd);
return 0;
if (!(json_str = json_object_to_json_string_ext(obj,flags))) {
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) {
_set_last_err("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;
}

return 0;
} }


// backwards compatible "format and write to file" function // backwards compatible "format and write to file" function
@@ -174,7 +190,9 @@ int json_object_to_file(const char *filename, struct json_object *obj)


int json_parse_double(const char *buf, double *retval) int json_parse_double(const char *buf, double *retval)
{ {
return (sscanf(buf, "%lf", retval)==1 ? 0 : 1);
char *end;
*retval = strtod(buf, &end);
return end == buf ? 1 : 0;
} }


/* /*


+ 12
- 1
json_util.h View File

@@ -67,7 +67,18 @@ 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_object_to_file_ext(const char *filename, struct json_object *obj, int flags);


/** /**
* Return the last error from json_object_to_file{,_ext} or
* Convert the json_object to a string and write it to the file descriptor.
* Handles partial writes and will keep writing until done, or an error
* occurs.
*
* @param flags flags to pass to json_object_to_json_string_ext()
* @return -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_fd(int fd, struct json_object *obj, int flags);

/**
* Return the last error from json_object_to_file{,_ext},
* json_object_to_fd() or
* json_object_from_{file,fd}, or NULL if there is none. * json_object_from_{file,fd}, or NULL if there is none.
*/ */
const char *json_util_get_last_err(void); const char *json_util_get_last_err(void);


+ 4
- 4
linkhash.c View File

@@ -23,7 +23,7 @@
# include <endian.h> /* attempt to define endianness */ # include <endian.h> /* attempt to define endianness */
#endif #endif


#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# include <windows.h> /* Get InterlockedCompareExchange */ # include <windows.h> /* Get InterlockedCompareExchange */
#endif #endif
@@ -452,7 +452,7 @@ static unsigned long lh_perllike_str_hash(const void *k)


static unsigned long lh_char_hash(const void *k) static unsigned long lh_char_hash(const void *k)
{ {
#if defined _MSC_VER
#if defined _MSC_VER || defined __MINGW32__
#define RANDOM_SEED_TYPE LONG #define RANDOM_SEED_TYPE LONG
#else #else
#define RANDOM_SEED_TYPE int #define RANDOM_SEED_TYPE int
@@ -474,10 +474,10 @@ static unsigned long lh_char_hash(const void *k)
#endif #endif
#if defined USE_SYNC_COMPARE_AND_SWAP #if defined USE_SYNC_COMPARE_AND_SWAP
(void)__sync_val_compare_and_swap(&random_seed, -1, seed); (void)__sync_val_compare_and_swap(&random_seed, -1, seed);
#elif defined _MSC_VER
#elif defined _MSC_VER || defined __MINGW32__
InterlockedCompareExchange(&random_seed, seed, -1); InterlockedCompareExchange(&random_seed, seed, -1);
#else #else
#warning "racy random seed initializtion if used by multiple threads"
//#warning "racy random seed initializtion if used by multiple threads"
random_seed = seed; /* potentially racy */ random_seed = seed; /* potentially racy */
#endif #endif
} }


+ 1
- 0
printbuf.c View File

@@ -27,6 +27,7 @@


#include "debug.h" #include "debug.h"
#include "printbuf.h" #include "printbuf.h"
#include "snprintf_compat.h"
#include "vasprintf_compat.h" #include "vasprintf_compat.h"


static int printbuf_extend(struct printbuf *p, int min_size); static int printbuf_extend(struct printbuf *p, int min_size);


+ 1
- 1
random_seed.c View File

@@ -9,6 +9,7 @@
* *
*/ */


#include "strerror_override.h"
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
#include "random_seed.h" #include "random_seed.h"
@@ -128,7 +129,6 @@ retry:
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>




+ 36
- 0
snprintf_compat.h View File

@@ -0,0 +1,36 @@
#ifndef __snprintf_compat_h
#define __snprintf_compat_h

/*
* Microsoft's _vsnprintf and _snprint don't always terminate
* the string, so use wrappers that ensure that.
*/

#include <stdarg.h>

#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
static int json_c_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int ret;
ret = _vsnprintf(str, size, format, ap);
str[size - 1] = '\0';
return ret;
}
#define vsnprintf json_c_vsnprintf

static int json_c_snprintf(char *str, size_t size, const char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = json_c_vsnprintf(str, size, format, ap);
va_end(ap);
return ret;
}
#define snprintf json_c_snprintf

#elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_SNPRINTF && defined(WIN32) */

#endif /* __snprintf_compat_h */

tests/strerror_override.c → strerror_override.c View File

@@ -1,4 +1,5 @@
#include <errno.h>
#define STRERROR_OVERRIDE_IMPL 1
#include "strerror_override.h"


/* /*
* Override strerror() to get consistent output across platforms. * Override strerror() to get consistent output across platforms.
@@ -52,14 +53,20 @@ static struct {
{ 0, (char *)0 } { 0, (char *)0 }
}; };


// Enabled during tests
int _json_c_strerror_enable = 0;

#define PREFIX "ERRNO=" #define PREFIX "ERRNO="
static char errno_buf[128] = PREFIX; static char errno_buf[128] = PREFIX;
char *strerror(int errno_in)
char *_json_c_strerror(int errno_in)
{ {
int start_idx; int start_idx;
char digbuf[20]; char digbuf[20];
int ii, jj; int ii, jj;


if (!_json_c_strerror_enable)
return strerror(errno_in);

// Avoid standard functions, so we don't need to include any // Avoid standard functions, so we don't need to include any
// headers, or guess at signatures. // headers, or guess at signatures.



+ 25
- 0
strerror_override.h View File

@@ -0,0 +1,25 @@
#ifndef _json_strerror_override_h_
#define _json_strerror_override_h_

#include "config.h"
#include <errno.h>

#include "json_object.h" /* for JSON_EXPORT */

#ifdef __cplusplus
extern "C" {
#endif

JSON_EXPORT char *_json_c_strerror(int errno_in);

#ifndef STRERROR_OVERRIDE_IMPL
#define strerror _json_c_strerror
#else
#include <string.h>
#endif

#ifdef __cplusplus
}
#endif

#endif /* _json_strerror_override_h_ */

+ 7
- 0
strerror_override_private.h View File

@@ -0,0 +1,7 @@
#ifndef __json_strerror_override_private_h__
#define __json_strerror_override_private_h__

/* Used by tests to get consistent output */
extern int _json_c_strerror_enable;

#endif

+ 1
- 1
tests/Makefile.am View File

@@ -52,7 +52,7 @@ EXTRA_DIST+= test2Formatted_plain.expected
EXTRA_DIST+= test2Formatted_pretty.expected EXTRA_DIST+= test2Formatted_pretty.expected
EXTRA_DIST+= test2Formatted_spaced.expected EXTRA_DIST+= test2Formatted_spaced.expected


test_util_file_SOURCES = test_util_file.c strerror_override.c
test_util_file_SOURCES = test_util_file.c


testsubdir=testSubDir testsubdir=testSubDir
TESTS_ENVIRONMENT = top_builddir=$(top_builddir) TESTS_ENVIRONMENT = top_builddir=$(top_builddir)


+ 8
- 0
tests/test-defs.sh View File

@@ -50,6 +50,14 @@ echo "=== Running test $progname"
CMP="${CMP-cmp}" CMP="${CMP-cmp}"


use_valgrind=${USE_VALGRIND-1} use_valgrind=${USE_VALGRIND-1}
case "${use_valgrind}" in
[0Nn]*)
use_valgrind=0
;;
*)
use_valgrind=1
;;
esac
valgrind_path=$(which valgrind 2> /dev/null) valgrind_path=$(which valgrind 2> /dev/null)
if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then
use_valgrind=0 use_valgrind=0


+ 13
- 0
tests/test1.c View File

@@ -120,6 +120,19 @@ void test_array_del_idx()
(int)(orig_array_len + 1), rc, json_object_to_json_string(my_array)); (int)(orig_array_len + 1), rc, json_object_to_json_string(my_array));


json_object_put(my_array); json_object_put(my_array);
/* Delete some array indexes, then add more */
my_array = make_array();
rc = json_object_array_del_idx(my_array, 0, orig_array_len - 1);
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n",
(int)(orig_array_len - 1), rc, json_object_to_json_string(my_array));
json_object_array_add(my_array, json_object_new_string("s1"));
json_object_array_add(my_array, json_object_new_string("s2"));
json_object_array_add(my_array, json_object_new_string("s3"));

printf("after adding more entries, my_array.to_string()=%s\n",
json_object_to_json_string(my_array));
json_object_put(my_array);
} }


int main(int argc, char **argv) int main(int argc, char **argv)


+ 2
- 0
tests/test1.expected View File

@@ -38,6 +38,8 @@ after del_idx(0,1)=0, my_array.to_string()=[ ]
after del_idx(0,1)=-1, my_array.to_string()=[ ] after del_idx(0,1)=-1, my_array.to_string()=[ ]
after del_idx(0,7)=0, my_array.to_string()=[ ] after del_idx(0,7)=0, my_array.to_string()=[ ]
after del_idx(0,8)=-1, my_array.to_string()=[ 1, 2, 3, 4, 5, null, 7 ] after del_idx(0,8)=-1, my_array.to_string()=[ 1, 2, 3, 4, 5, null, 7 ]
after del_idx(0,6)=0, my_array.to_string()=[ 7 ]
after adding more entries, my_array.to_string()=[ 7, "s1", "s2", "s3" ]
my_array= my_array=
[0]=3 [0]=3
[1]=1 [1]=1


+ 2
- 0
tests/test1Formatted_plain.expected View File

@@ -38,6 +38,8 @@ after del_idx(0,1)=0, my_array.to_string()=[]
after del_idx(0,1)=-1, my_array.to_string()=[] after del_idx(0,1)=-1, my_array.to_string()=[]
after del_idx(0,7)=0, my_array.to_string()=[] after del_idx(0,7)=0, my_array.to_string()=[]
after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7] after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7]
after del_idx(0,6)=0, my_array.to_string()=[7]
after adding more entries, my_array.to_string()=[7,"s1","s2","s3"]
my_array= my_array=
[0]=3 [0]=3
[1]=1 [1]=1


+ 2
- 0
tests/test1Formatted_pretty.expected View File

@@ -44,6 +44,8 @@ after del_idx(0,1)=0, my_array.to_string()=[]
after del_idx(0,1)=-1, my_array.to_string()=[] after del_idx(0,1)=-1, my_array.to_string()=[]
after del_idx(0,7)=0, my_array.to_string()=[] after del_idx(0,7)=0, my_array.to_string()=[]
after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7] after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7]
after del_idx(0,6)=0, my_array.to_string()=[7]
after adding more entries, my_array.to_string()=[7,"s1","s2","s3"]
my_array= my_array=
[0]=3 [0]=3
[1]=1 [1]=1


+ 2
- 0
tests/test1Formatted_spaced.expected View File

@@ -38,6 +38,8 @@ after del_idx(0,1)=0, my_array.to_string()=[]
after del_idx(0,1)=-1, my_array.to_string()=[] after del_idx(0,1)=-1, my_array.to_string()=[]
after del_idx(0,7)=0, my_array.to_string()=[] after del_idx(0,7)=0, my_array.to_string()=[]
after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7] after del_idx(0,8)=-1, my_array.to_string()=[1,2,3,4,5,null,7]
after del_idx(0,6)=0, my_array.to_string()=[7]
after adding more entries, my_array.to_string()=[7,"s1","s2","s3"]
my_array= my_array=
[0]=3 [0]=3
[1]=1 [1]=1


+ 0
- 12
tests/test4.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test4
exit $?

+ 1
- 0
tests/test4.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/testReplaceExisting.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test testReplaceExisting
exit $?

+ 1
- 0
tests/testReplaceExisting.test View File

@@ -0,0 +1 @@
test_basic.test

+ 19
- 0
tests/test_basic.test View File

@@ -0,0 +1,19 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

filename=$(basename "$0")
filename="${filename%.*}"

# This is only for the test_util_file.test ;
# more stuff could be extended
cp -f "$srcdir/valid.json" .

run_output_test $filename "$srcdir"
exit $?

+ 0
- 12
tests/test_cast.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_cast
exit $?

+ 1
- 0
tests/test_cast.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_charcase.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_charcase
exit $?

+ 1
- 0
tests/test_charcase.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_compare.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_compare
exit $?

+ 1
- 0
tests/test_compare.test View File

@@ -0,0 +1 @@
test_basic.test

+ 26
- 0
tests/test_double_serializer.c View File

@@ -27,5 +27,31 @@ int main()
json_object_set_serializer(obj, NULL, NULL, NULL); json_object_set_serializer(obj, NULL, NULL, NULL);
printf("obj.to_string(reset)=%s\n", json_object_to_json_string(obj)); printf("obj.to_string(reset)=%s\n", json_object_to_json_string(obj));


json_object_put(obj);
obj = json_object_new_double(0.52381);

printf("obj.to_string(default format)=%s\n", json_object_to_json_string(obj));
if (json_c_set_serialization_double_format("x%0.3fy", JSON_C_OPTION_GLOBAL) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(with global format)=%s\n", json_object_to_json_string(obj));
#ifdef HAVE___THREAD
if (json_c_set_serialization_double_format("T%0.2fX", JSON_C_OPTION_THREAD) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(with thread format)=%s\n", json_object_to_json_string(obj));
if (json_c_set_serialization_double_format("Ttttttttttttt%0.2fxxxxxxxxxxxxxxxxxxX", JSON_C_OPTION_THREAD) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(long thread format)=%s\n", json_object_to_json_string(obj));
if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_THREAD) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(back to global format)=%s\n", json_object_to_json_string(obj));
#else
// Just fake it up, so the output matches.
printf("obj.to_string(with thread format)=%s\n", "T0.52X");
printf("obj.to_string(back to global format)=%s\n", "x0.524y");
#endif
if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_GLOBAL) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(back to default format)=%s\n", json_object_to_json_string(obj));

json_object_put(obj); json_object_put(obj);
} }

+ 6
- 0
tests/test_double_serializer.expected View File

@@ -6,3 +6,9 @@ Test explicit serializer with custom userdata:
obj.to_string(custom)=test obj.to_string(custom)=test
Test reset serializer: Test reset serializer:
obj.to_string(reset)=0.5 obj.to_string(reset)=0.5
obj.to_string(default format)=0.52381
obj.to_string(with global format)=x0.524y
obj.to_string(with thread format)=T0.52X
obj.to_string(long thread format)=Ttttttttttttt0.52xxxxxxxxxxxxxxxxxxX
obj.to_string(back to global format)=x0.524y
obj.to_string(back to default format)=0.52381

+ 0
- 12
tests/test_double_serializer.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_double_serializer
exit $?

+ 1
- 0
tests/test_double_serializer.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_float.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_float
exit $?

+ 1
- 0
tests/test_float.test View File

@@ -0,0 +1 @@
test_basic.test

+ 4
- 1
tests/test_json_pointer.c View File

@@ -1,4 +1,5 @@
#include <errno.h>
#include "strerror_override.h"
#include "strerror_override_private.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -280,6 +281,8 @@ static void test_wrong_inputs_set()


int main(int argc, char **argv) int main(int argc, char **argv)
{ {
_json_c_strerror_enable = 1;

test_example_get(); test_example_get();
test_recursion_get(); test_recursion_get();
test_wrong_inputs_get(); test_wrong_inputs_get();


+ 0
- 12
tests/test_json_pointer.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_json_pointer
exit $?

+ 1
- 0
tests/test_json_pointer.test View File

@@ -0,0 +1 @@
test_basic.test

+ 1
- 0
tests/test_locale.c View File

@@ -7,6 +7,7 @@
#include "config.h" #include "config.h"
#include "json.h" #include "json.h"
#include "json_tokener.h" #include "json_tokener.h"
#include "snprintf_compat.h"


#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
#include <locale.h> #include <locale.h>


+ 0
- 12
tests/test_locale.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_locale
exit $?

+ 1
- 0
tests/test_locale.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_null.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_null
exit $?

+ 1
- 0
tests/test_null.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_parse.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_parse
exit $?

+ 1
- 0
tests/test_parse.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_parse_int64.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_parse_int64
exit $?

+ 1
- 0
tests/test_parse_int64.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_printbuf.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_printbuf
exit $?

+ 1
- 0
tests/test_printbuf.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_set_serializer.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_set_serializer
exit $?

+ 1
- 0
tests/test_set_serializer.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_set_value.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_set_value
exit $?

+ 1
- 0
tests/test_set_value.test View File

@@ -0,0 +1 @@
test_basic.test

+ 24
- 1
tests/test_util_file.c View File

@@ -1,4 +1,5 @@
#include <errno.h>
#include "strerror_override.h"
#include "strerror_override_private.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
@@ -49,6 +50,25 @@ static void test_write_to_file()
(rv == 0) ? "OK" : "FAIL", outfile2, rv); (rv == 0) ? "OK" : "FAIL", outfile2, rv);
if (rv == 0) if (rv == 0)
stat_and_cat(outfile2); stat_and_cat(outfile2);

const char *outfile3 = "json3.out";
int d = open(outfile3, O_WRONLY|O_CREAT, 0600);
if (d < 0)
{
printf("FAIL: unable to open %s %s\n", outfile3, strerror(errno));
return;
}
rv = json_object_to_fd(d, jso, JSON_C_TO_STRING_PRETTY);
printf("%s: json_object_to_fd(%s, jso, JSON_C_TO_STRING_PRETTY)=%d\n",
(rv == 0) ? "OK" : "FAIL", outfile3, rv);
// Write the same object twice
rv = json_object_to_fd(d, jso, JSON_C_TO_STRING_PLAIN);
printf("%s: json_object_to_fd(%s, jso, JSON_C_TO_STRING_PLAIN)=%d\n",
(rv == 0) ? "OK" : "FAIL", outfile3, rv);
close(d);
if (rv == 0)
stat_and_cat(outfile3);

json_object_put(jso); json_object_put(jso);
} }


@@ -87,6 +107,7 @@ static void stat_and_cat(const char *file)
buf[sb.st_size] = '\0'; buf[sb.st_size] = '\0';
printf("file[%s], size=%d, contents=%s\n", file, (int)sb.st_size, buf); printf("file[%s], size=%d, contents=%s\n", file, (int)sb.st_size, buf);
free(buf); free(buf);
close(d);
} }


int main(int argc, char **argv) int main(int argc, char **argv)
@@ -94,6 +115,8 @@ int main(int argc, char **argv)
// json_object_to_file(file, obj); // json_object_to_file(file, obj);
// json_object_to_file_ext(file, obj, flags); // json_object_to_file_ext(file, obj, flags);


_json_c_strerror_enable = 1;

const char *testdir; const char *testdir;
if (argc < 2) if (argc < 2)
{ {


+ 14
- 0
tests/test_util_file.expected View File

@@ -19,3 +19,17 @@ file[json2.out], size=367, contents={
"foo8":"abcdefghijklmnopqrstuvwxyz", "foo8":"abcdefghijklmnopqrstuvwxyz",
"foo9":"abcdefghijklmnopqrstuvwxyz" "foo9":"abcdefghijklmnopqrstuvwxyz"
} }
OK: json_object_to_fd(json3.out, jso, JSON_C_TO_STRING_PRETTY)=0
OK: json_object_to_fd(json3.out, jso, JSON_C_TO_STRING_PLAIN)=0
file[json3.out], size=703, contents={
"foo":1234,
"foo1":"abcdefghijklmnopqrstuvwxyz",
"foo2":"abcdefghijklmnopqrstuvwxyz",
"foo3":"abcdefghijklmnopqrstuvwxyz",
"foo4":"abcdefghijklmnopqrstuvwxyz",
"foo5":"abcdefghijklmnopqrstuvwxyz",
"foo6":"abcdefghijklmnopqrstuvwxyz",
"foo7":"abcdefghijklmnopqrstuvwxyz",
"foo8":"abcdefghijklmnopqrstuvwxyz",
"foo9":"abcdefghijklmnopqrstuvwxyz"
}{"foo":1234,"foo1":"abcdefghijklmnopqrstuvwxyz","foo2":"abcdefghijklmnopqrstuvwxyz","foo3":"abcdefghijklmnopqrstuvwxyz","foo4":"abcdefghijklmnopqrstuvwxyz","foo5":"abcdefghijklmnopqrstuvwxyz","foo6":"abcdefghijklmnopqrstuvwxyz","foo7":"abcdefghijklmnopqrstuvwxyz","foo8":"abcdefghijklmnopqrstuvwxyz","foo9":"abcdefghijklmnopqrstuvwxyz"}

+ 0
- 15
tests/test_util_file.test View File

@@ -1,15 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

cp -f "$srcdir/valid.json" .
run_output_test test_util_file "$srcdir"
_err=$?

exit $_err

+ 1
- 0
tests/test_util_file.test View File

@@ -0,0 +1 @@
test_basic.test

+ 0
- 12
tests/test_visit.test View File

@@ -1,12 +0,0 @@
#!/bin/sh

# Common definitions
if test -z "$srcdir"; then
srcdir="${0%/*}"
test "$srcdir" = "$0" && srcdir=.
test -z "$srcdir" && srcdir=.
fi
. "$srcdir/test-defs.sh"

run_output_test test_visit
exit $?

+ 1
- 0
tests/test_visit.test View File

@@ -0,0 +1 @@
test_basic.test

+ 1
- 5
vasprintf_compat.h View File

@@ -1,11 +1,7 @@
#ifndef __vasprintf_compat_h #ifndef __vasprintf_compat_h
#define __vasprintf_compat_h #define __vasprintf_compat_h


#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER)
# define vsnprintf _vsnprintf
#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
#include "snprintf_compat.h"


#if !defined(HAVE_VASPRINTF) #if !defined(HAVE_VASPRINTF)
/* CAW: compliant version of vasprintf */ /* CAW: compliant version of vasprintf */


Loading…
Cancel
Save