mirror of
https://github.com/json-c/json-c.git
synced 2026-04-07 14:29:06 +08:00
38
Makefile.am
38
Makefile.am
@@ -56,13 +56,43 @@ libjson_c_la_SOURCES = \
|
|||||||
strerror_override.c \
|
strerror_override.c \
|
||||||
strerror_override_private.h
|
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:
|
JSON_CLEANFILES=
|
||||||
-rm -rf configure
|
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"
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -45,7 +45,7 @@ $ sh autogen.sh
|
|||||||
followed by
|
followed by
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./configure
|
$ ./configure # --enable-threading
|
||||||
$ make
|
$ make
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
@@ -56,6 +56,25 @@ To build and run the test programs:
|
|||||||
$ make check
|
$ make check
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Building with partial threading support
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
Although json-c does not support fully multi-threaded access to
|
||||||
|
object trees, it has some code to help make use in threaded programs
|
||||||
|
a bit safer. Currently, this is limited to using atomic operations for
|
||||||
|
json_object_get() and json_object_put().
|
||||||
|
|
||||||
|
Since this may have a performance impact, of at least 3x slower
|
||||||
|
according to https://stackoverflow.com/a/11609063, it is disabled by
|
||||||
|
default. You may turn it on by adjusting your configure command with:
|
||||||
|
--enable-threading
|
||||||
|
|
||||||
|
Separately, the default hash function used for object field keys,
|
||||||
|
lh_char_hash, uses a compare-and-swap operation to ensure the randomly
|
||||||
|
seed is only generated once. Because this is a one-time operation, it
|
||||||
|
is always compiled in when the compare-and-swap operation is available.
|
||||||
|
|
||||||
|
|
||||||
Linking to `libjson-c`
|
Linking to `libjson-c`
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
#endif /* HAVE_STRINGS_H */
|
#endif /* HAVE_STRINGS_H */
|
||||||
|
|
||||||
|
#ifndef SIZE_T_MAX
|
||||||
#if SIZEOF_SIZE_T == SIZEOF_INT
|
#if SIZEOF_SIZE_T == SIZEOF_INT
|
||||||
#define SIZE_T_MAX UINT_MAX
|
#define SIZE_T_MAX UINT_MAX
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_LONG
|
#elif SIZEOF_SIZE_T == SIZEOF_LONG
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
#else
|
#else
|
||||||
#error Unable to determine size of size_t
|
#error Unable to determine size of size_t
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "arraylist.h"
|
#include "arraylist.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
autoreconf -Iautoconf-archive/m4 -v --install || exit 1
|
autoreconf -v --install || exit 1
|
||||||
|
|
||||||
# If there are any options, assume the user wants to run configure.
|
# If there are any options, assume the user wants to run configure.
|
||||||
# To run configure w/o any options, use ./autogen.sh --configure
|
# To run configure w/o any options, use ./autogen.sh --configure
|
||||||
|
|||||||
42
configure.ac
42
configure.ac
@@ -5,16 +5,32 @@ AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com])
|
|||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
AC_CONFIG_MACRO_DIRS([autoconf-archive/m4])
|
||||||
|
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(threading,
|
||||||
|
AS_HELP_STRING([--enable-threading],
|
||||||
|
[Enable code to support partly multi-threaded use]),
|
||||||
|
[if test x$enableval = xyes; then
|
||||||
|
enable_threading=yes
|
||||||
|
AC_DEFINE(ENABLE_THREADING, 1, [Enable partial threading support])
|
||||||
|
fi])
|
||||||
|
|
||||||
|
if test "x$enable_threading" = "xyes"; then
|
||||||
|
AC_MSG_RESULT([Partial multi-threaded support enabled.])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([Multi-threaded support disabled. Use --enable-threading to enable.])
|
||||||
|
fi
|
||||||
|
|
||||||
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.]),
|
||||||
[if test x$enableval = xyes; then
|
[if test x$enableval = xyes; then
|
||||||
enable_rdrand=yes
|
enable_rdrand=yes
|
||||||
AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed])
|
AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRAND Hardware RNG Hash Seed])
|
||||||
fi])
|
fi])
|
||||||
|
|
||||||
if test "x$enable_rdrand" = "xyes"; then
|
if test "x$enable_rdrand" = "xyes"; then
|
||||||
@@ -66,6 +82,30 @@ AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
|
|||||||
AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
|
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>]])
|
||||||
|
AC_MSG_CHECKING(for GCC atomic builtins)
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[
|
||||||
|
AC_LANG_SOURCE([[
|
||||||
|
int main() {
|
||||||
|
volatile unsigned int val = 1;
|
||||||
|
/* Note: __sync_val_compare_and_swap isn't checked here
|
||||||
|
* because it's protected by __GCC_HAVE_SYNC_COMPARE_AND_SWAP_<n>,
|
||||||
|
* which is automatically defined by gcc.
|
||||||
|
*/
|
||||||
|
__sync_add_and_fetch(&val, 1);
|
||||||
|
__sync_sub_and_fetch(&val, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
AC_DEFINE([HAVE_ATOMIC_BUILTINS],[1],[Has atomic builtins])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
AC_MSG_WARN([json-c will be built without atomic refcounts because atomic builtins are missing])
|
||||||
|
])
|
||||||
|
|
||||||
case "${host_os}" in
|
case "${host_os}" in
|
||||||
linux*)
|
linux*)
|
||||||
|
|||||||
@@ -163,25 +163,37 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl
|
|||||||
|
|
||||||
extern struct json_object* json_object_retain(struct json_object *jso)
|
extern struct json_object* json_object_retain(struct json_object *jso)
|
||||||
{
|
{
|
||||||
if (jso)
|
if (!jso) return jso;
|
||||||
jso->_ref_count++;
|
|
||||||
|
#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
|
||||||
|
__sync_add_and_fetch(&jso->_ref_count, 1);
|
||||||
|
#else
|
||||||
|
++jso->_ref_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
return jso;
|
return jso;
|
||||||
}
|
}
|
||||||
|
|
||||||
int json_object_release(struct json_object *jso)
|
int json_object_release(struct json_object *jso)
|
||||||
{
|
{
|
||||||
if(jso)
|
if(!jso) return 0;
|
||||||
{
|
|
||||||
jso->_ref_count--;
|
#if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
|
||||||
if(!jso->_ref_count)
|
/* Note: this only allow the refcount to remain correct
|
||||||
{
|
* when multiple threads are adjusting it. It is still an error
|
||||||
if (jso->_user_delete)
|
* for a thread to decrement the refcount if it doesn't "own" it,
|
||||||
jso->_user_delete(jso, jso->_userdata);
|
* as that can result in the thread that loses the race to 0
|
||||||
jso->_delete(jso);
|
* operating on an already-freed object.
|
||||||
return 1;
|
*/
|
||||||
}
|
if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0;
|
||||||
}
|
#else
|
||||||
return 0;
|
if (--jso->_ref_count > 0) return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (jso->_user_delete)
|
||||||
|
jso->_user_delete(jso, jso->_userdata);
|
||||||
|
jso->_delete(jso);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -693,7 +705,7 @@ int json_object_set_int64(struct json_object *jso,int64_t new_value){
|
|||||||
|
|
||||||
/* json_object_double */
|
/* json_object_double */
|
||||||
|
|
||||||
#ifdef HAVE___THREAD
|
#if defined(HAVE___THREAD)
|
||||||
// i.e. __thread or __declspec(thread)
|
// i.e. __thread or __declspec(thread)
|
||||||
static SPEC___THREAD char *tls_serialization_float_format = NULL;
|
static SPEC___THREAD char *tls_serialization_float_format = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -703,7 +715,7 @@ int json_c_set_serialization_double_format(const char *double_format, int global
|
|||||||
{
|
{
|
||||||
if (global_or_thread == JSON_C_OPTION_GLOBAL)
|
if (global_or_thread == JSON_C_OPTION_GLOBAL)
|
||||||
{
|
{
|
||||||
#ifdef HAVE___THREAD
|
#if defined(HAVE___THREAD)
|
||||||
if (tls_serialization_float_format)
|
if (tls_serialization_float_format)
|
||||||
{
|
{
|
||||||
free(tls_serialization_float_format);
|
free(tls_serialization_float_format);
|
||||||
@@ -716,7 +728,7 @@ int json_c_set_serialization_double_format(const char *double_format, int global
|
|||||||
}
|
}
|
||||||
else if (global_or_thread == JSON_C_OPTION_THREAD)
|
else if (global_or_thread == JSON_C_OPTION_THREAD)
|
||||||
{
|
{
|
||||||
#ifdef HAVE___THREAD
|
#if defined(HAVE___THREAD)
|
||||||
if (tls_serialization_float_format)
|
if (tls_serialization_float_format)
|
||||||
{
|
{
|
||||||
free(tls_serialization_float_format);
|
free(tls_serialization_float_format);
|
||||||
@@ -765,7 +777,7 @@ static int json_object_double_to_json_string_format(struct json_object* jso,
|
|||||||
{
|
{
|
||||||
const char *std_format = "%.17g";
|
const char *std_format = "%.17g";
|
||||||
|
|
||||||
#ifdef HAVE___THREAD
|
#if defined(HAVE___THREAD)
|
||||||
if (tls_serialization_float_format)
|
if (tls_serialization_float_format)
|
||||||
std_format = tls_serialization_float_format;
|
std_format = tls_serialization_float_format;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -265,7 +265,9 @@ int json_parse_int64(const char *buf, int64_t *retval)
|
|||||||
// Skip leading zeros, but keep at least one digit
|
// Skip leading zeros, but keep at least one digit
|
||||||
while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
|
while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
|
||||||
buf_sig_digits++;
|
buf_sig_digits++;
|
||||||
if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
|
// Can't check num64==0 because some sscanf impl's parse
|
||||||
|
// non-zero values to 0. (e.g. Illumos with UINT64_MAX)
|
||||||
|
if (buf_sig_digits[0] == '0' && buf_sig_digits[1] == '\0')
|
||||||
orig_has_neg = 0; // "-0" is the same as just plain "0"
|
orig_has_neg = 0; // "-0" is the same as just plain "0"
|
||||||
|
|
||||||
snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
|
snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
|
||||||
|
|||||||
Reference in New Issue
Block a user