Unverified Commit 8c205711 authored by Niels Lohmann's avatar Niels Lohmann

Merge branch 'release/3.2.0'

parents 183390c1 9f3857ef
**Bug Report** ---
name: Bug report
- What is the issue you have? about: Create a report to help us improve
- Please describe the steps to reproduce the issue. Can you provide a small but working code example? ---
- What is the expected behavior? - What is the issue you have?
- And what is the actual behavior instead? - Please describe the steps to reproduce the issue. Can you provide a small but working code example?
- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)? - What is the expected behavior?
- Did you use a released version of the library or the version from the `develop` branch? - And what is the actual behavior instead?
- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)? - Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
- Did you use a released version of the library or the version from the `develop` branch?
**Feature Request**
- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?
- Describe the feature in as much detail as possible.
- Include sample usage where appropriate.
---
name: Feature request
about: Suggest an idea for this project
---
- Describe the feature in as much detail as possible.
- Include sample usage where appropriate.
...@@ -155,6 +155,12 @@ matrix: ...@@ -155,6 +155,12 @@ matrix:
- os: osx - os: osx
osx_image: xcode9.2 osx_image: xcode9.2
- os: osx
osx_image: xcode9.3
- os: osx
osx_image: xcode9.4
# Linux / GCC # Linux / GCC
- os: linux - os: linux
...@@ -189,15 +195,23 @@ matrix: ...@@ -189,15 +195,23 @@ matrix:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build'] packages: ['g++-7', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'ninja-build']
- os: linux - os: linux
compiler: gcc compiler: gcc
env: env:
- COMPILER=g++-7 - COMPILER=g++-8
- CXXFLAGS=-std=c++17 - CXXFLAGS=-std=c++17
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build'] packages: ['g++-8', 'ninja-build']
# Linux / Clang # Linux / Clang
...@@ -257,15 +271,23 @@ matrix: ...@@ -257,15 +271,23 @@ matrix:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0'] sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build'] packages: ['g++-6', 'clang-5.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-6.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
- os: linux - os: linux
compiler: clang compiler: clang
env: env:
- COMPILER=clang++-5.0 - COMPILER=clang++-6.0
- CXXFLAGS=-std=c++1z - CXXFLAGS=-std=c++1z
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0'] sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build'] packages: ['g++-6', 'clang-6.0', 'ninja-build']
################ ################
# build script # # build script #
...@@ -277,6 +299,7 @@ script: ...@@ -277,6 +299,7 @@ script:
if [[ (-x $(which brew)) ]]; then if [[ (-x $(which brew)) ]]; then
brew update brew update
brew install cmake ninja brew install cmake ninja
brew upgrade cmake
cmake --version cmake --version
fi fi
......
cmake_minimum_required(VERSION 3.0.0) cmake_minimum_required(VERSION 3.8)
## ##
## PROJECT ## PROJECT
## name and version ## name and version
## ##
project(nlohmann_json VERSION 3.1.2 LANGUAGES CXX) project(nlohmann_json VERSION 3.2.0 LANGUAGES CXX)
## ##
## INCLUDE ## INCLUDE
...@@ -22,13 +22,15 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) ...@@ -22,13 +22,15 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
## CONFIGURATION ## CONFIGURATION
## ##
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME}) set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}"
CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include") set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in") set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake_config") set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake") set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake") set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
if (JSON_MultipleHeaders) if (JSON_MultipleHeaders)
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/") set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
...@@ -43,6 +45,8 @@ endif() ...@@ -43,6 +45,8 @@ endif()
## create target and add include path ## create target and add include path
## ##
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE) add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
target_include_directories( target_include_directories(
${NLOHMANN_JSON_TARGET_NAME} ${NLOHMANN_JSON_TARGET_NAME}
...@@ -51,8 +55,8 @@ target_include_directories( ...@@ -51,8 +55,8 @@ target_include_directories(
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
## add debug view defintion file for msvc (natvis) [cmake <= 3.2.2 does not support export of source files] ## add debug view definition file for msvc (natvis)
if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2") if (MSVC)
set(NLOHMANN_ADD_NATVIS TRUE) set(NLOHMANN_ADD_NATVIS TRUE)
set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis") set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis")
target_sources( target_sources(
...@@ -62,7 +66,7 @@ if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2") ...@@ -62,7 +66,7 @@ if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2")
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}>
) )
endif() endif()
## ##
## TESTS ## TESTS
## create and configure the unit test target ## create and configure the unit test target
...@@ -102,6 +106,11 @@ if (NLOHMANN_ADD_NATVIS) ...@@ -102,6 +106,11 @@ if (NLOHMANN_ADD_NATVIS)
DESTINATION . DESTINATION .
) )
endif() endif()
export(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
)
install( install(
TARGETS ${NLOHMANN_JSON_TARGET_NAME} TARGETS ${NLOHMANN_JSON_TARGET_NAME}
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME} EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
...@@ -109,5 +118,6 @@ install( ...@@ -109,5 +118,6 @@ install(
) )
install( install(
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME} EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR} DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
) )
This diff is collapsed.
...@@ -9,6 +9,7 @@ SRCS = include/nlohmann/json.hpp \ ...@@ -9,6 +9,7 @@ SRCS = include/nlohmann/json.hpp \
include/nlohmann/detail/exceptions.hpp \ include/nlohmann/detail/exceptions.hpp \
include/nlohmann/detail/input/binary_reader.hpp \ include/nlohmann/detail/input/binary_reader.hpp \
include/nlohmann/detail/input/input_adapters.hpp \ include/nlohmann/detail/input/input_adapters.hpp \
include/nlohmann/detail/input/json_sax.hpp \
include/nlohmann/detail/input/lexer.hpp \ include/nlohmann/detail/input/lexer.hpp \
include/nlohmann/detail/input/parser.hpp \ include/nlohmann/detail/input/parser.hpp \
include/nlohmann/detail/iterators/internal_iterator.hpp \ include/nlohmann/detail/iterators/internal_iterator.hpp \
...@@ -20,7 +21,10 @@ SRCS = include/nlohmann/json.hpp \ ...@@ -20,7 +21,10 @@ SRCS = include/nlohmann/json.hpp \
include/nlohmann/detail/json_ref.hpp \ include/nlohmann/detail/json_ref.hpp \
include/nlohmann/detail/macro_scope.hpp \ include/nlohmann/detail/macro_scope.hpp \
include/nlohmann/detail/macro_unscope.hpp \ include/nlohmann/detail/macro_unscope.hpp \
include/nlohmann/detail/meta.hpp \ include/nlohmann/detail/meta/cpp_future.hpp \
include/nlohmann/detail/meta/detected.hpp \
include/nlohmann/detail/meta/type_traits.hpp \
include/nlohmann/detail/meta/void_t.hpp \
include/nlohmann/detail/output/binary_writer.hpp \ include/nlohmann/detail/output/binary_writer.hpp \
include/nlohmann/detail/output/output_adapters.hpp \ include/nlohmann/detail/output/output_adapters.hpp \
include/nlohmann/detail/output/serializer.hpp \ include/nlohmann/detail/output/serializer.hpp \
...@@ -82,9 +86,9 @@ clean: ...@@ -82,9 +86,9 @@ clean:
coverage: coverage:
mkdir build_coverage mkdir build_coverage
cd build_coverage ; CXX=g++-5 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON cd build_coverage ; CXX=g++-7 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; ninja cd build_coverage ; ninja
cd build_coverage ; ctest -j10 cd build_coverage ; ctest -E '.*_default' -j10
cd build_coverage ; ninja lcov_html cd build_coverage ; ninja lcov_html
open build_coverage/test/html/index.html open build_coverage/test/html/index.html
......
This diff is collapsed.
version: '{build}' version: '{build}'
os:
- Visual Studio 2015
- Visual Studio 2017
environment: environment:
matrix: matrix:
- additional_flags: "" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
- additional_flags: "/permissive- /std:c++latest /utf-8" COMPILER: mingw
platform: x86
FLAGS: ""
GENERATOR: Ninja
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
init:
- cmake --version
- msbuild /version
matrix: install:
exclude: - if "%COMPILER%"=="mingw" appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
- additional_flags: "/permissive- /std:c++latest /utf-8" - if "%COMPILER%"=="mingw" 7z x ninja.zip -oC:\projects\deps\ninja > nul
os: Visual Studio 2015 - if "%COMPILER%"=="mingw" set PATH=C:\projects\deps\ninja;%PATH%
- if "%COMPILER%"=="mingw" set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
init: [] - if "%COMPILER%"=="mingw" g++ --version
install: [] before_build:
- cmake . -G "%GENERATOR%" -DCMAKE_CXX_FLAGS="%FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin"
build_script: build_script:
- IF "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" ( SET GEN="Visual Studio 14 2015") ELSE (SET GEN="Visual Studio 15 2017")
- cmake . -G%GEN% -DCMAKE_CXX_FLAGS="%additional_flags%"
- cmake --build . --config Release - cmake --build . --config Release
test_script: test_script:
......
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.8)
project(JSON_Benchmarks LANGUAGES CXX) project(JSON_Benchmarks LANGUAGES CXX)
# set compiler flags # set compiler flags
if((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang)) if((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -flto -DNDEBUG -O3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -DNDEBUG -O3")
endif() endif()
# configure Google Benchmarks # configure Google Benchmarks
...@@ -23,4 +23,5 @@ file(COPY ${CMAKE_SOURCE_DIR}/../test/data/regression/floats.json ...@@ -23,4 +23,5 @@ file(COPY ${CMAKE_SOURCE_DIR}/../test/data/regression/floats.json
# benchmark binary # benchmark binary
add_executable(json_benchmarks src/benchmarks.cpp) add_executable(json_benchmarks src/benchmarks.cpp)
target_compile_features(json_benchmarks PRIVATE cxx_std_11)
target_link_libraries(json_benchmarks benchmark ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(json_benchmarks benchmark ${CMAKE_THREAD_LIBS_INIT})
@PACKAGE_INIT@ @PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake") if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
endif()
check_required_components("@PROJECT_NAME@") check_required_components("@PROJECT_NAME@")
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "JSON for Modern C++" PROJECT_NAME = "JSON for Modern C++"
PROJECT_NUMBER = 3.1.2 PROJECT_NUMBER = 3.2.0
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = PROJECT_LOGO =
OUTPUT_DIRECTORY = . OUTPUT_DIRECTORY = .
......
doc/avatars.png

568 KB | W: | H:

doc/avatars.png

682 KB | W: | H:

doc/avatars.png
doc/avatars.png
doc/avatars.png
doc/avatars.png
  • 2-up
  • Swipe
  • Onion skin
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/TarF5pPn9NtHQjhf"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/VexEaSCbbvOOXsPt"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/tfI8DuCuZs3VB9VF"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/3OPLSVPyweUyEHaX"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/E1HQedkl1zo48WW5"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/4bn447WQbTERfBaL"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/mya8dUDcDDVoUlBZ"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/AHKW5EMQN4YQ68TY"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/sMmEKxW5MGOgLC7z"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/J0KoQF8sOpdMg4kN"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/qq29jfETq7nZRrh5"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/uuQK0DAjhbSd96K6"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/0zdmfNQCe4TMw0iI"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/eFzRNyod3g4aVkvl"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"compiler": { "compiler": {
"c++": "201103", "c++": "201103",
"family": "clang", "family": "clang",
"version": "9.0.0 (clang-900.0.39.2)" "version": "9.1.0 (clang-902.0.39.2)"
}, },
"copyright": "(C) 2013-2017 Niels Lohmann", "copyright": "(C) 2013-2017 Niels Lohmann",
"name": "JSON for Modern C++", "name": "JSON for Modern C++",
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
"url": "https://github.com/nlohmann/json", "url": "https://github.com/nlohmann/json",
"version": { "version": {
"major": 3, "major": 3,
"minor": 1, "minor": 2,
"patch": 2, "patch": 0,
"string": "3.1.2" "string": "3.2.0"
} }
} }
...@@ -17,8 +17,8 @@ int main() ...@@ -17,8 +17,8 @@ int main()
// output values and comparisons // output values and comparisons
std::cout << std::boolalpha; std::cout << std::boolalpha;
std::cout << array_1 << " == " << array_2 << " " << (array_1 > array_2) << '\n'; std::cout << array_1 << " > " << array_2 << " " << (array_1 > array_2) << '\n';
std::cout << object_1 << " == " << object_2 << " " << (object_1 > object_2) << '\n'; std::cout << object_1 << " > " << object_2 << " " << (object_1 > object_2) << '\n';
std::cout << number_1 << " == " << number_2 << " " << (number_1 > number_2) << '\n'; std::cout << number_1 << " > " << number_2 << " " << (number_1 > number_2) << '\n';
std::cout << string_1 << " == " << string_2 << " " << (string_1 > string_2) << '\n'; std::cout << string_1 << " > " << string_2 << " " << (string_1 > string_2) << '\n';
} }
<a target="_blank" href="https://wandbox.org/permlink/yiz7oCHVpFHSALB1"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/ntF7DMzC85gbQKHu"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
[1,2,3] == [1,2,4] false [1,2,3] > [1,2,4] false
{"A":"a","B":"b"} == {"A":"a","B":"b"} false {"A":"a","B":"b"} > {"A":"a","B":"b"} false
17 == 17.0000000000001 false 17 > 17.0000000000001 false
"foo" == "bar" true "foo" > "bar" true
#include <iostream> #include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/YrUqrUFMD7JHwSQR"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/IvgowYGaX0SgOFIG"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/wXcm4ObnoaXw7CRt"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/ckGZIBookDffV00n"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/vxt8d8qvYorXS2yq"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/oKnfnFrLHG8H1OAl"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/TSNxHmegVwLW2pXf"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/i3BBhl7Ub5y9b0yp"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/l3zNo3YKC2X8yAw9"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/sGdJMOaJnFNJBtH7"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/Mf7A6JtvqT1Na7Pk"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/UZgRBIeqdZhm6M8F"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/oa6BVkBXjG8DNkzX"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/VThe0hdMSUdNSOLK"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/QXdl4yzts3qPeZ0U"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/QZgjsR0PiAw2Lqpk"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/8ObNa6ejw4BXQ5qG"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/hFd1W46W2Hb81sHN"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// a simple event consumer that collects string representations of the passed
// values; not inheriting from json::json_sax_t is not required, but can
// help not to forget a required function
class sax_event_consumer : public json::json_sax_t
{
public:
std::vector<std::string> events;
bool null() override
{
events.push_back("value: null");
return true;
}
bool boolean(bool val) override
{
events.push_back("value: " + std::string(val ? "true" : "false"));
return true;
}
bool number_integer(number_integer_t val) override
{
events.push_back("value: " + std::to_string(val));
return true;
}
bool number_unsigned(number_unsigned_t val) override
{
events.push_back("value: " + std::to_string(val));
return true;
}
bool number_float(number_float_t val, const string_t& s) override
{
events.push_back("value: " + s);
return true;
}
bool string(string_t& val) override
{
events.push_back("value: " + val);
return true;
}
bool start_object(std::size_t elements) override
{
events.push_back("start: object");
return true;
}
bool end_object() override
{
events.push_back("end: object");
return true;
}
bool start_array(std::size_t elements) override
{
events.push_back("start: array");
return true;
}
bool end_array() override
{
events.push_back("end: array");
return true;
}
bool key(string_t& val) override
{
events.push_back("key: " + val);
return true;
}
bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override
{
events.push_back("error: " + std::string(ex.what()));
return false;
}
};
int main()
{
// a JSON text
auto text = R"(
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"Animated" : false,
"IDs": [116, 943, 234, 38793],
"Distance": 12.723374634
}
}
)";
// create a SAX event consumer object
sax_event_consumer sec;
// parse and serialize JSON
bool result = json::sax_parse(text, &sec);
// output the recorded events
for (auto& event : sec.events)
{
std::cout << "(" << event << ") ";
}
// output the result of sax_parse
std::cout << "\nresult: " << std::boolalpha << result << std::endl;
}
<a target="_blank" href="https://wandbox.org/permlink/fGkQLWbQn7enKkIG"><b>online</b></a>
\ No newline at end of file
(start: object) (key: Image) (start: object) (key: Width) (value: 800) (key: Height) (value: 600) (key: Title) (value: View from 15th Floor) (key: Thumbnail) (start: object) (key: Url) (value: http://www.example.com/image/481989943) (key: Height) (value: 125) (key: Width) (value: 100) (end: object) (key: Animated) (value: false) (key: IDs) (start: array) (value: 116) (value: 943) (value: 234) (value: 38793) (end: array) (key: Distance) (value: 12.723374634) (end: object) (end: object)
result: true
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/4bQSclXeqjVFYVL3"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/LRM37xarSuPJmv92"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/WvT2Q0r9vlJYyMM8"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/CaRFhkrefL4miesE"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/j3HE6cOkCmKbxxAt"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/2luqHy9iADx4UNm7"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/U45AGi5nsDtoDf3u"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/knK4jnD2hIVxQoyk"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/TGvdYyJtstacZxWq"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/kjcoWACW7FMqKRBG"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
#include <iostream> #include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
......
<a target="_blank" href="https://wandbox.org/permlink/BMlas6312rkE4cxz"><b>online</b></a> <a target="_blank" href="https://wandbox.org/permlink/0LBIsEa18IrerWwy"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -39,9 +39,11 @@ These pages contain the API documentation of JSON for Modern C++, a C++11 header ...@@ -39,9 +39,11 @@ These pages contain the API documentation of JSON for Modern C++, a C++11 header
- @link nlohmann::basic_json::dump dump @endlink serialize to string - @link nlohmann::basic_json::dump dump @endlink serialize to string
- @link nlohmann::basic_json::operator<<(std::ostream&, const basic_json &) operator<< @endlink serialize to stream - @link nlohmann::basic_json::operator<<(std::ostream&, const basic_json &) operator<< @endlink serialize to stream
- deserialization / parsing - deserialization / parsing
- @link nlohmann::basic_json::parse parse @endlink parse from string - @link nlohmann::basic_json::parse parse @endlink parse from input (string, file, etc.) and return JSON value
- @link nlohmann::basic_json::sax_parse sax_parse @endlink parse from input (string, file, etc.) and generate SAX events
- @link nlohmann::basic_json::operator>>(std::istream&, basic_json&) operator>> @endlink parse from stream - @link nlohmann::basic_json::operator>>(std::istream&, basic_json&) operator>> @endlink parse from stream
- @link nlohmann::basic_json::accept accept @endlink check for syntax errors without parsing - @link nlohmann::basic_json::accept accept @endlink check for syntax errors without parsing
- @link nlohmann::json_sax SAX interface @endlink define a user-defined SAX event consumer
- [binary formats](binary_formats.md): - [binary formats](binary_formats.md):
- CBOR: @link nlohmann::basic_json::from_cbor from_cbor @endlink / @link nlohmann::basic_json::to_cbor to_cbor @endlink - CBOR: @link nlohmann::basic_json::from_cbor from_cbor @endlink / @link nlohmann::basic_json::to_cbor to_cbor @endlink
- MessagePack: @link nlohmann::basic_json::from_msgpack from_msgpack @endlink / @link nlohmann::basic_json::to_msgpack to_msgpack @endlink - MessagePack: @link nlohmann::basic_json::from_msgpack from_msgpack @endlink / @link nlohmann::basic_json::to_msgpack to_msgpack @endlink
...@@ -304,4 +306,4 @@ Note that this table only lists those exceptions thrown due to the type. For ins ...@@ -304,4 +306,4 @@ Note that this table only lists those exceptions thrown due to the type. For ins
@author [Niels Lohmann](http://nlohmann.me) @author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code @see https://github.com/nlohmann/json to download the source code
@version 3.1.2 @version 3.2.0
doc/json.gif

1.47 MB | W: | H:

doc/json.gif

1.56 MB | W: | H:

doc/json.gif
doc/json.gif
doc/json.gif
doc/json.gif
  • 2-up
  • Swipe
  • Onion skin
...@@ -5,21 +5,34 @@ ...@@ -5,21 +5,34 @@
#include <ciso646> // and, not #include <ciso646> // and, not
#include <forward_list> // forward_list #include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end #include <iterator> // inserter, front_inserter, end
#include <map> // map
#include <string> // string #include <string> // string
#include <tuple> // tuple, make_tuple #include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
#include <unordered_map> // unordered_map
#include <utility> // pair, declval #include <utility> // pair, declval
#include <valarray> // valarray #include <valarray> // valarray
#include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
namespace nlohmann namespace nlohmann
{ {
namespace detail namespace detail
{ {
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_UNLIKELY(not j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
}
n = nullptr;
}
// overloads for basic_json template parameters // overloads for basic_json template parameters
template<typename BasicJsonType, typename ArithmeticType, template<typename BasicJsonType, typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value and enable_if_t<std::is_arithmetic<ArithmeticType>::value and
...@@ -70,6 +83,23 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) ...@@ -70,6 +83,23 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
} }
template <
typename BasicJsonType, typename CompatibleStringType,
enable_if_t <
is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
not std::is_same<typename BasicJsonType::string_t,
CompatibleStringType>::value,
int > = 0 >
void from_json(const BasicJsonType& j, CompatibleStringType& s)
{
if (JSON_UNLIKELY(not j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template<typename BasicJsonType> template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{ {
...@@ -277,6 +307,44 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t) ...@@ -277,6 +307,44 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
from_json_tuple_impl(j, t, index_sequence_for<Args...> {}); from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
} }
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t<not std::is_constructible<
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
for (const auto& p : j)
{
if (JSON_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
typename = enable_if_t<not std::is_constructible<
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
for (const auto& p : j)
{
if (JSON_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
struct from_json_fn struct from_json_fn
{ {
private: private:
......
...@@ -887,7 +887,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) ...@@ -887,7 +887,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
// decimal representations are not exactly "short". // decimal representations are not exactly "short".
// //
// The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars) // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
// says "value is converted to a string as if by std::sprintf in the default ("C") locale" // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
// does. // does.
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#include <valarray> // valarray #include <valarray> // valarray
#include <vector> // vector #include <vector> // vector
#include <nlohmann/detail/meta.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
namespace nlohmann namespace nlohmann
{ {
...@@ -51,6 +53,16 @@ struct external_constructor<value_t::string> ...@@ -51,6 +53,16 @@ struct external_constructor<value_t::string>
j.m_value = std::move(s); j.m_value = std::move(s);
j.assert_invariant(); j.assert_invariant();
} }
template<typename BasicJsonType, typename CompatibleStringType,
enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
int> = 0>
static void construct(BasicJsonType& j, const CompatibleStringType& str)
{
j.m_type = value_t::string;
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
j.assert_invariant();
}
}; };
template<> template<>
...@@ -247,7 +259,7 @@ void to_json(BasicJsonType& j, const CompatibleArrayType& arr) ...@@ -247,7 +259,7 @@ void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
template<typename BasicJsonType, typename T, template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
void to_json(BasicJsonType& j, std::valarray<T> arr) void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{ {
external_constructor<value_t::array>::construct(j, std::move(arr)); external_constructor<value_t::array>::construct(j, std::move(arr));
} }
...@@ -284,6 +296,14 @@ void to_json(BasicJsonType& j, const std::pair<Args...>& p) ...@@ -284,6 +296,14 @@ void to_json(BasicJsonType& j, const std::pair<Args...>& p)
j = {p.first, p.second}; j = {p.first, p.second};
} }
// for https://github.com/nlohmann/json/pull/1134
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
void to_json(BasicJsonType& j, T b) noexcept
{
j = {{b.key(), b.value()}};
}
template<typename BasicJsonType, typename Tuple, std::size_t... Idx> template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>) void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
{ {
......
#pragma once #pragma once
#include <algorithm> // min
#include <array> // array
#include <cassert> // assert #include <cassert> // assert
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstring> // strlen #include <cstring> // strlen
#include <ios> // streamsize, streamoff, streampos
#include <istream> // istream #include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof #include <memory> // shared_ptr, make_shared, addressof
...@@ -20,6 +17,9 @@ namespace nlohmann ...@@ -20,6 +17,9 @@ namespace nlohmann
{ {
namespace detail namespace detail
{ {
/// the supported input formats
enum class input_format_t { json, cbor, msgpack, ubjson };
//////////////////// ////////////////////
// input adapters // // input adapters //
//////////////////// ////////////////////
...@@ -28,19 +28,17 @@ namespace detail ...@@ -28,19 +28,17 @@ namespace detail
@brief abstract input adapter interface @brief abstract input adapter interface
Produces a stream of std::char_traits<char>::int_type characters from a Produces a stream of std::char_traits<char>::int_type characters from a
std::istream, a buffer, or some other input type. Accepts the return of exactly std::istream, a buffer, or some other input type. Accepts the return of
one non-EOF character for future input. The int_type characters returned exactly one non-EOF character for future input. The int_type characters
consist of all valid char values as positive values (typically unsigned char), returned consist of all valid char values as positive values (typically
plus an EOF value outside that range, specified by the value of the function unsigned char), plus an EOF value outside that range, specified by the value
std::char_traits<char>::eof(). This value is typically -1, but could be any of the function std::char_traits<char>::eof(). This value is typically -1, but
arbitrary value which is not a valid char value. could be any arbitrary value which is not a valid char value.
*/ */
struct input_adapter_protocol struct input_adapter_protocol
{ {
/// get a character [0,255] or std::char_traits<char>::eof(). /// get a character [0,255] or std::char_traits<char>::eof().
virtual std::char_traits<char>::int_type get_character() = 0; virtual std::char_traits<char>::int_type get_character() = 0;
/// restore the last non-eof() character to input
virtual void unget_character() = 0;
virtual ~input_adapter_protocol() = default; virtual ~input_adapter_protocol() = default;
}; };
...@@ -68,34 +66,7 @@ class input_stream_adapter : public input_adapter_protocol ...@@ -68,34 +66,7 @@ class input_stream_adapter : public input_adapter_protocol
explicit input_stream_adapter(std::istream& i) explicit input_stream_adapter(std::istream& i)
: is(i), sb(*i.rdbuf()) : is(i), sb(*i.rdbuf())
{ {}
// skip byte order mark
std::char_traits<char>::int_type c;
if ((c = get_character()) == 0xEF)
{
if ((c = get_character()) == 0xBB)
{
if ((c = get_character()) == 0xBF)
{
return; // Ignore BOM
}
else if (c != std::char_traits<char>::eof())
{
is.unget();
}
is.putback('\xBB');
}
else if (c != std::char_traits<char>::eof())
{
is.unget();
}
is.putback('\xEF');
}
else if (c != std::char_traits<char>::eof())
{
is.unget(); // no byte order mark; process as usual
}
}
// delete because of pointer members // delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete; input_stream_adapter(const input_stream_adapter&) = delete;
...@@ -109,11 +80,6 @@ class input_stream_adapter : public input_adapter_protocol ...@@ -109,11 +80,6 @@ class input_stream_adapter : public input_adapter_protocol
return sb.sbumpc(); return sb.sbumpc();
} }
void unget_character() override
{
sb.sungetc(); // is.unget() avoided for performance
}
private: private:
/// the associated input stream /// the associated input stream
std::istream& is; std::istream& is;
...@@ -125,14 +91,8 @@ class input_buffer_adapter : public input_adapter_protocol ...@@ -125,14 +91,8 @@ class input_buffer_adapter : public input_adapter_protocol
{ {
public: public:
input_buffer_adapter(const char* b, const std::size_t l) input_buffer_adapter(const char* b, const std::size_t l)
: cursor(b), limit(b + l), start(b) : cursor(b), limit(b + l)
{ {}
// skip byte order mark
if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
{
cursor += 3;
}
}
// delete because of pointer members // delete because of pointer members
input_buffer_adapter(const input_buffer_adapter&) = delete; input_buffer_adapter(const input_buffer_adapter&) = delete;
...@@ -148,21 +108,164 @@ class input_buffer_adapter : public input_adapter_protocol ...@@ -148,21 +108,164 @@ class input_buffer_adapter : public input_adapter_protocol
return std::char_traits<char>::eof(); return std::char_traits<char>::eof();
} }
void unget_character() noexcept override private:
/// pointer to the current character
const char* cursor;
/// pointer past the last character
const char* const limit;
};
template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol
{
public:
explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
std::char_traits<char>::int_type get_character() noexcept override
{ {
if (JSON_LIKELY(cursor > start)) // check if buffer needs to be filled
if (utf8_bytes_index == utf8_bytes_filled)
{ {
--cursor; if (sizeof(typename WideStringType::value_type) == 2)
{
fill_buffer_utf16();
}
else
{
fill_buffer_utf32();
}
assert(utf8_bytes_filled > 0);
assert(utf8_bytes_index == 0);
} }
// use buffer
assert(utf8_bytes_filled > 0);
assert(utf8_bytes_index < utf8_bytes_filled);
return utf8_bytes[utf8_bytes_index++];
} }
private: private:
/// pointer to the current character void fill_buffer_utf16()
const char* cursor; {
/// pointer past the last character utf8_bytes_index = 0;
const char* limit;
/// pointer to the first character if (current_wchar == str.size())
const char* start; {
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const int wc = static_cast<int>(str[current_wchar++]);
// UTF-16 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6));
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 2;
}
else if (0xD800 > wc or wc >= 0xE000)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12));
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 3;
}
else
{
if (current_wchar < str.size())
{
const int wc2 = static_cast<int>(str[current_wchar++]);
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
utf8_bytes[0] = 0xf0 | (charcode >> 18);
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
utf8_bytes_filled = 4;
}
else
{
// unknown character
++current_wchar;
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
}
}
}
void fill_buffer_utf32()
{
utf8_bytes_index = 0;
if (current_wchar == str.size())
{
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const int wc = static_cast<int>(str[current_wchar++]);
// UTF-32 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 2;
}
else if (wc <= 0xFFFF)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 3;
}
else if (wc <= 0x10FFFF)
{
utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 4;
}
else
{
// unknown character
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
}
}
private:
/// the wstring to process
const WideStringType& str;
/// index of the current wchar in str
std::size_t current_wchar = 0;
/// a buffer for UTF-8 bytes
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
/// index to the utf8_codes array for the next valid byte
std::size_t utf8_bytes_index = 0;
/// number of valid bytes in the utf8_codes array
std::size_t utf8_bytes_filled = 0;
}; };
class input_adapter class input_adapter
...@@ -178,6 +281,15 @@ class input_adapter ...@@ -178,6 +281,15 @@ class input_adapter
input_adapter(std::istream&& i) input_adapter(std::istream&& i)
: ia(std::make_shared<input_stream_adapter>(i)) {} : ia(std::make_shared<input_stream_adapter>(i)) {}
input_adapter(const std::wstring& ws)
: ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
input_adapter(const std::u16string& ws)
: ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
input_adapter(const std::u32string& ws)
: ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
/// input adapter for buffer /// input adapter for buffer
template<typename CharT, template<typename CharT,
typename std::enable_if< typename std::enable_if<
......
This diff is collapsed.
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
#include <clocale> // localeconv #include <clocale> // localeconv
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <cstdio> // snprintf
#include <initializer_list> // initializer_list #include <initializer_list> // initializer_list
#include <ios> // hex, uppercase
#include <iomanip> // setw, setfill
#include <sstream> // stringstream
#include <string> // char_traits, string #include <string> // char_traits, string
#include <vector> // vector #include <vector> // vector
...@@ -94,12 +92,14 @@ class lexer ...@@ -94,12 +92,14 @@ class lexer
return "end of input"; return "end of input";
case token_type::literal_or_value: case token_type::literal_or_value:
return "'[', '{', or a literal"; return "'[', '{', or a literal";
// LCOV_EXCL_START
default: // catch non-enum values default: // catch non-enum values
return "unknown token"; // LCOV_EXCL_LINE return "unknown token";
// LCOV_EXCL_STOP
} }
} }
explicit lexer(detail::input_adapter_t adapter) explicit lexer(detail::input_adapter_t&& adapter)
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {} : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
// delete because of pointer members // delete because of pointer members
...@@ -747,11 +747,13 @@ class lexer ...@@ -747,11 +747,13 @@ class lexer
goto scan_number_any1; goto scan_number_any1;
} }
// LCOV_EXCL_START
default: default:
{ {
// all other characters are rejected outside scan_number() // all other characters are rejected outside scan_number()
assert(false); // LCOV_EXCL_LINE assert(false);
} }
// LCOV_EXCL_STOP
} }
scan_number_minus: scan_number_minus:
...@@ -1081,7 +1083,16 @@ scan_number_done: ...@@ -1081,7 +1083,16 @@ scan_number_done:
std::char_traits<char>::int_type get() std::char_traits<char>::int_type get()
{ {
++chars_read; ++chars_read;
current = ia->get_character(); if (next_unget)
{
// just reset the next_unget variable and work with current
next_unget = false;
}
else
{
current = ia->get_character();
}
if (JSON_LIKELY(current != std::char_traits<char>::eof())) if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{ {
token_string.push_back(std::char_traits<char>::to_char_type(current)); token_string.push_back(std::char_traits<char>::to_char_type(current));
...@@ -1089,13 +1100,20 @@ scan_number_done: ...@@ -1089,13 +1100,20 @@ scan_number_done:
return current; return current;
} }
/// unget current character (return it again on next get) /*!
@brief unget current character (read it again on next get)
We implement unget by setting variable next_unget to true. The input is not
changed - we just simulate ungetting by modifying chars_read and
token_string. The next call to get() will behave as if the unget character
is read again.
*/
void unget() void unget()
{ {
next_unget = true;
--chars_read; --chars_read;
if (JSON_LIKELY(current != std::char_traits<char>::eof())) if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{ {
ia->unget_character();
assert(token_string.size() != 0); assert(token_string.size() != 0);
token_string.pop_back(); token_string.pop_back();
} }
...@@ -1131,9 +1149,9 @@ scan_number_done: ...@@ -1131,9 +1149,9 @@ scan_number_done:
} }
/// return current string value (implicitly resets the token; useful only once) /// return current string value (implicitly resets the token; useful only once)
string_t&& move_string() string_t& get_string()
{ {
return std::move(token_buffer); return token_buffer;
} }
///////////////////// /////////////////////
...@@ -1158,10 +1176,9 @@ scan_number_done: ...@@ -1158,10 +1176,9 @@ scan_number_done:
if ('\x00' <= c and c <= '\x1F') if ('\x00' <= c and c <= '\x1F')
{ {
// escape control characters // escape control characters
std::stringstream ss; char cs[9];
ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0') snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
<< std::hex << static_cast<int>(c) << ">"; result += cs;
result += ss.str();
} }
else else
{ {
...@@ -1183,8 +1200,43 @@ scan_number_done: ...@@ -1183,8 +1200,43 @@ scan_number_done:
// actual scanner // actual scanner
///////////////////// /////////////////////
/*!
@brief skip the UTF-8 byte order mark
@return true iff there is no BOM or the correct BOM has been skipped
*/
bool skip_bom()
{
if (get() == 0xEF)
{
if (get() == 0xBB and get() == 0xBF)
{
// we completely parsed the BOM
return true;
}
else
{
// after reading 0xEF, an unexpected character followed
return false;
}
}
else
{
// the first character is not the beginning of the BOM; unget it to
// process is later
unget();
return true;
}
}
token_type scan() token_type scan()
{ {
// initially, skip the BOM
if (chars_read == 0 and not skip_bom())
{
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
return token_type::parse_error;
}
// read next character and ignore whitespace // read next character and ignore whitespace
do do
{ {
...@@ -1254,6 +1306,9 @@ scan_number_done: ...@@ -1254,6 +1306,9 @@ scan_number_done:
/// the current character /// the current character
std::char_traits<char>::int_type current = std::char_traits<char>::eof(); std::char_traits<char>::int_type current = std::char_traits<char>::eof();
/// whether the next get() call should just return current
bool next_unget = false;
/// the number of characters read /// the number of characters read
std::size_t chars_read = 0; std::size_t chars_read = 0;
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <nlohmann/detail/iterators/internal_iterator.hpp> #include <nlohmann/detail/iterators/internal_iterator.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp> #include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
namespace nlohmann namespace nlohmann
...@@ -31,7 +31,7 @@ This class implements a both iterators (iterator and const_iterator) for the ...@@ -31,7 +31,7 @@ This class implements a both iterators (iterator and const_iterator) for the
@requirement The class satisfies the following concept requirements: @requirement The class satisfies the following concept requirements:
- -
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented). incremented and decremented).
...@@ -583,7 +583,7 @@ class iter_impl ...@@ -583,7 +583,7 @@ class iter_impl
@brief return the key of an object iterator @brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
typename object_t::key_type key() const const typename object_t::key_type& key() const
{ {
assert(m_object != nullptr); assert(m_object != nullptr);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <cstddef> // size_t #include <cstddef> // size_t
#include <string> // string, to_string #include <string> // string, to_string
#include <iterator> // input_iterator_tag
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
...@@ -16,15 +17,31 @@ template<typename IteratorType> class iteration_proxy ...@@ -16,15 +17,31 @@ template<typename IteratorType> class iteration_proxy
/// helper class for iteration /// helper class for iteration
class iteration_proxy_internal class iteration_proxy_internal
{ {
public:
using difference_type = std::ptrdiff_t;
using value_type = iteration_proxy_internal;
using pointer = iteration_proxy_internal*;
using reference = iteration_proxy_internal&;
using iterator_category = std::input_iterator_tag;
private: private:
/// the iterator /// the iterator
IteratorType anchor; IteratorType anchor;
/// an index for arrays (used to create key names) /// an index for arrays (used to create key names)
std::size_t array_index = 0; std::size_t array_index = 0;
/// last stringified array index
mutable std::size_t array_index_last = 0;
/// a string representation of the array index
mutable std::string array_index_str = "0";
/// an empty string (to return a reference for primitive values)
const std::string empty_str = "";
public: public:
explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
iteration_proxy_internal(const iteration_proxy_internal&) = default;
iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
/// dereference operator (needed for range-based for) /// dereference operator (needed for range-based for)
iteration_proxy_internal& operator*() iteration_proxy_internal& operator*()
{ {
...@@ -40,6 +57,12 @@ template<typename IteratorType> class iteration_proxy ...@@ -40,6 +57,12 @@ template<typename IteratorType> class iteration_proxy
return *this; return *this;
} }
/// equality operator (needed for InputIterator)
bool operator==(const iteration_proxy_internal& o) const noexcept
{
return anchor == o.anchor;
}
/// inequality operator (needed for range-based for) /// inequality operator (needed for range-based for)
bool operator!=(const iteration_proxy_internal& o) const noexcept bool operator!=(const iteration_proxy_internal& o) const noexcept
{ {
...@@ -47,7 +70,7 @@ template<typename IteratorType> class iteration_proxy ...@@ -47,7 +70,7 @@ template<typename IteratorType> class iteration_proxy
} }
/// return key of the iterator /// return key of the iterator
std::string key() const const std::string& key() const
{ {
assert(anchor.m_object != nullptr); assert(anchor.m_object != nullptr);
...@@ -55,7 +78,14 @@ template<typename IteratorType> class iteration_proxy ...@@ -55,7 +78,14 @@ template<typename IteratorType> class iteration_proxy
{ {
// use integer array index as key // use integer array index as key
case value_t::array: case value_t::array:
return std::to_string(array_index); {
if (array_index != array_index_last)
{
array_index_str = std::to_string(array_index);
array_index_last = array_index;
}
return array_index_str;
}
// use key from the object // use key from the object
case value_t::object: case value_t::object:
...@@ -63,7 +93,7 @@ template<typename IteratorType> class iteration_proxy ...@@ -63,7 +93,7 @@ template<typename IteratorType> class iteration_proxy
// use an empty key for all primitive types // use an empty key for all primitive types
default: default:
return ""; return empty_str;
} }
} }
......
...@@ -21,10 +21,10 @@ create @ref const_reverse_iterator). ...@@ -21,10 +21,10 @@ create @ref const_reverse_iterator).
@requirement The class satisfies the following concept requirements: @requirement The class satisfies the following concept requirements:
- -
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented). incremented and decremented).
- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
It is possible to write to the pointed-to element (only if @a Base is It is possible to write to the pointed-to element (only if @a Base is
@ref iterator). @ref iterator).
...@@ -41,11 +41,11 @@ class json_reverse_iterator : public std::reverse_iterator<Base> ...@@ -41,11 +41,11 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
using reference = typename Base::reference; using reference = typename Base::reference;
/// create reverse iterator from iterator /// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it) {} : base_iterator(it) {}
/// create reverse iterator from base class /// create reverse iterator from base class
json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++) /// post-increment (it++)
json_reverse_iterator const operator++(int) json_reverse_iterator const operator++(int)
......
...@@ -87,7 +87,7 @@ class primitive_iterator_t ...@@ -87,7 +87,7 @@ class primitive_iterator_t
primitive_iterator_t const operator++(int) noexcept primitive_iterator_t const operator++(int) noexcept
{ {
auto result = *this; auto result = *this;
m_it++; ++m_it;
return result; return result;
} }
...@@ -100,7 +100,7 @@ class primitive_iterator_t ...@@ -100,7 +100,7 @@ class primitive_iterator_t
primitive_iterator_t const operator--(int) noexcept primitive_iterator_t const operator--(int) noexcept
{ {
auto result = *this; auto result = *this;
m_it--; --m_it;
return result; return result;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment