mirror of
https://github.com/akheron/jansson.git
synced 2025-04-13 16:50:36 +00:00
Compare commits
54 commits
Author | SHA1 | Date | |
---|---|---|---|
|
96d160df90 | ||
|
aef13f87f1 | ||
|
c16ac732e4 | ||
|
05a10aa8af | ||
|
4d7ac97b89 | ||
|
23905f372c | ||
|
ed5cae4ed0 | ||
|
0f9c18dd12 | ||
|
61fc3d0e28 | ||
|
cce8caba26 | ||
|
50953fb1fa | ||
|
c780171cf3 | ||
|
2297a2e320 | ||
|
f5b3ab323c | ||
|
9d3abab610 | ||
|
9699de8600 | ||
|
33a6c95d56 | ||
|
ed06f65412 | ||
|
8b975abca1 | ||
|
8660da0f7c | ||
|
dcbeb58829 | ||
|
53383b9e26 | ||
|
649c9357c6 | ||
|
73dc6960ad | ||
|
88375fb10e | ||
|
0247b5e2e7 | ||
|
842708ac0c | ||
|
2d1c13224f | ||
|
9b9b5e81cf | ||
|
0c9c11a89d | ||
|
f52d79a4d3 | ||
|
2f1777ba80 | ||
|
1e57cadbd3 | ||
|
0db4db1048 | ||
|
73d968feef | ||
|
0154c4af07 | ||
|
60097f0096 | ||
|
bde28463f8 | ||
|
e7c9ef8e52 | ||
|
a22dc95311 | ||
|
a7d04c8554 | ||
|
e23f558007 | ||
|
1894366598 | ||
|
7e04530916 | ||
|
011e625769 | ||
|
de5f2963ab | ||
|
128e9c5f37 | ||
|
fe6e8eec7e | ||
|
addeeef408 | ||
|
d82b436b2f | ||
|
586b4461e6 | ||
|
78418c84f1 | ||
|
eb81670881 | ||
|
0677666f65 |
55 changed files with 6693 additions and 352 deletions
15
.github/dependabot.yml
vendored
Normal file
15
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
2
.github/workflows/fuzz.yml
vendored
2
.github/workflows/fuzz.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
|||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
|
33
.github/workflows/tests.yml
vendored
33
.github/workflows/tests.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
|||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- run: ./scripts/clang-format-check
|
||||
|
||||
autotools:
|
||||
|
@ -18,18 +18,19 @@ jobs:
|
|||
matrix:
|
||||
os: ["ubuntu-latest", "macos-latest"]
|
||||
cc: ["gcc", "clang"]
|
||||
dtoa: ["yes", "no"]
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- if: ${{runner.os == 'macOS'}}
|
||||
run: brew install autoconf automake libtool
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- run: autoreconf -fi
|
||||
- env:
|
||||
CC: ${{matrix.cc}}
|
||||
CC: ${{ matrix.cc }}
|
||||
CFLAGS: -Werror
|
||||
run: ./configure
|
||||
run: ./configure --enable-dtoa=${{ matrix.dtoa }}
|
||||
- run: make check
|
||||
|
||||
cmake:
|
||||
|
@ -49,32 +50,18 @@ jobs:
|
|||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- env:
|
||||
CC: ${{matrix.cc}}
|
||||
run: cmake .
|
||||
- run: cmake --build .
|
||||
- run: ctest
|
||||
- run: ctest --output-on-failure
|
||||
|
||||
valgrind:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- run: sudo apt update && sudo apt install valgrind
|
||||
- run: cmake -DJANSSON_TEST_WITH_VALGRIND=ON .
|
||||
- run: cmake --build .
|
||||
- run: ctest
|
||||
|
||||
coveralls:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: sudo apt update && sudo apt install curl lcov
|
||||
- run: cmake -DJANSSON_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug .
|
||||
- run: cmake --build .
|
||||
- run: cmake --build . --target coverage
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: coverage.info
|
||||
- run: ctest --output-on-failure
|
||||
|
|
24
CHANGES
24
CHANGES
|
@ -1,3 +1,25 @@
|
|||
Version 2.14.1
|
||||
==============
|
||||
|
||||
Released 2025-03-23
|
||||
|
||||
* Fixes:
|
||||
|
||||
- Fix thread safety of encoding and decoding when `uselocale` or `newlocale`
|
||||
is used to switch locales inside the threads (#674, #675, #677. Thanks to
|
||||
Bruno Haible for the report and help with fixing.)
|
||||
|
||||
- Use David M. Gay's `dtoa()` algorithm to avoid misprinting issues of real
|
||||
numbers that are not exactly representable as a `double` (#680).
|
||||
|
||||
If this is not desirable, use `./configure --disable-dtoa` or `cmake
|
||||
-DUSE_DTOA=OFF .`
|
||||
|
||||
* Build:
|
||||
|
||||
- Make test output nicer in CMake based builds (#683)
|
||||
- Simplify tests (#685)
|
||||
|
||||
Version 2.14
|
||||
============
|
||||
|
||||
|
@ -616,7 +638,7 @@ Released 2011-10-06
|
|||
- Fix identifier decoding under non-UTF-8 locales. (#35)
|
||||
|
||||
- `json_load_file()`: Open the input file in binary mode for maximum
|
||||
compatiblity.
|
||||
compatibility.
|
||||
|
||||
* Documentation:
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
cmake_minimum_required (VERSION 3.1)
|
||||
cmake_minimum_required (VERSION 3.10)
|
||||
project(jansson C)
|
||||
|
||||
# Options
|
||||
option(JANSSON_BUILD_SHARED_LIBS "Build shared libraries." OFF)
|
||||
option(USE_URANDOM "Use /dev/urandom to seed the hash function." ON)
|
||||
option(USE_WINDOWS_CRYPTOAPI "Use CryptGenRandom to seed the hash function." ON)
|
||||
option(USE_DTOA "Use dtoa for optimal floating-point to string conversions." ON)
|
||||
|
||||
if (MSVC)
|
||||
# This option must match the settings used in your program, in particular if you
|
||||
|
@ -35,7 +36,7 @@ endif()
|
|||
# set (JANSSON_VERSION "2.3.1")
|
||||
# set (JANSSON_SOVERSION 2)
|
||||
|
||||
set(JANSSON_DISPLAY_VERSION "2.14")
|
||||
set(JANSSON_DISPLAY_VERSION "2.14.1")
|
||||
|
||||
# This is what is required to match the same numbers as automake's
|
||||
set(JANSSON_VERSION "4.14.0")
|
||||
|
@ -93,6 +94,9 @@ check_function_exists (sched_yield HAVE_SCHED_YIELD)
|
|||
# Check for the int-type includes
|
||||
check_include_files (stdint.h HAVE_STDINT_H)
|
||||
|
||||
include (TestBigEndian)
|
||||
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
|
||||
|
||||
# Check our 64 bit integer sizes
|
||||
check_type_size (__int64 __INT64)
|
||||
check_type_size (int64_t INT64_T)
|
||||
|
@ -193,6 +197,8 @@ endif ()
|
|||
# detect what to use for the 64 bit type.
|
||||
# Note: I will prefer long long if I can get it, as that is what the automake system aimed for.
|
||||
if (NOT DEFINED JSON_INT_T)
|
||||
set (JSON_INTEGER_IS_LONG_LONG 1)
|
||||
|
||||
if (HAVE_LONG_LONG_INT AND (LONG_LONG_INT EQUAL 8))
|
||||
set (JSON_INT_T "long long")
|
||||
elseif (HAVE_INT64_T)
|
||||
|
@ -215,18 +221,7 @@ if (NOT DEFINED JSON_INT_T)
|
|||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
# If locale.h and localeconv() are available, define to 1, otherwise to 0.
|
||||
check_include_files (locale.h HAVE_LOCALE_H)
|
||||
check_function_exists (localeconv HAVE_LOCALECONV)
|
||||
|
||||
if (HAVE_LOCALECONV AND HAVE_LOCALE_H)
|
||||
set (JSON_HAVE_LOCALECONV 1)
|
||||
else ()
|
||||
set (JSON_HAVE_LOCALECONV 0)
|
||||
endif()
|
||||
|
||||
# check if we have setlocale
|
||||
check_function_exists(setlocale HAVE_SETLOCALE)
|
||||
|
||||
# Check what the inline keyword is.
|
||||
|
@ -271,20 +266,20 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_config.h.cmake
|
|||
file (COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
||||
|
||||
add_definitions(-DJANSSON_USING_CMAKE)
|
||||
|
||||
# configure the private config file
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_private_config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/private_include/jansson_private_config.h)
|
||||
|
||||
# and tell the source code to include it
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
include_directories (${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
include_directories (${CMAKE_CURRENT_BINARY_DIR}/private_include)
|
||||
|
||||
# Configuration flags will be set on project later once we have defined the target
|
||||
|
||||
|
||||
# Add the lib sources.
|
||||
file(GLOB JANSSON_SRC src/*.c)
|
||||
if (NOT USE_DTOA)
|
||||
list(FILTER JANSSON_SRC EXCLUDE REGEX ".*dtoa\\.c$")
|
||||
endif()
|
||||
|
||||
set(JANSSON_HDR_PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hashtable.h
|
||||
|
@ -342,7 +337,7 @@ if(JANSSON_BUILD_SHARED_LIBS)
|
|||
)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/jansson.sym")
|
||||
if (VSCRIPT_WORKS)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/jansson.sym")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/jansson.sym")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -358,6 +353,20 @@ else()
|
|||
POSITION_INDEPENDENT_CODE true)
|
||||
endif()
|
||||
|
||||
|
||||
# Now target jansson is declared, set per-target values
|
||||
|
||||
target_compile_definitions(jansson PUBLIC JANSSON_USING_CMAKE)
|
||||
target_compile_definitions(jansson PRIVATE HAVE_CONFIG_H)
|
||||
|
||||
target_include_directories(jansson
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
INTERFACE $<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
add_library( jansson::jansson ALIAS jansson )
|
||||
|
||||
|
||||
if (JANSSON_EXAMPLES)
|
||||
add_executable(simple_parse "${CMAKE_CURRENT_SOURCE_DIR}/examples/simple_parse.c")
|
||||
target_link_libraries(simple_parse jansson)
|
||||
|
@ -537,6 +546,11 @@ if (NOT JANSSON_WITHOUT_TESTS)
|
|||
if (IS_DIRECTORY ${TESTDIR})
|
||||
get_filename_component(TNAME ${TESTDIR} NAME)
|
||||
|
||||
if ((USE_DTOA AND EXISTS ${TESTDIR}/skip_if_dtoa) OR
|
||||
(NOT USE_DTOA AND EXISTS ${TESTDIR}/skip_unless_dtoa))
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if (JANSSON_TEST_WITH_VALGRIND)
|
||||
add_test(memcheck__${SUITE}__${TNAME}
|
||||
${MEMCHECK_COMMAND} ${SUITE_TEST_CMD} ${TESTDIR})
|
||||
|
@ -602,9 +616,7 @@ foreach(p LIB BIN INCLUDE CMAKE)
|
|||
endforeach()
|
||||
|
||||
# Generate the config file for the build-tree.
|
||||
set(JANSSON__INCLUDE_DIRS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
set(JANSSON__INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
set(JANSSON_INCLUDE_DIRS ${JANSSON__INCLUDE_DIRS} CACHE PATH "Jansson include directories")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/janssonConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/janssonConfig.cmake
|
||||
|
|
3
CONTRIBUTING.md
Normal file
3
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
Hi, and thanks for contributing!
|
||||
|
||||
Please remember to add tests and documentation for new functionality. Backwards incompatible changes or features that are not directly related to JSON are likely to be rejected.
|
26
LICENSE
26
LICENSE
|
@ -1,4 +1,11 @@
|
|||
Copyright (c) 2009-2020 Petri Lehtinen <petri@digip.org>
|
||||
# License
|
||||
|
||||
This project is licensed under the MIT license, except where otherwise noted.
|
||||
The full text of the MIT license is included below.
|
||||
|
||||
## MIT License
|
||||
|
||||
Copyright (c) 2009-2024 Petri Lehtinen <petri@digip.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -17,3 +24,20 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## Exceptions
|
||||
|
||||
### `src/dtoa.c`
|
||||
|
||||
Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose without fee is hereby granted, provided that this entire notice
|
||||
is included in all copies of any software which is or includes a copy
|
||||
or modification of this software and in all copies of the supporting
|
||||
documentation for such software.
|
||||
|
||||
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
|
||||
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
|
|
41
README.rst
41
README.rst
|
@ -1,14 +1,10 @@
|
|||
Jansson README
|
||||
==============
|
||||
|
||||
.. image:: https://github.com/akheron/jansson/workflows/tests/badge.svg
|
||||
:target: https://github.com/akheron/jansson/actions
|
||||
.. |tests| image:: https://github.com/akheron/jansson/workflows/tests/badge.svg
|
||||
.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/lmhkkc4q8cwc65ko
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/lmhkkc4q8cwc65ko
|
||||
:target: https://ci.appveyor.com/project/akheron/jansson
|
||||
|
||||
.. image:: https://coveralls.io/repos/akheron/jansson/badge.png?branch=master
|
||||
:target: https://coveralls.io/r/akheron/jansson?branch=master
|
||||
|tests| |appveyor|
|
||||
|
||||
Jansson_ is a C library for encoding, decoding and manipulating JSON
|
||||
data. Its main features and design principles are:
|
||||
|
@ -26,24 +22,11 @@ data. Its main features and design principles are:
|
|||
Jansson is licensed under the `MIT license`_; see LICENSE in the
|
||||
source distribution for details.
|
||||
|
||||
|
||||
Compilation and Installation
|
||||
----------------------------
|
||||
|
||||
You can download and install Jansson using the `vcpkg <https://github.com/Microsoft/vcpkg/>`_ dependency manager:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install jansson
|
||||
|
||||
The Jansson port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please `create an issue or pull request <https://github.com/Microsoft/vcpkg/>`_ on the vcpkg repository.
|
||||
|
||||
If you obtained a `source tarball`_ from the "Releases" section of the main
|
||||
site just use the standard autotools commands::
|
||||
If you obtained a ``jansson-X.Y.tar.*`` tarball from GitHub Releases, just use
|
||||
the standard autotools commands::
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
|
@ -53,9 +36,8 @@ To run the test suite, invoke::
|
|||
|
||||
$ make check
|
||||
|
||||
If the source has been checked out from a Git repository, the
|
||||
./configure script has to be generated first. The easiest way is to
|
||||
use autoreconf::
|
||||
If the source has been checked out from a Git repository, the ``configure``
|
||||
script has to be generated first. The easiest way is to use autoreconf::
|
||||
|
||||
$ autoreconf -i
|
||||
|
||||
|
@ -74,8 +56,15 @@ Then, point your browser to ``doc/_build/html/index.html``. Sphinx_
|
|||
1.0 or newer is required to generate the documentation.
|
||||
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
* `Documentation <http://jansson.readthedocs.io/en/latest/>`_
|
||||
* `Issue tracker <https://github.com/akheron/jansson/issues>`_
|
||||
* `Mailing list <http://groups.google.com/group/jansson-users>`_
|
||||
* `Wiki <https://github.com/akheron/jansson/wiki>`_ contains some development documentation
|
||||
|
||||
.. _Jansson: http://www.digip.org/jansson/
|
||||
.. _`Comprehensive documentation`: http://jansson.readthedocs.io/en/latest/
|
||||
.. _`MIT license`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`source tarball`: http://www.digip.org/jansson#releases
|
||||
.. _Sphinx: http://sphinx.pocoo.org/
|
||||
|
|
9
SECURITY.md
Normal file
9
SECURITY.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Latest released version.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Send an email to petri@digip.org.
|
|
@ -32,10 +32,6 @@
|
|||
otherwise to 0. */
|
||||
#define JSON_INTEGER_IS_LONG_LONG 1
|
||||
|
||||
/* If locale.h and localeconv() are available, define to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV 0
|
||||
|
||||
/* Maximum recursion depth for parsing JSON input.
|
||||
This limits the depth of e.g. array-within-array constructions. */
|
||||
#define JSON_PARSER_MAX_DEPTH 2048
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
#define JANSSON_USING_CMAKE
|
||||
#endif
|
||||
|
||||
/* Note: when using cmake, JSON_INTEGER_IS_LONG_LONG is not defined nor used,
|
||||
* as we will also check for __int64 etc types.
|
||||
* (the definition was used in the automake system) */
|
||||
/* If your compiler supports the `long long` type and the strtoll()
|
||||
library function, JSON_INTEGER_IS_LONG_LONG is defined to 1,
|
||||
otherwise to 0. */
|
||||
#cmakedefine JSON_INTEGER_IS_LONG_LONG 1
|
||||
|
||||
/* Bring in the cmake-detected defines */
|
||||
#cmakedefine HAVE_STDINT_H 1
|
||||
|
@ -56,9 +57,6 @@
|
|||
#define JSON_INTEGER_FORMAT @JSON_INTEGER_FORMAT@
|
||||
|
||||
|
||||
/* If locale.h and localeconv() are available, define to 1, otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV @JSON_HAVE_LOCALECONV@
|
||||
|
||||
/* If __atomic builtins are available they will be used to manage
|
||||
reference counts of json_t. */
|
||||
#define JSON_HAVE_ATOMIC_BUILTINS @JSON_HAVE_ATOMIC_BUILTINS@
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#cmakedefine HAVE_LOCALE_H 1
|
||||
#cmakedefine HAVE_SETLOCALE 1
|
||||
|
||||
#cmakedefine WORDS_BIGENDIAN 1
|
||||
|
||||
#cmakedefine HAVE_INT32_T 1
|
||||
#ifndef HAVE_INT32_T
|
||||
# define int32_t @JSON_INT32@
|
||||
|
@ -50,4 +52,11 @@
|
|||
#cmakedefine USE_URANDOM 1
|
||||
#cmakedefine USE_WINDOWS_CRYPTOAPI 1
|
||||
|
||||
#cmakedefine USE_DTOA 1
|
||||
#if USE_DTOA
|
||||
# define DTOA_ENABLED 1
|
||||
#else
|
||||
# define DTOA_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define INITIAL_HASHTABLE_ORDER @JANSSON_INITIAL_HASHTABLE_ORDER@
|
||||
|
|
25
configure.ac
25
configure.ac
|
@ -1,5 +1,5 @@
|
|||
AC_PREREQ([2.60])
|
||||
AC_INIT([jansson], [2.14], [https://github.com/akheron/jansson/issues])
|
||||
AC_INIT([jansson], [2.14.1], [https://github.com/akheron/jansson/issues])
|
||||
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AM_INIT_AUTOMAKE([1.10 foreign])
|
||||
|
@ -25,6 +25,8 @@ AC_TYPE_UINT16_T
|
|||
AC_TYPE_UINT8_T
|
||||
AC_TYPE_LONG_LONG_INT
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
AC_C_INLINE
|
||||
case $ac_cv_c_inline in
|
||||
yes) json_inline=inline;;
|
||||
|
@ -34,7 +36,7 @@ esac
|
|||
AC_SUBST([json_inline])
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_FUNCS([close getpid gettimeofday localeconv open read sched_yield strtoll])
|
||||
AC_CHECK_FUNCS([close getpid gettimeofday open read setlocale sched_yield strtoll])
|
||||
|
||||
AC_MSG_CHECKING([for gcc __sync builtins])
|
||||
have_sync_builtins=no
|
||||
|
@ -74,12 +76,6 @@ case "$ac_cv_type_long_long_int$ac_cv_func_strtoll" in
|
|||
esac
|
||||
AC_SUBST([json_have_long_long])
|
||||
|
||||
case "$ac_cv_header_locale_h$ac_cv_func_localeconv" in
|
||||
yesyes) json_have_localeconv=1;;
|
||||
*) json_have_localeconv=0;;
|
||||
esac
|
||||
AC_SUBST([json_have_localeconv])
|
||||
|
||||
# Features
|
||||
AC_ARG_ENABLE([urandom],
|
||||
[AS_HELP_STRING([--disable-urandom],
|
||||
|
@ -142,6 +138,19 @@ JSON_SYMVER_LDFLAGS=
|
|||
AC_CHECK_DECL([__GLIBC__], [JSON_SYMVER_LDFLAGS=-Wl,--default-symver])
|
||||
AC_SUBST([JSON_SYMVER_LDFLAGS])
|
||||
|
||||
AC_ARG_ENABLE([dtoa],
|
||||
[AS_HELP_STRING([--enable-dtoa], [Use dtoa for optimal floating point to string conversion])],
|
||||
[case "$enableval" in
|
||||
yes) dtoa=yes ;;
|
||||
no) dtoa=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-dtoa]) ;;
|
||||
esac], [dtoa=yes])
|
||||
if test "$dtoa" = "yes"; then
|
||||
AC_DEFINE([DTOA_ENABLED], [1],
|
||||
[Define to 1 to use dtoa to convert floating points to strings])
|
||||
fi
|
||||
AM_CONDITIONAL([DTOA_ENABLED], [test "$dtoa" = "yes"])
|
||||
|
||||
AC_ARG_ENABLE([ossfuzzers],
|
||||
[AS_HELP_STRING([--enable-ossfuzzers],
|
||||
[Whether to generate the fuzzers for OSS-Fuzz])],
|
||||
|
|
9
doc/.readthedocs.yaml
Normal file
9
doc/.readthedocs.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.12"
|
||||
|
||||
sphinx:
|
||||
configuration: doc/conf.py
|
|
@ -48,7 +48,7 @@ copyright = u'2009-2020, Petri Lehtinen'
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '2.14'
|
||||
version = '2.14.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ int main(int argc, char *argv[]) {
|
|||
sha = json_object_get(data, "sha");
|
||||
if (!json_is_string(sha)) {
|
||||
fprintf(stderr, "error: commit %d: sha is not a string\n", (int)(i + 1));
|
||||
json_decref(root);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
find . -type f -a '(' -name '*.c' -o -name '*.h' ')' | xargs clang-format -i
|
||||
git ls-files | grep '\.[ch]$' | xargs clang-format -i
|
||||
|
|
|
@ -12,13 +12,16 @@ fi
|
|||
errors=0
|
||||
paths=$(git ls-files | grep '\.[ch]$')
|
||||
for path in $paths; do
|
||||
echo "Checking $path"
|
||||
$CLANG_FORMAT $path > $path.formatted
|
||||
in=$(cat $path)
|
||||
out=$($CLANG_FORMAT $path)
|
||||
out=$(cat $path.formatted)
|
||||
|
||||
if [ "$in" != "$out" ]; then
|
||||
diff -u -L $path -L "$path.formatted" $path - <<<$out
|
||||
diff -u $path $path.formatted
|
||||
errors=1
|
||||
fi
|
||||
rm $path.formatted
|
||||
done
|
||||
|
||||
if [ $errors -ne 0 ]; then
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
EXTRA_DIST = jansson.def
|
||||
EXTRA_DIST = jansson.def dtoa.c
|
||||
|
||||
include_HEADERS = jansson.h
|
||||
nodist_include_HEADERS = jansson_config.h
|
||||
|
@ -22,9 +22,14 @@ libjansson_la_SOURCES = \
|
|||
utf.h \
|
||||
value.c \
|
||||
version.c
|
||||
|
||||
if DTOA_ENABLED
|
||||
libjansson_la_SOURCES += dtoa.c
|
||||
endif
|
||||
|
||||
libjansson_la_LDFLAGS = \
|
||||
-no-undefined \
|
||||
-export-symbols-regex '^json_|^jansson_' \
|
||||
-version-info 18:0:14 \
|
||||
-version-info 18:1:14 \
|
||||
@JSON_SYMVER_LDFLAGS@ \
|
||||
@JSON_BSYMBOLIC_LDFLAGS@
|
||||
|
|
6265
src/dtoa.c
Normal file
6265
src/dtoa.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,10 +23,10 @@
|
|||
#include "strbuffer.h"
|
||||
#include "utf.h"
|
||||
|
||||
#define MAX_INTEGER_STR_LENGTH 100
|
||||
#define MAX_REAL_STR_LENGTH 100
|
||||
#define MAX_INTEGER_STR_LENGTH 25
|
||||
#define MAX_REAL_STR_LENGTH 25
|
||||
|
||||
#define FLAGS_TO_INDENT(f) ((f)&0x1F)
|
||||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
||||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
||||
|
||||
struct buffer {
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ extern "C" {
|
|||
|
||||
#define JANSSON_MAJOR_VERSION 2
|
||||
#define JANSSON_MINOR_VERSION 14
|
||||
#define JANSSON_MICRO_VERSION 0
|
||||
#define JANSSON_MICRO_VERSION 1
|
||||
|
||||
/* Micro version is omitted if it's 0 */
|
||||
#define JANSSON_VERSION "2.14"
|
||||
#define JANSSON_VERSION "2.14.1"
|
||||
|
||||
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
||||
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
|
||||
|
@ -379,14 +379,14 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
|
|||
/* encoding */
|
||||
|
||||
#define JSON_MAX_INDENT 0x1F
|
||||
#define JSON_INDENT(n) ((n)&JSON_MAX_INDENT)
|
||||
#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT)
|
||||
#define JSON_COMPACT 0x20
|
||||
#define JSON_ENSURE_ASCII 0x40
|
||||
#define JSON_SORT_KEYS 0x80
|
||||
#define JSON_PRESERVE_ORDER 0x100
|
||||
#define JSON_ENCODE_ANY 0x200
|
||||
#define JSON_ESCAPE_SLASH 0x400
|
||||
#define JSON_REAL_PRECISION(n) (((n)&0x1F) << 11)
|
||||
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
||||
#define JSON_EMBED 0x10000
|
||||
|
||||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
||||
|
|
|
@ -32,10 +32,6 @@
|
|||
otherwise to 0. */
|
||||
#define JSON_INTEGER_IS_LONG_LONG @json_have_long_long@
|
||||
|
||||
/* If locale.h and localeconv() are available, define to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV @json_have_localeconv@
|
||||
|
||||
/* If __atomic builtins are available they will be used to manage
|
||||
reference counts of json_t. */
|
||||
#define JSON_HAVE_ATOMIC_BUILTINS @json_have_atomic_builtins@
|
||||
|
|
|
@ -562,8 +562,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) {
|
|||
long unpacked = 0;
|
||||
|
||||
if (gotopt || json_object_size(root) != key_set.size) {
|
||||
json_object_foreach(root, key, value) {
|
||||
key_len = strlen(key);
|
||||
json_object_keylen_foreach(root, key, key_len, value) {
|
||||
if (!hashtable_get(&key_set, key, key_len)) {
|
||||
unpacked++;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define STRBUFFER_MIN_SIZE 16
|
||||
#define STRBUFFER_FACTOR 2
|
||||
#define STRBUFFER_SIZE_MAX ((size_t)-1)
|
||||
#define STRBUFFER_SIZE_MAX ((size_t)(-1))
|
||||
|
||||
int strbuffer_init(strbuffer_t *strbuff) {
|
||||
strbuff->size = STRBUFFER_MIN_SIZE;
|
||||
|
|
165
src/strconv.c
165
src/strconv.c
|
@ -11,57 +11,42 @@
|
|||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
#include <locale.h>
|
||||
|
||||
/*
|
||||
- This code assumes that the decimal separator is exactly one
|
||||
character.
|
||||
|
||||
- If setlocale() is called by another thread between the call to
|
||||
localeconv() and the call to sprintf() or strtod(), the result may
|
||||
be wrong. setlocale() is not thread-safe and should not be used
|
||||
this way. Multi-threaded programs should use uselocale() instead.
|
||||
get_decimal_point() and the call to sprintf() or strtod(), the
|
||||
result may be wrong. setlocale() is not thread-safe and should
|
||||
not be used this way. Multi-threaded programs should use
|
||||
uselocale() instead.
|
||||
*/
|
||||
static char get_decimal_point() {
|
||||
char buf[3];
|
||||
sprintf(buf, "%#.0f", 1.0); // "1." in the current locale
|
||||
return buf[1];
|
||||
}
|
||||
|
||||
static void to_locale(strbuffer_t *strbuffer) {
|
||||
const char *point;
|
||||
char point;
|
||||
char *pos;
|
||||
|
||||
point = localeconv()->decimal_point;
|
||||
if (*point == '.') {
|
||||
point = get_decimal_point();
|
||||
if (point == '.') {
|
||||
/* No conversion needed */
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strchr(strbuffer->value, '.');
|
||||
if (pos)
|
||||
*pos = *point;
|
||||
*pos = point;
|
||||
}
|
||||
|
||||
static void from_locale(char *buffer) {
|
||||
const char *point;
|
||||
char *pos;
|
||||
|
||||
point = localeconv()->decimal_point;
|
||||
if (*point == '.') {
|
||||
/* No conversion needed */
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strchr(buffer, *point);
|
||||
if (pos)
|
||||
*pos = '.';
|
||||
}
|
||||
#endif
|
||||
|
||||
int jsonp_strtod(strbuffer_t *strbuffer, double *out) {
|
||||
double value;
|
||||
char *end;
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
to_locale(strbuffer);
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
value = strtod(strbuffer->value, &end);
|
||||
|
@ -76,6 +61,127 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if DTOA_ENABLED
|
||||
/* see dtoa.c */
|
||||
char *dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve,
|
||||
char *buf, size_t blen);
|
||||
|
||||
int jsonp_dtostr(char *buffer, size_t size, double value, int precision) {
|
||||
/* adapted from `format_float_short()` in
|
||||
* https://github.com/python/cpython/blob/2cf18a44303b6d84faa8ecffaecc427b53ae121e/Python/pystrtod.c#L969
|
||||
*/
|
||||
char digits[25];
|
||||
char *digits_end;
|
||||
int mode = precision == 0 ? 0 : 2;
|
||||
int decpt, sign, exp_len, exp = 0, use_exp = 0;
|
||||
int digits_len, vdigits_start, vdigits_end;
|
||||
char *p;
|
||||
|
||||
if (dtoa_r(value, mode, precision, &decpt, &sign, &digits_end, digits, 25) == NULL) {
|
||||
// digits is too short => should not happen
|
||||
return -1;
|
||||
}
|
||||
|
||||
digits_len = digits_end - digits;
|
||||
if (decpt <= -4 || decpt > 16) {
|
||||
use_exp = 1;
|
||||
exp = decpt - 1;
|
||||
decpt = 1;
|
||||
}
|
||||
|
||||
vdigits_start = decpt <= 0 ? decpt - 1 : 0;
|
||||
vdigits_end = digits_len;
|
||||
if (!use_exp) {
|
||||
/* decpt + 1 to add ".0" if value is an integer */
|
||||
vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1;
|
||||
} else {
|
||||
vdigits_end = vdigits_end > decpt ? vdigits_end : decpt;
|
||||
}
|
||||
|
||||
if (
|
||||
/* sign, decimal point and trailing 0 byte */
|
||||
(size_t)(3 +
|
||||
|
||||
/* total digit count (including zero padding on both sides) */
|
||||
(vdigits_end - vdigits_start) +
|
||||
|
||||
/* exponent "e+100", max 3 numerical digits */
|
||||
(use_exp ? 5 : 0)) > size) {
|
||||
/* buffer is too short */
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = buffer;
|
||||
if (sign == 1) {
|
||||
*p++ = '-';
|
||||
}
|
||||
|
||||
/* note that exactly one of the three 'if' conditions is true,
|
||||
so we include exactly one decimal point */
|
||||
/* Zero padding on left of digit string */
|
||||
if (decpt <= 0) {
|
||||
memset(p, '0', decpt - vdigits_start);
|
||||
p += decpt - vdigits_start;
|
||||
*p++ = '.';
|
||||
memset(p, '0', 0 - decpt);
|
||||
p += 0 - decpt;
|
||||
} else {
|
||||
memset(p, '0', 0 - vdigits_start);
|
||||
p += 0 - vdigits_start;
|
||||
}
|
||||
|
||||
/* Digits, with included decimal point */
|
||||
if (0 < decpt && decpt <= digits_len) {
|
||||
strncpy(p, digits, decpt - 0);
|
||||
p += decpt - 0;
|
||||
*p++ = '.';
|
||||
strncpy(p, digits + decpt, digits_len - decpt);
|
||||
p += digits_len - decpt;
|
||||
} else {
|
||||
strncpy(p, digits, digits_len);
|
||||
p += digits_len;
|
||||
}
|
||||
|
||||
/* And zeros on the right */
|
||||
if (digits_len < decpt) {
|
||||
memset(p, '0', decpt - digits_len);
|
||||
p += decpt - digits_len;
|
||||
*p++ = '.';
|
||||
memset(p, '0', vdigits_end - decpt);
|
||||
p += vdigits_end - decpt;
|
||||
} else {
|
||||
memset(p, '0', vdigits_end - digits_len);
|
||||
p += vdigits_end - digits_len;
|
||||
}
|
||||
|
||||
if (p[-1] == '.')
|
||||
p--;
|
||||
|
||||
if (use_exp) {
|
||||
*p++ = 'e';
|
||||
exp_len = sprintf(p, "%d", exp);
|
||||
p += exp_len;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return (int)(p - buffer);
|
||||
}
|
||||
#else /* DTOA_ENABLED == 0 */
|
||||
static void from_locale(char *buffer) {
|
||||
char point;
|
||||
char *pos;
|
||||
|
||||
point = get_decimal_point();
|
||||
if (point == '.') {
|
||||
/* No conversion needed */
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strchr(buffer, point);
|
||||
if (pos)
|
||||
*pos = '.';
|
||||
}
|
||||
|
||||
int jsonp_dtostr(char *buffer, size_t size, double value, int precision) {
|
||||
int ret;
|
||||
char *start, *end;
|
||||
|
@ -92,9 +198,7 @@ int jsonp_dtostr(char *buffer, size_t size, double value, int precision) {
|
|||
if (length >= size)
|
||||
return -1;
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
from_locale(buffer);
|
||||
#endif
|
||||
|
||||
/* Make sure there's a dot or 'e' in the output. Otherwise
|
||||
a real is converted to an integer when decoding */
|
||||
|
@ -130,3 +234,4 @@ int jsonp_dtostr(char *buffer, size_t size, double value, int precision) {
|
|||
|
||||
return (int)length;
|
||||
}
|
||||
#endif
|
||||
|
|
28
src/value.c
28
src/value.c
|
@ -191,13 +191,14 @@ int json_object_clear(json_t *json) {
|
|||
|
||||
int json_object_update(json_t *object, json_t *other) {
|
||||
const char *key;
|
||||
size_t key_len;
|
||||
json_t *value;
|
||||
|
||||
if (!json_is_object(object) || !json_is_object(other))
|
||||
return -1;
|
||||
|
||||
json_object_foreach(other, key, value) {
|
||||
if (json_object_set_nocheck(object, key, value))
|
||||
json_object_keylen_foreach(other, key, key_len, value) {
|
||||
if (json_object_setn_nocheck(object, key, key_len, value))
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -222,14 +223,15 @@ int json_object_update_existing(json_t *object, json_t *other) {
|
|||
|
||||
int json_object_update_missing(json_t *object, json_t *other) {
|
||||
const char *key;
|
||||
size_t key_len;
|
||||
json_t *value;
|
||||
|
||||
if (!json_is_object(object) || !json_is_object(other))
|
||||
return -1;
|
||||
|
||||
json_object_foreach(other, key, value) {
|
||||
if (!json_object_get(object, key))
|
||||
json_object_set_nocheck(object, key, value);
|
||||
json_object_keylen_foreach(other, key, key_len, value) {
|
||||
if (!json_object_getn(object, key, key_len))
|
||||
json_object_setn_nocheck(object, key, key_len, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -250,7 +252,7 @@ int do_object_update_recursive(json_t *object, json_t *other, hashtable_t *paren
|
|||
return -1;
|
||||
|
||||
json_object_keylen_foreach(other, key, key_len, value) {
|
||||
json_t *v = json_object_get(object, key);
|
||||
json_t *v = json_object_getn(object, key, key_len);
|
||||
|
||||
if (json_is_object(v) && json_is_object(value)) {
|
||||
if (do_object_update_recursive(v, value, parents)) {
|
||||
|
@ -352,13 +354,14 @@ void *json_object_key_to_iter(const char *key) {
|
|||
|
||||
static int json_object_equal(const json_t *object1, const json_t *object2) {
|
||||
const char *key;
|
||||
size_t key_len;
|
||||
const json_t *value1, *value2;
|
||||
|
||||
if (json_object_size(object1) != json_object_size(object2))
|
||||
return 0;
|
||||
|
||||
json_object_foreach((json_t *)object1, key, value1) {
|
||||
value2 = json_object_get(object2, key);
|
||||
json_object_keylen_foreach((json_t *)object1, key, key_len, value1) {
|
||||
value2 = json_object_getn(object2, key, key_len);
|
||||
|
||||
if (!json_equal(value1, value2))
|
||||
return 0;
|
||||
|
@ -371,13 +374,15 @@ static json_t *json_object_copy(json_t *object) {
|
|||
json_t *result;
|
||||
|
||||
const char *key;
|
||||
size_t key_len;
|
||||
json_t *value;
|
||||
|
||||
result = json_object();
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
json_object_foreach(object, key, value) json_object_set_nocheck(result, key, value);
|
||||
json_object_keylen_foreach(object, key, key_len, value)
|
||||
json_object_setn_nocheck(result, key, key_len, value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -400,11 +405,14 @@ static json_t *json_object_deep_copy(const json_t *object, hashtable_t *parents)
|
|||
iter = json_object_iter((json_t *)object);
|
||||
while (iter) {
|
||||
const char *key;
|
||||
size_t key_len;
|
||||
const json_t *value;
|
||||
key = json_object_iter_key(iter);
|
||||
key_len = json_object_iter_key_len(iter);
|
||||
value = json_object_iter_value(iter);
|
||||
|
||||
if (json_object_set_new_nocheck(result, key, do_deep_copy(value, parents))) {
|
||||
if (json_object_setn_new_nocheck(result, key, key_len,
|
||||
do_deep_copy(value, parents))) {
|
||||
json_decref(result);
|
||||
result = NULL;
|
||||
break;
|
||||
|
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
|
@ -7,6 +7,7 @@ suites/api/test_cpp
|
|||
suites/api/test_dump
|
||||
suites/api/test_dump_callback
|
||||
suites/api/test_equal
|
||||
suites/api/test_fixed_size
|
||||
suites/api/test_load
|
||||
suites/api/test_load_callback
|
||||
suites/api/test_loadb
|
||||
|
|
|
@ -35,7 +35,6 @@ struct config {
|
|||
int ensure_ascii;
|
||||
int sort_keys;
|
||||
int strip;
|
||||
int use_env;
|
||||
int have_hashseed;
|
||||
int hashseed;
|
||||
int precision;
|
||||
|
@ -81,11 +80,10 @@ static char *loadfile(FILE *file) {
|
|||
|
||||
static void read_conf(FILE *conffile) {
|
||||
char *buffer, *line, *val;
|
||||
conf.have_hashseed = 0;
|
||||
|
||||
buffer = loadfile(conffile);
|
||||
for (line = strtok(buffer, "\r\n"); line; line = strtok(NULL, "\r\n")) {
|
||||
if (!strncmp(line, "export ", 7))
|
||||
continue;
|
||||
val = strchr(line, '=');
|
||||
if (!val) {
|
||||
printf("invalid configuration line\n");
|
||||
|
@ -110,8 +108,6 @@ static void read_conf(FILE *conffile) {
|
|||
if (!strcmp(line, "HASHSEED")) {
|
||||
conf.have_hashseed = 1;
|
||||
conf.hashseed = atoi(val);
|
||||
} else {
|
||||
conf.have_hashseed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,10 +134,16 @@ static int cmpfile(const char *str, const char *path, const char *fname) {
|
|||
}
|
||||
|
||||
buffer = loadfile(file);
|
||||
if (strcmp(buffer, str) != 0)
|
||||
if (strcmp(buffer, str) != 0) {
|
||||
fprintf(stderr, "=== Expected %s ===\n", fname);
|
||||
fprintf(stderr, "%s\n", buffer);
|
||||
fprintf(stderr, "=== Actual %s ===\n", fname);
|
||||
fprintf(stderr, "%s\n", str);
|
||||
ret = 1;
|
||||
else
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
|
||||
|
@ -206,8 +208,9 @@ int use_conf(char *test_path) {
|
|||
buffer = loadfile(infile);
|
||||
json = json_loads(strip(buffer), 0, &error);
|
||||
free(buffer);
|
||||
} else
|
||||
} else {
|
||||
json = json_loadf(infile, 0, &error);
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
|
||||
|
@ -227,108 +230,6 @@ int use_conf(char *test_path) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int getenv_int(const char *name) {
|
||||
char *value, *end;
|
||||
long result;
|
||||
|
||||
value = getenv(name);
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
result = strtol(value, &end, 10);
|
||||
if (*end != '\0')
|
||||
return 0;
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
int use_env() {
|
||||
int indent, precision;
|
||||
size_t flags = 0;
|
||||
json_t *json;
|
||||
json_error_t error;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* On Windows, set stdout and stderr to binary mode to avoid
|
||||
outputting DOS line terminators */
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
_setmode(_fileno(stderr), _O_BINARY);
|
||||
#endif
|
||||
|
||||
indent = getenv_int("JSON_INDENT");
|
||||
if (indent < 0 || indent > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_INDENT: %d\n", indent);
|
||||
return 2;
|
||||
}
|
||||
if (indent > 0)
|
||||
flags |= JSON_INDENT(indent);
|
||||
|
||||
if (getenv_int("JSON_COMPACT") > 0)
|
||||
flags |= JSON_COMPACT;
|
||||
|
||||
if (getenv_int("JSON_ENSURE_ASCII"))
|
||||
flags |= JSON_ENSURE_ASCII;
|
||||
|
||||
if (getenv_int("JSON_PRESERVE_ORDER"))
|
||||
flags |= JSON_PRESERVE_ORDER;
|
||||
|
||||
if (getenv_int("JSON_SORT_KEYS"))
|
||||
flags |= JSON_SORT_KEYS;
|
||||
|
||||
precision = getenv_int("JSON_REAL_PRECISION");
|
||||
if (precision < 0 || precision > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n", precision);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (getenv("HASHSEED"))
|
||||
json_object_seed(getenv_int("HASHSEED"));
|
||||
|
||||
if (precision > 0)
|
||||
flags |= JSON_REAL_PRECISION(precision);
|
||||
|
||||
if (getenv_int("STRIP")) {
|
||||
/* Load to memory, strip leading and trailing whitespace */
|
||||
size_t size = 0, used = 0;
|
||||
char *buffer = NULL, *buf_ck = NULL;
|
||||
|
||||
while (1) {
|
||||
size_t count;
|
||||
|
||||
size = (size == 0 ? 128 : size * 2);
|
||||
buf_ck = realloc(buffer, size);
|
||||
if (!buf_ck) {
|
||||
fprintf(stderr, "Unable to allocate %d bytes\n", (int)size);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
buffer = buf_ck;
|
||||
|
||||
count = fread(buffer + used, 1, size - used, stdin);
|
||||
if (count < size - used) {
|
||||
buffer[used + count] = '\0';
|
||||
break;
|
||||
}
|
||||
used += count;
|
||||
}
|
||||
|
||||
json = json_loads(strip(buffer), 0, &error);
|
||||
free(buffer);
|
||||
} else
|
||||
json = json_loadf(stdin, 0, &error);
|
||||
|
||||
if (!json) {
|
||||
fprintf(stderr, "%d %d %d\n%s\n", error.line, error.column, error.position,
|
||||
error.text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
json_dumpf(json, stdout, flags);
|
||||
json_decref(json);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
char *test_path = NULL;
|
||||
|
@ -344,23 +245,17 @@ int main(int argc, char *argv[]) {
|
|||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--strip"))
|
||||
conf.strip = 1;
|
||||
else if (!strcmp(argv[i], "--env"))
|
||||
conf.use_env = 1;
|
||||
else
|
||||
test_path = argv[i];
|
||||
}
|
||||
|
||||
if (conf.use_env)
|
||||
return use_env();
|
||||
else {
|
||||
if (!test_path)
|
||||
goto usage;
|
||||
|
||||
return use_conf(test_path);
|
||||
if (!test_path) {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
return use_conf(test_path);
|
||||
|
||||
usage:
|
||||
fprintf(stderr, "argc =%d\n", argc);
|
||||
fprintf(stderr, "usage: %s [--strip] [--env] test_dir\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s [--strip] test_dir\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ grep 'json_\|jansson_' $top_srcdir/src/jansson.def \
|
|||
nm -D $SOFILE >/dev/null >$test_log/symbols 2>/dev/null \
|
||||
|| exit 77 # Skip if "nm -D" doesn't seem to work
|
||||
|
||||
grep ' [DT] ' $test_log/symbols | cut -d' ' -f3 | grep -v '^_' | sort >$test_log/output
|
||||
grep ' [DT] ' $test_log/symbols | cut -d' ' -f3 | grep -v '^_' | sed 's/@@libjansson.*//' | sort >$test_log/output
|
||||
|
||||
if ! cmp -s $test_log/exports $test_log/output; then
|
||||
diff -u $test_log/exports $test_log/output >&2
|
||||
|
|
|
@ -127,6 +127,7 @@ static void test_keylen(void) {
|
|||
|
||||
static void test_invalid_keylen(void) {
|
||||
json_t *obj = json_object();
|
||||
json_t *empty_obj = json_object();
|
||||
const char key[] = {'t', 'e', 's', 't', '1'};
|
||||
|
||||
json_object_set_new_nocheck(obj, "test1", json_true());
|
||||
|
@ -149,7 +150,14 @@ static void test_invalid_keylen(void) {
|
|||
if (!json_object_del(obj, NULL))
|
||||
fail("json_object_del with NULL failed");
|
||||
|
||||
if (!json_object_deln(empty_obj, key, sizeof(key)))
|
||||
fail("json_object_deln with empty object failed");
|
||||
|
||||
if (!json_object_deln(obj, key, sizeof(key) - 1))
|
||||
fail("json_object_deln with incomplete key failed");
|
||||
|
||||
json_decref(obj);
|
||||
json_decref(empty_obj);
|
||||
}
|
||||
|
||||
static void test_binary_keys(void) {
|
||||
|
@ -166,6 +174,21 @@ static void test_binary_keys(void) {
|
|||
if (!json_is_true(json_object_getn(obj, (const char *)&key1, sizeof(key2))))
|
||||
fail("cannot get integer key2");
|
||||
|
||||
if (json_object_size(obj) != 2)
|
||||
fail("binary object size missmatch");
|
||||
|
||||
if (json_object_deln(obj, (const char *)&key1, sizeof(key1)))
|
||||
fail("cannot del integer key1");
|
||||
|
||||
if (json_object_size(obj) != 1)
|
||||
fail("binary object size missmatch");
|
||||
|
||||
if (json_object_deln(obj, (const char *)&key2, sizeof(key2)))
|
||||
fail("cannot del integer key2");
|
||||
|
||||
if (json_object_size(obj) != 0)
|
||||
fail("binary object size missmatch");
|
||||
|
||||
json_decref(obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_COMPACT=1
|
||||
export JSON_COMPACT
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
JSON_COMPACT=1
|
||||
HASHSEED=1
|
||||
export JSON_COMPACT HASHSEED
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_ENSURE_ASCII=1
|
||||
export JSON_ENSURE_ASCII
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_INDENT=4
|
||||
export JSON_INDENT
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
JSON_INDENT=4
|
||||
JSON_COMPACT=1
|
||||
export JSON_INDENT JSON_COMPACT
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
JSON_INDENT=4
|
||||
JSON_COMPACT=1
|
||||
HASHSEED=1
|
||||
export JSON_INDENT JSON_COMPACT HASHSEED
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
JSON_INDENT=4
|
||||
HASHSEED=1
|
||||
export JSON_INDENT HASHSEED
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
HASHSEED=1
|
||||
export HASHSEED
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_PRESERVE_ORDER=1
|
||||
export JSON_PRESERVE_ORDER
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_REAL_PRECISION=4
|
||||
export JSON_REAL_PRECISION
|
||||
|
|
|
@ -1 +1 @@
|
|||
[1.23456789, 1.0, 1.0000000000000002]
|
||||
[1.23456789, 1.0, 1.0000000000000002, 1.23456e99, 1.23456e-99, 0.0000000000012345]
|
||||
|
|
|
@ -1 +1 @@
|
|||
[1.235, 1.0, 1.0]
|
||||
[1.235, 1.0, 1.0, 1.235e99, 1.235e-99, 1.235e-12]
|
|
@ -10,23 +10,13 @@ is_test() {
|
|||
}
|
||||
|
||||
run_test() {
|
||||
(
|
||||
if [ -f $test_path/env ]; then
|
||||
. $test_path/env
|
||||
fi
|
||||
$json_process --env <$test_path/input >$test_log/stdout 2>$test_log/stderr
|
||||
)
|
||||
$json_process $test_path >$test_log/stdout 2>$test_log/stderr || return 1
|
||||
valgrind_check $test_log/stderr || return 1
|
||||
cmp -s $test_path/output $test_log/stdout
|
||||
}
|
||||
|
||||
show_error() {
|
||||
valgrind_show_error && return
|
||||
|
||||
echo "EXPECTED OUTPUT:"
|
||||
nl -bn $test_path/output
|
||||
echo "ACTUAL OUTPUT:"
|
||||
nl -bn $test_log/stdout
|
||||
cat $test_log/stderr
|
||||
}
|
||||
|
||||
. $top_srcdir/test/scripts/run-tests.sh
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
JSON_SORT_KEYS=1
|
||||
export JSON_SORT_KEYS
|
||||
|
|
|
@ -10,18 +10,13 @@ is_test() {
|
|||
}
|
||||
|
||||
run_test() {
|
||||
$json_process --env <$test_path/input >$test_log/stdout 2>$test_log/stderr
|
||||
valgrind_check $test_log/stderr || return 1
|
||||
cmp -s $test_path/error $test_log/stderr
|
||||
$json_process $test_path >$test_log/stdout 2>$test_log/stderr || return 1
|
||||
valgrind_check $test_log/stderr$s || return 1
|
||||
}
|
||||
|
||||
show_error() {
|
||||
valgrind_show_error && return
|
||||
|
||||
echo "EXPECTED ERROR:"
|
||||
nl -bn $test_path/error
|
||||
echo "ACTUAL ERROR:"
|
||||
nl -bn $test_log/stderr
|
||||
cat $test_log/stderr
|
||||
}
|
||||
|
||||
. $top_srcdir/test/scripts/run-tests.sh
|
||||
|
|
|
@ -13,24 +13,18 @@ do_run() {
|
|||
variant=$1
|
||||
s=".$1"
|
||||
|
||||
strip=0
|
||||
strip=""
|
||||
if [ "$variant" = "strip" ]; then
|
||||
# This test should not be stripped
|
||||
[ -f $test_path/nostrip ] && return
|
||||
strip=1
|
||||
strip="--strip"
|
||||
fi
|
||||
|
||||
STRIP=$strip $json_process --env \
|
||||
<$test_path/input >$test_log/stdout$s 2>$test_log/stderr$s
|
||||
valgrind_check $test_log/stderr$s || return 1
|
||||
|
||||
ref=error
|
||||
[ -f $test_path/error$s ] && ref=error$s
|
||||
|
||||
if ! cmp -s $test_path/$ref $test_log/stderr$s; then
|
||||
echo $variant > $test_log/variant
|
||||
if ! $json_process $strip $test_path >$test_log/stdout$s 2>$test_log/stderr$s; then
|
||||
echo $variant >$test_log/variant
|
||||
return 1
|
||||
fi
|
||||
valgrind_check $test_log/stderr$s || return 1
|
||||
}
|
||||
|
||||
run_test() {
|
||||
|
@ -44,14 +38,7 @@ show_error() {
|
|||
s=".$variant"
|
||||
|
||||
echo "VARIANT: $variant"
|
||||
|
||||
echo "EXPECTED ERROR:"
|
||||
ref=error
|
||||
[ -f $test_path/error$s ] && ref=error$s
|
||||
nl -bn $test_path/$ref
|
||||
|
||||
echo "ACTUAL ERROR:"
|
||||
nl -bn $test_log/stderr$s
|
||||
cat $test_log/stderr$s
|
||||
}
|
||||
|
||||
. $top_srcdir/test/scripts/run-tests.sh
|
||||
|
|
1
test/suites/valid/real-exponent-no-dtoa/input
Normal file
1
test/suites/valid/real-exponent-no-dtoa/input
Normal file
|
@ -0,0 +1 @@
|
|||
[1.23e47, 0.1, 0.3, 9.99]
|
1
test/suites/valid/real-exponent-no-dtoa/output
Normal file
1
test/suites/valid/real-exponent-no-dtoa/output
Normal file
|
@ -0,0 +1 @@
|
|||
[1.2299999999999999e47, 0.10000000000000001, 0.29999999999999999, 9.9900000000000002]
|
0
test/suites/valid/real-exponent-no-dtoa/skip_if_dtoa
Normal file
0
test/suites/valid/real-exponent-no-dtoa/skip_if_dtoa
Normal file
|
@ -1 +1 @@
|
|||
[123e45]
|
||||
[1.23e47, 0.1, 0.3, 9.99]
|
||||
|
|
|
@ -1 +1 @@
|
|||
[1.2299999999999999e47]
|
||||
[1.23e47, 0.1, 0.3, 9.99]
|
0
test/suites/valid/real-exponent/skip_unless_dtoa
Normal file
0
test/suites/valid/real-exponent/skip_unless_dtoa
Normal file
|
@ -5,31 +5,33 @@
|
|||
# Jansson is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the MIT license. See LICENSE for details.
|
||||
|
||||
JSON_SORT_KEYS=1
|
||||
export JSON_SORT_KEYS
|
||||
dtoa_enabled() {
|
||||
grep -q "DTOA_ENABLED 1" $top_builddir/jansson_private_config.h
|
||||
}
|
||||
|
||||
is_test() {
|
||||
test -d $test_path
|
||||
}
|
||||
|
||||
do_run() {
|
||||
if [ -f $test_path/skip_unless_dtoa ]; then
|
||||
dtoa_enabled || return 77
|
||||
fi
|
||||
if [ -f $test_path/skip_if_dtoa ]; then
|
||||
dtoa_enabled && return 77
|
||||
fi
|
||||
|
||||
variant=$1
|
||||
s=".$1"
|
||||
|
||||
strip=0
|
||||
[ "$variant" = "strip" ] && strip=1
|
||||
strip=""
|
||||
[ "$variant" = "strip" ] && strip="--strip"
|
||||
|
||||
STRIP=$strip $json_process --env \
|
||||
<$test_path/input >$test_log/stdout$s 2>$test_log/stderr$s
|
||||
valgrind_check $test_log/stderr$s || return 1
|
||||
|
||||
ref=output
|
||||
[ -f $test_path/output$s ] && ref=output$s
|
||||
|
||||
if ! cmp -s $test_path/$ref $test_log/stdout$s; then
|
||||
echo $variant > $test_log/variant
|
||||
if ! $json_process $strip $test_path >$test_log/stdout$s 2>$test_log/stderr$s; then
|
||||
echo $variant >$test_log/variant
|
||||
return 1
|
||||
fi
|
||||
valgrind_check $test_log/stderr$s || return 1
|
||||
}
|
||||
|
||||
run_test() {
|
||||
|
@ -43,14 +45,7 @@ show_error() {
|
|||
s=".$variant"
|
||||
|
||||
echo "VARIANT: $variant"
|
||||
|
||||
echo "EXPECTED OUTPUT:"
|
||||
ref=output
|
||||
[ -f $test_path/output$s ] && ref=output$s
|
||||
nl -bn $test_path/$ref
|
||||
|
||||
echo "ACTUAL OUTPUT:"
|
||||
nl -bn $test_log/stdout$s
|
||||
cat $test_log/stderr$s
|
||||
}
|
||||
|
||||
. $top_srcdir/test/scripts/run-tests.sh
|
||||
|
|
Loading…
Add table
Reference in a new issue