Codebase list snapcast / fresh-releases/main
Merge new upstream release 0.23.0. Debian Janitor 3 years ago
87 changed file(s) with 16214 addition(s) and 7182 deletion(s). Raw diff Collapse all Expand all
0 name: macOS
0 name: macOS-x86_64
11
22 on: [push, pull_request]
33
1414 id: cache-boost
1515 uses: actions/cache@v2
1616 with:
17 path: boost_1_74_0
17 path: boost_1_75_0
1818 key: ${{ runner.os }}-boost
1919 - name: get boost
2020 if: steps.cache-boost.outputs.cache-hit != 'true'
21 run: wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2 && tar xjf boost_1_74_0.tar.bz2
21 run: wget https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.bz2 && tar xjf boost_1_75_0.tar.bz2
2222 - name: cache ccache
2323 id: cache-ccache
2424 uses: actions/cache@v2
2929 #- name: ccache dump config
3030 # run: ccache -p
3131 - name: cmake build
32 run: cmake -S . -B build -DBOOST_ROOT=boost_1_74_0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS="$CXXFLAGS -Werror -Wall -Wextra -pedantic -Wno-unused-function -I/usr/local/include"
32 run: cmake -S . -B build -DBOOST_ROOT=boost_1_75_0 -DCMAKE_BUILD_TYPE=Release -DWERROR=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS="-I/usr/local/include"
3333 - name: cmake make
3434 run: cmake --build build --parallel 3
0 name: self-hosted
0 name: Raspbian-armhf
11
22 on: [push, pull_request]
33
1111 run: rm -rf /home/pi/actions-runner/_work/snapcast/snap*_armhf.deb
1212 - uses: actions/checkout@v2
1313 - name: cmake build
14 run: mkdir build && cd build && cmake -DBOOST_ROOT=/home/pi/Develop/boost_1_74_0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS="$CXXFLAGS -Wall -Wextra -pedantic -Wno-unused-function" .. && cd ..
14 run: mkdir build && cd build && cmake -DBOOST_ROOT=/home/pi/Develop/boost_1_75_0 -DCMAKE_BUILD_TYPE=Release -DWERROR=ON -DCMAKE_CXX_FLAGS="$CXXFLAGS -Wno-psabi" -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. && cd ..
1515 - name: cmake make
16 run: cmake --build build
16 run: cmake --build build -- -j 2
1717 - name: debian package
18 run: fakeroot make -f debian/rules CMAKEFLAGS="-DBOOST_ROOT=/home/pi/Develop/boost_1_74_0 -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" binary
18 run: fakeroot make -f debian/rules CMAKEFLAGS="-DBOOST_ROOT=/home/pi/Develop/boost_1_75_0 -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" binary
1919 - name: Archive artifacts
2020 uses: actions/upload-artifact@v2
2121 with:
0 name: Ubuntu
0 name: Ubuntu-amd64
11
22 on: [push, pull_request]
33
1010 steps:
1111 - uses: actions/checkout@v2
1212 - name: dependencies
13 run: sudo apt-get update && sudo apt-get install -yq libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon debhelper ccache expat
13 run: sudo apt-get update && sudo apt-get install -yq libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon debhelper ccache expat
1414 - name: cache boost
1515 id: cache-boost
1616 uses: actions/cache@v2
1717 with:
18 path: boost_1_74_0
18 path: boost_1_75_0
1919 key: ${{ runner.os }}-boost
2020 - name: get boost
2121 if: steps.cache-boost.outputs.cache-hit != 'true'
22 run: wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2 && tar xjf boost_1_74_0.tar.bz2
22 run: wget https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.bz2 && tar xjf boost_1_75_0.tar.bz2
2323 - name: cache ccache
2424 id: cache-ccache
2525 uses: actions/cache@v2
3030 #- name: ccache dump config
3131 # run: ccache -p
3232 - name: cmake build
33 run: cmake -S . -B build -DBOOST_ROOT=boost_1_74_0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS="$CXXFLAGS -Werror -Wall -Wextra -pedantic -Wno-unused-function"
33 run: cmake -S . -B build -DBOOST_ROOT=boost_1_75_0 -DCMAKE_BUILD_TYPE=Release -DWERROR=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
3434 - name: cmake make
3535 run: cmake --build build --parallel 3
3636 - name: debian package
37 run: fakeroot make -f debian/rules CMAKEFLAGS="-DBOOST_ROOT=boost_1_74_0 -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" binary
37 run: fakeroot make -f debian/rules CMAKEFLAGS="-DBOOST_ROOT=boost_1_75_0 -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" binary
3838 - name: Archive artifacts
3939 uses: actions/upload-artifact@v2
4040 with:
0 name: Windows
0 name: Windows-win64
11
22 on: [push, pull_request]
33
2121 - name: cmake build
2222 run: |
2323 echo vcpkg installation root: ${env:VCPKG_INSTALLATION_ROOT}
24 cmake -S . -B build -G "Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows" -DCMAKE_BUILD_TYPE="Release"
24 cmake -S . -B build -G "Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows" -DCMAKE_BUILD_TYPE="Release" -DWERROR=ON
2525 - name: cmake make
2626 run: cmake --build build --config Release --parallel 3 --verbose
27 - name: installer
28 run: |
29 copy ${env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows\bin\FLAC.dll bin\Release\
30 copy ${env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows\bin\ogg.dll bin\Release\
31 copy ${env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows\bin\opus.dll bin\Release\
32 copy ${env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows\bin\vorbis.dll bin\Release\
33 copy ${env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows\bin\soxr.dll bin\Release\
34 copy "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Redist\MSVC\v142\vc_redist.x64.exe" bin\Release\
2735 - name: Archive artifacts
2836 uses: actions/upload-artifact@v2
2937 with:
3038 name: develop_snapshot_win64-${{github.sha}}
31 path: bin\Release\snapclient.exe
39 path: |
40 bin\Release\snapclient.exe
41 bin\Release\FLAC.dll
42 bin\Release\ogg.dll
43 bin\Release\opus.dll
44 bin\Release\vorbis.dll
45 bin\Release\soxr.dll
46 bin\Release\vc_redist.x64.exe
3247
48
2929 - sourceline: 'ppa:mhier/libboost-latest'
3030 - ubuntu-toolchain-r-test
3131 packages:
32 - g++-5 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
32 - g++-5 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
3333
3434 - os: linux
3535 compiler: gcc
4141 - sourceline: 'ppa:mhier/libboost-latest'
4242 - ubuntu-toolchain-r-test
4343 packages:
44 - g++-6 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
44 - g++-6 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
4545
4646 - os: linux
4747 compiler: gcc
5353 - sourceline: 'ppa:mhier/libboost-latest'
5454 - ubuntu-toolchain-r-test
5555 packages:
56 - g++-7 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
56 - g++-7 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
5757
5858 - os: linux
5959 compiler: gcc
6565 - sourceline: 'ppa:mhier/libboost-latest'
6666 - ubuntu-toolchain-r-test
6767 packages:
68 - g++-8 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
68 - g++-8 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
6969
7070 - os: linux
7171 compiler: gcc
7777 - sourceline: 'ppa:mhier/libboost-latest'
7878 - ubuntu-toolchain-r-test
7979 packages:
80 - g++-9 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
80 - g++-9 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
8181
8282
8383 - os: linux
9292 - sourceline: 'ppa:mhier/libboost-latest'
9393 - llvm-toolchain-trusty-3.9
9494 packages:
95 - clang-3.9 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
95 - clang-3.9 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
9696
9797 - os: linux
9898 compiler: clang
106106 - sourceline: 'ppa:mhier/libboost-latest'
107107 - llvm-toolchain-trusty-4.0
108108 packages:
109 - clang-4.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
109 - clang-4.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
110110
111111 - os: linux
112112 compiler: clang
120120 - sourceline: 'ppa:mhier/libboost-latest'
121121 - llvm-toolchain-trusty-5.0
122122 packages:
123 - clang-5.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
123 - clang-5.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
124124
125125 - os: linux
126126 compiler: clang
134134 - llvm-toolchain-trusty-6.0
135135 - ubuntu-toolchain-r-test
136136 packages:
137 - clang-6.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
137 - clang-6.0 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
138138
139139 - os: linux
140140 compiler: clang
148148 - llvm-toolchain-trusty-7
149149 - ubuntu-toolchain-r-test
150150 packages:
151 - clang-7 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libavahi-client-dev avahi-daemon expat
151 - clang-7 boost1.74 libasound2-dev libsoxr-dev libvorbisidec-dev libvorbis-dev libflac-dev libopus-dev alsa-utils libpulse-dev libavahi-client-dev avahi-daemon expat
152152
153153 # build on osx
154 - os: osx
155 osx_image: xcode9.4
156 env:
157 - MATRIX_EVAL="brew update && brew unlink python@2 && brew upgrade boost && brew install flac opus libvorbis libsoxr expat"
154
155 # xcode 9 is running into a timeout
156 # - os: osx
157 # osx_image: xcode9.4
158 # env:
159 # - MATRIX_EVAL="brew update && brew unlink python@2 && brew upgrade boost && brew install flac opus libvorbis libsoxr expat"
158160
159161 - os: osx
160162 osx_image: xcode10.3
196198 - |
197199 (
198200 if [ "$TRAVIS_OS_NAME" != 'windows' ]; then
199 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="$CXXFLAGS -Werror -Wall -Wextra -pedantic -Wno-unused-function" .. && make && sudo make install
201 cmake -DCMAKE_BUILD_TYPE=Release -DWERROR=ON .. && make && sudo make install
200202 else
201 cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows ..
203 cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_BUILD_TYPE=Release -DWERROR=ON ..
202204 cmake --build . --config Release
203205 fi
204206 )
00 cmake_minimum_required(VERSION 3.2)
11
2 project(snapcast LANGUAGES CXX VERSION 0.22.0)
2 project(snapcast LANGUAGES CXX VERSION 0.23.0)
33 set(PROJECT_DESCRIPTION "Multiroom client-server audio player")
44 set(PROJECT_URL "https://github.com/badaix/snapcast")
55
66 option(BUILD_SHARED_LIBS "Build snapcast in a shared context" ON)
77 option(BUILD_STATIC_LIBS "Build snapcast in a static context" ON)
88 option(BUILD_TESTS "Build tests (run tests with make test)" ON)
9 option(WERROR "Treat warnings as errors" OFF)
10
11 option(ASAN "Enable AddressSanitizer" OFF)
12 option(TSAN "Enable ThreadSanitizer" OFF)
13 option(UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
14
15 if (MSVC)
16 # warning level 4 and all warnings as errors
17 # warning C4505: 'getArch': unreferenced local function has been removed
18 # warning C4458: declaration of 'size' hides class member
19 # warning C4459: declaration of 'query' hides global declaration
20 add_compile_options(/W4 /wd4458 /wd4459 /wd4505)
21 if (WERROR)
22 add_compile_options(/WX)
23 endif()
24 else()
25 # lots of warnings and all warnings as errors
26 add_compile_options(-Wall -Wextra -pedantic -Wno-unused-function)
27 if (WERROR)
28 add_compile_options(-Werror)
29 endif()
30
31 if (ASAN)
32 add_compile_options(-fsanitize=address)
33 add_link_options(-fsanitize=address)
34 endif()
35
36 if (TSAN)
37 add_compile_options(-fsanitize=thread)
38 add_link_options(-fsanitize=thread)
39 endif()
40
41 if (UBSAN)
42 add_compile_options(-fsanitize=undefined)
43 add_link_options(-fsanitize=undefined)
44 endif()
45 endif()
946
1047 include(GNUInstallDirs)
1148
2158 option(BUILD_WITH_OPUS "Build with OPUS support" ON)
2259 option(BUILD_WITH_AVAHI "Build with AVAHI support" ON)
2360 option(BUILD_WITH_EXPAT "Build with EXPAT support" ON)
24
61 option(BUILD_WITH_PULSE "Build with PulseAudio support" ON)
2562
2663 if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
2764 message(FATAL_ERROR "One or both of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be set to ON to build")
4077 endif()
4178 elseif (${CMAKE_SYSTEM_NAME} MATCHES "Android")
4279 set (ANDROID TRUE)
43 add_definitions("-DASIO_DISABLE_STD_FUTURE")
4480 if (BUILD_SERVER)
4581 message(FATAL_ERROR "Snapserver not yet supported for Android, use \"-DBUILD_SERVER=OFF\"")
4682 endif()
68104 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
69105 add_definitions(-DVERSION="${PROJECT_VERSION}")
70106
71 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
72 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
73 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
107 if(NOT ANDROID)
108 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
109 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
110 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
111 endif()
74112
75113 # Configure compiler options
76114 set(CMAKE_CXX_STANDARD 14)
111149 endif()
112150
113151
114 if(NOT WIN32)
152 if(NOT WIN32 AND NOT ANDROID)
115153
116154 if(MACOSX)
117155 set(BONJOUR_FOUND true)
122160 add_definitions(-DFREEBSD -DMACOS -DHAS_DAEMON)
123161 link_directories("/usr/local/lib")
124162 list(APPEND INCLUDE_DIRS "/usr/local/include")
125 elseif(ANDROID)
126 # add_definitions("-DNO_CPP11_STRING")
127163 else()
128164
129165 pkg_search_module(ALSA REQUIRED alsa)
130166 if (ALSA_FOUND)
131167 add_definitions(-DHAS_ALSA)
132168 endif (ALSA_FOUND)
169
170 if(BUILD_WITH_PULSE)
171 pkg_search_module(PULSE libpulse)
172 if (PULSE_FOUND)
173 add_definitions(-DHAS_PULSE)
174 endif (PULSE_FOUND)
175 endif(BUILD_WITH_PULSE)
133176
134177 if(BUILD_WITH_AVAHI)
135178 pkg_search_module(AVAHI avahi-client)
220263 endif()
221264 endif()
222265
223 find_package(Boost 1.70 REQUIRED)
266 if(NOT ANDROID)
267 find_package(Boost 1.70 REQUIRED)
268 else()
269 find_package(oboe REQUIRED CONFIG)
270 find_package(flac REQUIRED CONFIG)
271 find_package(ogg REQUIRED CONFIG)
272 find_package(opus REQUIRED CONFIG)
273 find_package(soxr REQUIRED CONFIG)
274 find_package(tremor REQUIRED CONFIG)
275 find_package(boost REQUIRED CONFIG)
276
277 add_definitions("-DHAS_OBOE")
278 add_definitions("-DHAS_OPENSL")
279 add_definitions("-DHAS_FLAC")
280 add_definitions("-DHAS_OGG")
281 add_definitions("-DHAS_SOXR")
282 add_definitions("-DHAS_TREMOR")
283 endif()
284
224285 add_definitions("-DBOOST_ERROR_CODE_HEADER_ONLY")
225286
226287 if(WIN32)
274335 client/*.[ch]pp
275336 server/*.[ch]pp
276337 )
277
338
339 list(REMOVE_ITEM CHECK_CXX_SOURCE_FILES "${CMAKE_SOURCE_DIR}/common/json.hpp")
340
278341 ADD_CUSTOM_TARGET(
279342 reformat
280343 COMMAND
00 # Contributing
11
22 ## Engaging in Our Project
3
4 You can contribute in several ways:
5
6 * Contribute code for new features, bugfixes, or documentation (see below)
7
8 * Help testing the latest features. Nightly builds are available in [Actions](https://github.com/badaix/snapcast/actions)
9
10 * Star the project
11
12 * Donate on [PayPal](https://www.paypal.me/badaix)
13
14 * Spread the word: blog about Snapcast, tell your friends ...
315
416 We use GitHub to manage reviews of pull requests.
517
2436 You are welcome to contribute code in order to fix a bug or to implement a new feature that is logged as an issue.
2537
2638 Only start working on the Pull Request after the team assigned the issue to you to avoid unnecessary efforts.
39
40 Please note that Snapweb related contributions should be made in the [Snapweb project](https://github.com/badaix/snapweb).
2741
2842 The following rule governs code contributions:
2943
8787 After installation, Snapserver and Snapclient are started with the command line arguments that are configured in `/etc/default/snapserver` and `/etc/default/snapclient`.
8888 Allowed options are listed in the man pages (`man snapserver`, `man snapclient`) or by invoking the snapserver or snapclient with the `-h` option.
8989
90 ### Server
91
9092 The server configuration is done in `/etc/snapserver.conf`. Different audio sources can by configured in the `[stream]` section with a list of `source` options, e.g.:
9193
9294 [stream]
104106 - [tcp](doc/configuration.md#tcp-server): receives audio from a TCP socket, can act as client or server
105107 - [meta](doc/configuration.md#meta): read and mix audio from other stream sources
106108
107 The client will use as audio backend the system's low level audio API to have the best possible control and most precise timing to achieve perfectly synced playback. On Linux `alsa` is used, on Android `oboe` or `opensl`, on macOS `coreaudio` and on Windows `wasapi`.
108 There is also a `file` backend available that will write the raw PCM data to a file (or stdout, stderr). The backend can be configured using the `--player` command line parameter.
109 ### Client
110
111 The client will use as audio backend the system's low level audio API to have the best possible control and most precise timing to achieve perfectly synced playback.
112
113 Available audio backends are configured using the `--player` command line parameter:
114
115 | Backend | OS | Description | Parameters |
116 | --------- | ------- | ------------ | ---------- |
117 | alsa | Linux | ALSA | `buffer_time=<total buffer size [ms]>` (default 80, min 10)<br />`fragments=<number of buffers>` (default 4, min 2) |
118 | pulse | Linux | PulseAudio | `buffer_time=<buffer size [ms]>` (default 80, min 10) |
119 | oboe | Android | Oboe, using OpenSL ES on Android 4.1 and AAudio on 8.1 | |
120 | opensl | Android | OpenSL ES | |
121 | coreaudio | macOS | Core Audio | |
122 | wasapi | Windows | Windows Audio Session API | |
123 | file | All | Write audio to file | `filename=<filename>` (`<filename>` = `stdout`, `stderr`, `null` or a filename)<br />`mode=[w|a]` (`w`: write (discarding the content), `a`: append (keeping the content) |
124
125 Parameters are appended to the player name, e.g. `--player alsa:buffer_time=100`. Use `--player <name>:?` to get a list of available options.
126 For some audio backends you can configure the PCM device using the `-s` or `--soundcard` parameter, the device is choosen by index or name. Available PCM devices can be listed with `-l` or `--list`
109127
110128 ## Test
111129
117135 It's also possible to let the server play a WAV file. Simply configure a `file` stream in `/etc/snapserver.conf`, and restart the server:
118136
119137 [stream]
120 stream = file:///home/user/Musik/Some%20wave%20file.wav?name=test
138 source = file:///home/user/Musik/Some%20wave%20file.wav?name=test
121139
122140 When you are using a Raspberry Pi, you might have to change your audio output to the 3.5mm jack:
123141
00 # Snapcast changelog
1
2 ## Version 0.23.0
3
4 ### Features
5
6 - Client: Add PulseAudio player backend (Issue #722)
7 - Client: Configurable buffer time for alsa and pulse players
8 - Server: If docroot is not configured, a default page is served (Issue #711)
9 - Server: airplay source supports "password" parameter (Issue #754)
10
11 ### Bugfixes
12
13 - Server: airplay source deletes Shairport's meta pipe on exit (Issue #672)
14 - Server: alsa source will not send silece when going idle (Issue #729)
15 - Server: pipe source will not send silence after 3h idle (Issue #741)
16 - Server: Fix build error on FreeBSD (Issue #752)
17 - Client: "make install" will set correct user/group for snapclient (Issue #728)
18 - Client: Fix printing UTF-8 device names on Windows (Issue #732)
19 - Client: Fix stuttering on alsa player backend (Issue #722, #727)
20 - Client: Terminate if host is not configured and mDNS is unavailable
21
22 ### General
23
24 - Server: Change librespot parameter "killall" default to false (Issue #746, #724)
25 - Client: Android uses performance mode "none" to allow effects (Issue #766)
26 - Snapweb: Update to v0.1.0
27 - Build: Update CMakeLists.txt to build Snapclient on Android
28
29 _Johannes Pohl <snapcast@badaix.de> Sun, 10 Jan 2021 00:13:37 +0200_
130
231 ## Version 0.22.0
332
2929 find_library(IOKIT_LIB IOKit)
3030 find_library(AUDIOTOOLBOX_LIB AudioToolbox)
3131 list(APPEND CLIENT_LIBRARIES ${COREAUDIO_LIB} ${COREFOUNDATION_LIB} ${IOKIT_LIB} ${AUDIOTOOLBOX_LIB})
32 elseif (WIN32)
32 elseif (WIN32)
3333 list(APPEND CLIENT_SOURCES player/wasapi_player.cpp)
3434 list(APPEND CLIENT_LIBRARIES wsock32 ws2_32 avrt ksuser iphlpapi)
35 else()
35 elseif(NOT ANDROID)
3636 # Avahi
3737 if (AVAHI_FOUND)
3838 list(APPEND CLIENT_SOURCES browseZeroConf/browse_avahi.cpp)
4646 list(APPEND CLIENT_LIBRARIES ${ALSA_LIBRARIES})
4747 list(APPEND CLIENT_INCLUDE ${ALSA_INCLUDE_DIRS})
4848 endif (ALSA_FOUND)
49
50 if (PULSE_FOUND)
51 list(APPEND CLIENT_SOURCES player/pulse_player.cpp)
52 list(APPEND CLIENT_LIBRARIES ${PULSE_LIBRARIES})
53 list(APPEND CLIENT_INCLUDE ${PULSE_INCLUDE_DIRS})
54 endif (PULSE_FOUND)
4955 endif (MACOSX)
5056
51 # if OGG then tremor or vorbis
52 if (OGG_FOUND)
57 if (ANDROID)
58 list(APPEND CLIENT_LIBRARIES oboe::oboe)
59 list(APPEND CLIENT_LIBRARIES boost::boost)
60 list(APPEND CLIENT_LIBRARIES flac::flac)
61 list(APPEND CLIENT_LIBRARIES opus::opus)
62 list(APPEND CLIENT_LIBRARIES tremor::tremor)
63 list(APPEND CLIENT_LIBRARIES ogg::ogg)
64 list(APPEND CLIENT_SOURCES player/oboe_player.cpp)
65 list(APPEND CLIENT_SOURCES player/opensl_player.cpp)
5366 list(APPEND CLIENT_SOURCES decoder/ogg_decoder.cpp)
54 list(APPEND CLIENT_LIBRARIES ${OGG_LIBRARIES})
55 list(APPEND CLIENT_INCLUDE ${OGG_INCLUDE_DIRS})
56 endif (OGG_FOUND)
67 list(APPEND CLIENT_SOURCES decoder/flac_decoder.cpp)
68 list(APPEND CLIENT_LIBRARIES OpenSLES)
5769
58 # Tremor (fixed-point) or libvorbis (floating-point)
59 if (TREMOR_FOUND)
60 list(APPEND CLIENT_LIBRARIES ${TREMOR_LIBRARIES})
61 list(APPEND CLIENT_INCLUDE ${TREMOR_INCLUDE_DIRS})
62 elseif (VORBIS_FOUND)
63 list(APPEND CLIENT_LIBRARIES ${VORBIS_LIBRARIES})
64 list(APPEND CLIENT_INCLUDE ${VORBIS_INCLUDE_DIRS})
65 endif (TREMOR_FOUND)
70 else()
71 # if OGG then tremor or vorbis
72 if (OGG_FOUND)
73 list(APPEND CLIENT_SOURCES decoder/ogg_decoder.cpp)
74 list(APPEND CLIENT_LIBRARIES ${OGG_LIBRARIES})
75 list(APPEND CLIENT_INCLUDE ${OGG_INCLUDE_DIRS})
76 endif (OGG_FOUND)
6677
67 if (FLAC_FOUND)
68 list(APPEND CLIENT_SOURCES decoder/flac_decoder.cpp)
69 list(APPEND CLIENT_LIBRARIES ${FLAC_LIBRARIES})
70 list(APPEND CLIENT_INCLUDE ${FLAC_INCLUDE_DIRS})
71 endif (FLAC_FOUND)
78 # Tremor (fixed-point) or libvorbis (floating-point)
79 if (TREMOR_FOUND)
80 list(APPEND CLIENT_LIBRARIES ${TREMOR_LIBRARIES})
81 list(APPEND CLIENT_INCLUDE ${TREMOR_INCLUDE_DIRS})
82 elseif (VORBIS_FOUND)
83 list(APPEND CLIENT_LIBRARIES ${VORBIS_LIBRARIES})
84 list(APPEND CLIENT_INCLUDE ${VORBIS_INCLUDE_DIRS})
85 endif (TREMOR_FOUND)
7286
73 if (OPUS_FOUND)
74 list(APPEND CLIENT_SOURCES decoder/opus_decoder.cpp)
75 list(APPEND CLIENT_LIBRARIES ${OPUS_LIBRARIES})
76 list(APPEND CLIENT_INCLUDE ${OPUS_INCLUDE_DIRS})
77 endif (OPUS_FOUND)
87 if (FLAC_FOUND)
88 list(APPEND CLIENT_SOURCES decoder/flac_decoder.cpp)
89 list(APPEND CLIENT_LIBRARIES ${FLAC_LIBRARIES})
90 list(APPEND CLIENT_INCLUDE ${FLAC_INCLUDE_DIRS})
91 endif (FLAC_FOUND)
92
93 if (OPUS_FOUND)
94 list(APPEND CLIENT_SOURCES decoder/opus_decoder.cpp)
95 list(APPEND CLIENT_LIBRARIES ${OPUS_LIBRARIES})
96 list(APPEND CLIENT_INCLUDE ${OPUS_INCLUDE_DIRS})
97 endif (OPUS_FOUND)
98 endif()
7899
79100 include_directories(${CLIENT_INCLUDE})
80 add_executable(snapclient ${CLIENT_SOURCES})
81 target_link_libraries(snapclient ${CLIENT_LIBRARIES})
101 if (ANDROID)
102 add_executable(libsnapclient.so ${CLIENT_SOURCES})
103 target_link_libraries(libsnapclient.so ${CLIENT_LIBRARIES} log OpenSLES)
104 else()
105 add_executable(snapclient ${CLIENT_SOURCES})
106 target_link_libraries(snapclient ${CLIENT_LIBRARIES})
82107
83 install(TARGETS snapclient COMPONENT client DESTINATION "${CMAKE_INSTALL_BINDIR}")
84 install(FILES snapclient.1 COMPONENT client DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
108 install(TARGETS snapclient COMPONENT client DESTINATION "${CMAKE_INSTALL_BINDIR}")
109 install(FILES snapclient.1 COMPONENT client DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
110 endif()
85111
1313 # You should have received a copy of the GNU General Public License
1414 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16 VERSION = 0.22.0
16 VERSION = 0.23.0
1717 BIN = snapclient
1818
1919 ifeq ($(TARGET), FREEBSD)
8383 else
8484
8585 CXX = g++
86 CXXFLAGS += -pthread -DHAS_VORBIS -DHAS_ALSA -DHAS_AVAHI -DHAS_DAEMON
87 LDFLAGS += -lrt -lasound -lvorbis -lavahi-client -lavahi-common -latomic
88 OBJ += ../common/daemon.o player/alsa_player.o browseZeroConf/browse_avahi.o
86 CXXFLAGS += -pthread -DHAS_VORBIS -DHAS_ALSA -DHAS_PULSE -DHAS_AVAHI -DHAS_DAEMON
87 LDFLAGS += -lrt -lasound -lpulse -lvorbis -lavahi-client -lavahi-common -latomic
88 OBJ += ../common/daemon.o player/alsa_player.o player/pulse_player.o browseZeroConf/browse_avahi.o
8989
9090 endif
9191
177177 /etc/init.d/$(BIN) start; \
178178
179179 adduser:
180 @if ! getent passwd snapclient >/dev/null; then \
181 useradd --gid audio --system snapclient; \
182 fi; \
180 sh ../debian/snapclient.postinst configure
183181
184182 ifeq ($(TARGET), MACOS)
185183
226224 systemctl daemon-reload; \
227225
228226 deluser:
229 @userdel --force snapclient > /dev/null || true; \
230
227 sh ../debian/snapclient.postrm purge
228
175175 deque<mDNSReply> replyCollection;
176176 {
177177 DNSServiceHandle service(new DNSServiceRef(NULL));
178 CHECKED(DNSServiceBrowse(service.get(), 0, 0, serviceName.c_str(), "local.",
179 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode,
180 const char* serviceName, const char* regtype, const char* replyDomain, void* context) {
181 auto replyCollection = static_cast<deque<mDNSReply>*>(context);
182
183 CHECKED(errorCode);
184 replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
185 },
186 &replyCollection));
178 CHECKED(DNSServiceBrowse(
179 service.get(), 0, 0, serviceName.c_str(), "local.",
180 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode, const char* serviceName,
181 const char* regtype, const char* replyDomain, void* context) {
182 auto replyCollection = static_cast<deque<mDNSReply>*>(context);
183
184 CHECKED(errorCode);
185 replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
186 },
187 &replyCollection));
187188
188189 runService(service);
189190 }
193194 {
194195 DNSServiceHandle service(new DNSServiceRef(NULL));
195196 for (auto& reply : replyCollection)
196 CHECKED(DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
197 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode,
198 const char* /*fullName*/, const char* hosttarget, uint16_t port, uint16_t /*txtLen*/,
199 const unsigned char* /*txtRecord*/, void* context) {
200 auto resultCollection = static_cast<deque<mDNSResolve>*>(context);
201
202 CHECKED(errorCode);
203 resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
204 },
205 &resolveCollection));
197 CHECKED(DNSServiceResolve(
198 service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
199 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode, const char* /*fullName*/,
200 const char* hosttarget, uint16_t port, uint16_t /*txtLen*/, const unsigned char* /*txtRecord*/, void* context) {
201 auto resultCollection = static_cast<deque<mDNSResolve>*>(context);
202
203 CHECKED(errorCode);
204 resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
205 },
206 &resolveCollection));
206207
207208 runService(service);
208209 }
215216 for (auto& resolve : resolveCollection)
216217 {
217218 resultCollection[i].port = resolve.port;
218 CHECKED(DNSServiceGetAddrInfo(service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
219 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t interfaceIndex, DNSServiceErrorType /*errorCode*/,
220 const char* hostname, const sockaddr* address, uint32_t /*ttl*/, void* context) {
221 auto result = static_cast<mDNSResult*>(context);
222
223 result->host = string(hostname);
224 result->ip_version = (address->sa_family == AF_INET) ? (IPVersion::IPv4) : (IPVersion::IPv6);
225 result->iface_idx = static_cast<int>(interfaceIndex);
226
227 char hostIP[NI_MAXHOST];
228 char hostService[NI_MAXSERV];
229 if (getnameinfo(address, sizeof(*address), hostIP, sizeof(hostIP), hostService, sizeof(hostService),
230 NI_NUMERICHOST | NI_NUMERICSERV) == 0)
231 result->ip = string(hostIP);
232 else
233 return;
234 result->valid = true;
235 },
236 &resultCollection[i++]));
219 CHECKED(DNSServiceGetAddrInfo(
220 service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
221 [](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t interfaceIndex, DNSServiceErrorType /*errorCode*/, const char* hostname,
222 const sockaddr* address, uint32_t /*ttl*/, void* context) {
223 auto result = static_cast<mDNSResult*>(context);
224
225 result->host = string(hostname);
226 result->ip_version = (address->sa_family == AF_INET) ? (IPVersion::IPv4) : (IPVersion::IPv6);
227 result->iface_idx = static_cast<int>(interfaceIndex);
228
229 char hostIP[NI_MAXHOST];
230 char hostService[NI_MAXSERV];
231 if (getnameinfo(address, sizeof(*address), hostIP, sizeof(hostIP), hostService, sizeof(hostService), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
232 result->ip = string(hostIP);
233 else
234 return;
235 result->valid = true;
236 },
237 &resultCollection[i++]));
237238 }
238239 runService(service);
239240 }
6060 /// @param value the response message
6161 void setValue(std::unique_ptr<msg::BaseMessage> value)
6262 {
63 boost::asio::post(strand_, [ this, self = shared_from_this(), val = std::move(value) ]() mutable {
63 boost::asio::post(strand_, [this, self = shared_from_this(), val = std::move(value)]() mutable {
6464 timer_.cancel();
6565 if (handler_)
6666 handler_({}, std::move(val));
7878 void startTimer(const chronos::usec& timeout)
7979 {
8080 timer_.expires_after(timeout);
81 timer_.async_wait(boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](boost::system::error_code ec) {
81 timer_.async_wait(boost::asio::bind_executor(strand_, [this, self = shared_from_this()](boost::system::error_code ec) {
8282 if (!handler_)
8383 return;
8484 if (!ec)
5959 std::string player_name{""};
6060 std::string parameter{""};
6161 int latency{0};
62 PcmDevice pcm_device;
62 player::PcmDevice pcm_device;
6363 SampleFormat sample_format;
6464 SharingMode sharing_mode{SharingMode::unspecified};
6565 Mixer mixer;
3333
3434 #ifdef HAS_ALSA
3535 #include "player/alsa_player.hpp"
36 #endif
37 #ifdef HAS_PULSE
38 #include "player/pulse_player.hpp"
3639 #endif
3740 #ifdef HAS_OPENSL
3841 #include "player/opensl_player.hpp"
6265 #include <string>
6366
6467 using namespace std;
68 using namespace player;
6569
6670 static constexpr auto LOG_TAG = "Controller";
6771 static constexpr auto TIME_SYNC_INTERVAL = 1s;
8892 {
8993 std::vector<std::string> result;
9094 #ifdef HAS_ALSA
91 result.emplace_back("alsa");
95 result.emplace_back(player::ALSA);
96 #endif
97 #ifdef HAS_PULSE
98 result.emplace_back(player::PULSE);
9299 #endif
93100 #ifdef HAS_OBOE
94 result.emplace_back("oboe");
101 result.emplace_back(player::OBOE);
95102 #endif
96103 #ifdef HAS_OPENSL
97 result.emplace_back("opensl");
104 result.emplace_back(player::OPENSL);
98105 #endif
99106 #ifdef HAS_COREAUDIO
100 result.emplace_back("coreaudio");
107 result.emplace_back(player::COREAUDIO);
101108 #endif
102109 #ifdef HAS_WASAPI
103 result.emplace_back("wasapi");
104 #endif
105 result.emplace_back("file");
110 result.emplace_back(player::WASAPI);
111 #endif
112 result.emplace_back(player::FILE);
106113 return result;
107114 }
108115
177184
178185 #ifdef HAS_ALSA
179186 if (!player_)
180 player_ = createPlayer<AlsaPlayer>(settings_.player, "alsa");
187 player_ = createPlayer<AlsaPlayer>(settings_.player, player::ALSA);
188 #endif
189 #ifdef HAS_PULSE
190 if (!player_)
191 player_ = createPlayer<PulsePlayer>(settings_.player, player::PULSE);
181192 #endif
182193 #ifdef HAS_OBOE
183194 if (!player_)
184 player_ = createPlayer<OboePlayer>(settings_.player, "oboe");
195 player_ = createPlayer<OboePlayer>(settings_.player, player::OBOE);
185196 #endif
186197 #ifdef HAS_OPENSL
187198 if (!player_)
188 player_ = createPlayer<OpenslPlayer>(settings_.player, "opensl");
199 player_ = createPlayer<OpenslPlayer>(settings_.player, player::OPENSL);
189200 #endif
190201 #ifdef HAS_COREAUDIO
191202 if (!player_)
192 player_ = createPlayer<CoreAudioPlayer>(settings_.player, "coreaudio");
203 player_ = createPlayer<CoreAudioPlayer>(settings_.player, player::COREAUDIO);
193204 #endif
194205 #ifdef HAS_WASAPI
195206 if (!player_)
196 player_ = createPlayer<WASAPIPlayer>(settings_.player, "wasapi");
197 #endif
198 if (!player_ && (settings_.player.player_name == "file"))
199 player_ = createPlayer<FilePlayer>(settings_.player, "file");
207 player_ = createPlayer<WASAPIPlayer>(settings_.player, player::WASAPI);
208 #endif
209 if (!player_ && (settings_.player.player_name == player::FILE))
210 player_ = createPlayer<FilePlayer>(settings_.player, player::FILE);
200211
201212 if (!player_)
202213 throw SnapException("No audio player support" + (settings_.player.player_name.empty() ? "" : " for: " + settings_.player.player_name));
249260 void Controller::sendTimeSyncMessage(int quick_syncs)
250261 {
251262 auto timeReq = std::make_shared<msg::Time>();
252 clientConnection_->sendRequest<msg::Time>(timeReq, 2s, [this, quick_syncs](const boost::system::error_code& ec,
253 const std::unique_ptr<msg::Time>& response) mutable {
254 if (ec)
255 {
256 LOG(ERROR, LOG_TAG) << "Time sync request failed: " << ec.message() << "\n";
257 reconnect();
258 return;
259 }
260 else
261 {
262 TimeProvider::getInstance().setDiff(response->latency, response->received - response->sent);
263 }
264
265 std::chrono::microseconds next = TIME_SYNC_INTERVAL;
266 if (quick_syncs > 0)
267 {
268 if (--quick_syncs == 0)
269 LOG(INFO, LOG_TAG) << "diff to server [ms]: " << (float)TimeProvider::getInstance().getDiffToServer<chronos::usec>().count() / 1000.f << "\n";
270 next = 100us;
271 }
272 timer_.expires_after(next);
273 timer_.async_wait([this, quick_syncs](const boost::system::error_code& ec) {
274 if (!ec)
275 {
276 sendTimeSyncMessage(quick_syncs);
277 }
263 clientConnection_->sendRequest<msg::Time>(
264 timeReq, 2s, [this, quick_syncs](const boost::system::error_code& ec, const std::unique_ptr<msg::Time>& response) mutable {
265 if (ec)
266 {
267 LOG(ERROR, LOG_TAG) << "Time sync request failed: " << ec.message() << "\n";
268 reconnect();
269 return;
270 }
271 else
272 {
273 TimeProvider::getInstance().setDiff(response->latency, response->received - response->sent);
274 }
275
276 std::chrono::microseconds next = TIME_SYNC_INTERVAL;
277 if (quick_syncs > 0)
278 {
279 if (--quick_syncs == 0)
280 LOG(INFO, LOG_TAG) << "diff to server [ms]: " << (float)TimeProvider::getInstance().getDiffToServer<chronos::usec>().count() / 1000.f
281 << "\n";
282 next = 100us;
283 }
284 timer_.expires_after(next);
285 timer_.async_wait([this, quick_syncs](const boost::system::error_code& ec) {
286 if (!ec)
287 {
288 sendTimeSyncMessage(quick_syncs);
289 }
290 });
278291 });
279 });
280292 }
281293
282294 void Controller::browseMdns(const MdnsHandler& handler)
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 ***/
1717
18 #ifndef CONTROLLER_H
19 #define CONTROLLER_H
18 #ifndef CONTROLLER_HPP
19 #define CONTROLLER_HPP
2020
2121 #include "client_connection.hpp"
2222 #include "client_settings.hpp"
5454 void browseMdns(const MdnsHandler& handler);
5555
5656 template <typename PlayerType>
57 std::unique_ptr<Player> createPlayer(ClientSettings::Player& settings, const std::string& player_name);
57 std::unique_ptr<player::Player> createPlayer(ClientSettings::Player& settings, const std::string& player_name);
5858
5959 void getNextMessage();
6060 void sendTimeSyncMessage(int quick_syncs);
6767 std::unique_ptr<ClientConnection> clientConnection_;
6868 std::shared_ptr<Stream> stream_;
6969 std::unique_ptr<decoder::Decoder> decoder_;
70 std::unique_ptr<Player> player_;
70 std::unique_ptr<player::Player> player_;
7171 std::unique_ptr<MetadataAdapter> meta_;
7272 std::unique_ptr<msg::ServerSettings> serverSettings_;
7373 std::unique_ptr<msg::CodecHeader> headerChunk_;
205205 if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
206206 {
207207 static_cast<FlacDecoder*>(client_data)->cacheInfo_.sampleRate_ = metadata->data.stream_info.sample_rate;
208 sampleFormat.setFormat(metadata->data.stream_info.sample_rate, metadata->data.stream_info.bits_per_sample, metadata->data.stream_info.channels);
208 sampleFormat.setFormat(metadata->data.stream_info.sample_rate, static_cast<uint16_t>(metadata->data.stream_info.bits_per_sample),
209 static_cast<uint16_t>(metadata->data.stream_info.channels));
209210 }
210211 }
211212
224224 /// local state for most of the decode so multiple block decodes can proceed
225225 /// in parallel. We could init multiple vorbis_block structures for vd here
226226
227 sampleFormat_.setFormat(vi.rate, 16, vi.channels);
227 sampleFormat_.setFormat(vi.rate, 16, static_cast<uint16_t>(vi.channels));
228228
229229 /* Throw the comments plus a few lines about the bitstream we're decoding */
230230 char** ptr = vc.user_comments;
2121 #include "common/str_compat.hpp"
2222 #include "common/utils/string_utils.hpp"
2323
24 //#define BUFFER_TIME 120000
25 #define PERIOD_TIME 15000
24 using namespace std::chrono_literals;
25 using namespace std;
26
27 namespace player
28 {
29
30 static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms;
31 static constexpr int PERIODS = 4;
32
2633 #define exp10(x) (exp((x)*log(10)))
2734
28 using namespace std;
2935
3036 static constexpr auto LOG_TAG = "Alsa";
3137 static constexpr auto DEFAULT_MIXER = "PCM";
6066
6167 LOG(DEBUG, LOG_TAG) << "Mixer: " << mixer_name_ << ", device: " << mixer_device_ << "\n";
6268 }
69
70 buffer_time_ = BUFFER_TIME;
71 periods_ = PERIODS;
72 auto params = utils::string::split_pairs(settings.parameter, ',', '=');
73 if (params.find("buffer_time") != params.end())
74 buffer_time_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10));
75 if (params.find("fragments") != params.end())
76 periods_ = std::max(cpt::stoi(params["fragments"]), 2);
77
78 LOG(INFO, LOG_TAG) << "Using buffer_time: " << buffer_time_.count() / 1000 << " ms, fragments: " << periods_ << "\n";
6379 }
6480
6581
260276 void AlsaPlayer::initAlsa()
261277 {
262278 std::lock_guard<std::recursive_mutex> lock(mutex_);
263 unsigned int tmp, rate;
264 int err, channels;
265 snd_pcm_hw_params_t* params;
266279
267280 const SampleFormat& format = stream_->getFormat();
268 rate = format.rate();
269 channels = format.channels();
270
271 /* Open the PCM device in playback mode */
281 unsigned int rate = format.rate();
282 int channels = format.channels();
283 int err;
284
285 // Open the PCM device in playback mode
272286 if ((err = snd_pcm_open(&handle_, settings_.pcm_device.name.c_str(), SND_PCM_STREAM_PLAYBACK, 0)) < 0)
273287 throw SnapException("Can't open " + settings_.pcm_device.name + ", error: " + snd_strerror(err), err);
274288
275 /* struct snd_pcm_playback_info_t pinfo;
276 if ( (pcm = snd_pcm_playback_info( pcm_handle, &pinfo )) < 0 )
277 fprintf( stderr, "Error: playback info error: %s\n", snd_strerror( err ) );
278 printf("buffer: '%d'\n", pinfo.buffer_size);
279 */
280 /* Allocate parameters object and fill it with default values*/
289 // struct snd_pcm_playback_info_t pinfo;
290 // if ((pcm = snd_pcm_playback_info( pcm_handle, &pinfo)) < 0)
291 // fprintf(stderr, "Error: playback info error: %s\n", snd_strerror(err));
292 // printf("buffer: '%d'\n", pinfo.buffer_size);
293
294 // Allocate parameters object and fill it with default values
295 snd_pcm_hw_params_t* params;
281296 snd_pcm_hw_params_alloca(&params);
282
283297 if ((err = snd_pcm_hw_params_any(handle_, params)) < 0)
284298 throw SnapException("Can't fill params: " + string(snd_strerror(err)));
285299
286 /* Set parameters */
300 // Set parameters
287301 if ((err = snd_pcm_hw_params_set_access(handle_, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
288302 throw SnapException("Can't set interleaved mode: " + string(snd_strerror(err)));
289303
332346
333347 if ((err = snd_pcm_hw_params_set_rate_near(handle_, params, &rate, nullptr)) < 0)
334348 throw SnapException("Can't set rate: " + string(snd_strerror(err)));
335
336 unsigned int period_time;
337 snd_pcm_hw_params_get_period_time_max(params, &period_time, nullptr);
338 if (period_time > PERIOD_TIME)
339 period_time = PERIOD_TIME;
340
341 unsigned int buffer_time = 4 * period_time;
342
343 snd_pcm_hw_params_set_period_time_near(handle_, params, &period_time, nullptr);
344 snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr);
349 if (rate != format.rate())
350 LOG(WARNING, LOG_TAG) << "Could not set sample rate to " << format.rate() << " Hz, using: " << rate << " Hz\n";
351
352 unsigned int buffer_time = buffer_time_.count();
353 if ((err = snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr)) < 0)
354 throw SnapException("Can't set buffer time: " + string(snd_strerror(err)));
355
356 unsigned int periods = periods_;
357 if ((err = snd_pcm_hw_params_set_periods_near(handle_, params, &periods, 0)) < 0)
358 throw SnapException("Can't set periods: " + string(snd_strerror(err)));
345359
346360 // long unsigned int periodsize = stream_->format.msRate() * 50;//2*rate/50;
347361 // if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0)
348362 // LOG(ERROR, LOG_TAG) << "Unable to set buffer size " << (long int)periodsize << ": " << snd_strerror(pcm) << "\n";
349363
350 /* Write parameters */
364 // Write parameters
351365 if ((err = snd_pcm_hw_params(handle_, params)) < 0)
352366 throw SnapException("Can't set hardware parameters: " + string(snd_strerror(err)));
353367
354 /* Resume information */
355 LOG(DEBUG, LOG_TAG) << "PCM name: " << snd_pcm_name(handle_) << "\n";
356 LOG(DEBUG, LOG_TAG) << "PCM state: " << snd_pcm_state_name(snd_pcm_state(handle_)) << "\n";
357 snd_pcm_hw_params_get_channels(params, &tmp);
358 LOG(DEBUG, LOG_TAG) << "channels: " << tmp << "\n";
359
360 snd_pcm_hw_params_get_rate(params, &tmp, nullptr);
361 LOG(DEBUG, LOG_TAG) << "rate: " << tmp << " bps\n";
362
363 /* Allocate buffer to hold single period */
368 // Resume information
369 unsigned int period_time;
370 snd_pcm_hw_params_get_period_time(params, &period_time, nullptr);
364371 snd_pcm_hw_params_get_period_size(params, &frames_, nullptr);
365 LOG(DEBUG, LOG_TAG) << "frames: " << frames_ << "\n";
366
367 snd_pcm_hw_params_get_period_time(params, &tmp, nullptr);
368 LOG(DEBUG, LOG_TAG) << "period time: " << tmp << "\n";
369
372 LOG(INFO, LOG_TAG) << "PCM name: " << snd_pcm_name(handle_) << ", sample rate: " << rate << " Hz, channels: " << channels
373 << ", buffer time: " << buffer_time << " us, periods: " << periods << ", period time: " << period_time
374 << " us, period frames: " << frames_ << "\n";
375
376 // Allocate buffer to hold single period
370377 snd_pcm_sw_params_t* swparams;
371378 snd_pcm_sw_params_alloca(&swparams);
372379 snd_pcm_sw_params_current(handle_, swparams);
376383 // snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, frames_);
377384 snd_pcm_sw_params(handle_, swparams);
378385
386 if (snd_pcm_state(handle_) == SND_PCM_STATE_PREPARED)
387 {
388 if ((err = snd_pcm_start(handle_)) < 0)
389 LOG(DEBUG, LOG_TAG) << "Failed to start PCM: " << snd_strerror(err) << "\n";
390 }
391
379392 if (ctl_ == nullptr)
380393 initMixer();
381394 }
456469
457470 bool AlsaPlayer::needsThread() const
458471 {
472 return true;
473 }
474
475
476 bool AlsaPlayer::getAvailDelay(snd_pcm_sframes_t& avail, snd_pcm_sframes_t& delay)
477 {
478 int result = snd_pcm_avail_delay(handle_, &avail, &delay);
479 if (result < 0)
480 {
481 LOG(WARNING, LOG_TAG) << "snd_pcm_avail_delay failed: " << snd_strerror(result) << " (" << result << "), avail: " << avail << ", delay: " << delay
482 << ", using snd_pcm_avail amd snd_pcm_delay.\n";
483 this_thread::sleep_for(1ms);
484 avail = snd_pcm_avail(handle_);
485 result = snd_pcm_delay(handle_, &delay);
486 if ((result < 0) || (delay < 0))
487 {
488 LOG(WARNING, LOG_TAG) << "snd_pcm_delay failed: " << snd_strerror(result) << " (" << result << "), avail: " << avail << ", delay: " << delay
489 << "\n";
490 return false;
491 }
492 // LOG(DEBUG, LOG_TAG) << "snd_pcm_delay: " << delay << ", snd_pcm_avail: " << avail << "\n";
493 }
494
495 if (avail < 0)
496 {
497 LOG(DEBUG, LOG_TAG) << "snd_pcm_avail failed: " << snd_strerror(avail) << " (" << avail << "), using " << frames_ << "\n";
498 avail = frames_;
499 }
500
459501 return true;
460502 }
461503
490532 int wait_result = snd_pcm_wait(handle_, 100);
491533 if (wait_result == -EPIPE)
492534 {
493 LOG(ERROR, LOG_TAG) << "XRUN: " << snd_strerror(wait_result) << "\n";
535 LOG(ERROR, LOG_TAG) << "XRUN while waiting for PCM: " << snd_strerror(wait_result) << "\n";
494536 snd_pcm_prepare(handle_);
495537 }
496538 else if (wait_result < 0)
504546 continue;
505547 }
506548
507 int result = snd_pcm_avail_delay(handle_, &framesAvail, &framesDelay);
508 if (result < 0)
509 {
510 // if (result == -EPIPE)
511 // snd_pcm_prepare(handle_);
512 // else
513 // uninitAlsa();
514 LOG(WARNING, LOG_TAG) << "snd_pcm_avail_delay failed: " << snd_strerror(result) << ", avail: " << framesAvail << ", delay: " << framesDelay
515 << ", retrying.\n";
549 if (!getAvailDelay(framesAvail, framesDelay))
550 {
551 this_thread::sleep_for(10ms);
552 snd_pcm_prepare(handle_);
553 continue;
554 }
555
556 if (framesAvail < static_cast<snd_pcm_sframes_t>(frames_))
557 {
516558 this_thread::sleep_for(5ms);
517 int result = snd_pcm_avail_delay(handle_, &framesAvail, &framesDelay);
518 if (result < 0)
519 {
520 this_thread::sleep_for(5ms);
521 LOG(WARNING, LOG_TAG) << "snd_pcm_avail_delay failed again: " << snd_strerror(result) << ", avail: " << framesAvail
522 << ", delay: " << framesDelay << ", using snd_pcm_avail and snd_pcm_delay.\n";
523 framesAvail = snd_pcm_avail(handle_);
524 result = snd_pcm_delay(handle_, &framesDelay);
525 if ((result < 0) || (framesAvail <= 0) || (framesDelay <= 0))
526 {
527 LOG(WARNING, LOG_TAG) << "snd_pcm_avail and snd_pcm_delay failed: " << snd_strerror(result) << ", avail: " << framesAvail
528 << ", delay: " << framesDelay << "\n";
529 this_thread::sleep_for(10ms);
530 snd_pcm_prepare(handle_);
531 continue;
532 }
533 }
534 }
535
536 if (framesAvail < static_cast<snd_pcm_sframes_t>(frames_))
537 {
538 this_thread::sleep_for(10ms);
539559 continue;
540560 }
541561
554574 adjustVolume(buffer_.data(), framesAvail);
555575 if ((pcm = snd_pcm_writei(handle_, buffer_.data(), framesAvail)) == -EPIPE)
556576 {
557 LOG(ERROR, LOG_TAG) << "XRUN: " << snd_strerror(pcm) << "\n";
577 LOG(ERROR, LOG_TAG) << "XRUN while writing to PCM: " << snd_strerror(pcm) << "\n";
558578 snd_pcm_prepare(handle_);
559579 }
560580 else if (pcm < 0)
624644 snd_device_name_free_hint(hints);
625645 return result;
626646 }
647
648 } // namespace player
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 ***/
1717
18 #ifndef ALSA_PLAYER_H
19 #define ALSA_PLAYER_H
18 #ifndef ALSA_PLAYER_HPP
19 #define ALSA_PLAYER_HPP
2020
2121 #include "player.hpp"
22
2223 #include <alsa/asoundlib.h>
24 #include <chrono>
2325
26
27 namespace player
28 {
29
30 static constexpr auto ALSA = "alsa";
2431
2532 /// Audio Player
2633 /**
3643 void stop() override;
3744
3845 /// List the system's audio output devices
39 static std::vector<PcmDevice> pcm_list(void);
46 static std::vector<PcmDevice> pcm_list();
4047
4148 protected:
4249 void worker() override;
4855 /// free alsa and optionally the mixer
4956 /// @param uninit_mixer free the mixer
5057 void uninitAlsa(bool uninit_mixer);
58 bool getAvailDelay(snd_pcm_sframes_t& avail, snd_pcm_sframes_t& delay);
5159
5260 void initMixer();
5361 void uninitMixer();
7280 std::chrono::time_point<std::chrono::steady_clock> last_change_;
7381 std::recursive_mutex mutex_;
7482 boost::asio::steady_timer timer_;
83
84 std::chrono::microseconds buffer_time_;
85 unsigned int periods_;
7586 };
7687
88 } // namespace player
7789
7890 #endif
1818 #include "coreaudio_player.hpp"
1919 #include <CoreAudio/CoreAudio.h>
2020
21 namespace player
22 {
23
2124 #define NUM_BUFFERS 2
2225
2326 static constexpr auto LOG_TAG = "CoreAudioPlayer";
4447
4548
4649 /// TODO: experimental. No output device can be configured yet.
47 std::vector<PcmDevice> CoreAudioPlayer::pcm_list(void)
50 std::vector<PcmDevice> CoreAudioPlayer::pcm_list()
4851 {
4952 UInt32 propsize;
5053
209212 pubStream_->clearChunks();
210213 CFRunLoopStop(CFRunLoopGetCurrent());
211214 }
215
216 } // namespace player
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 ***/
1717
18 #ifndef CORE_AUDIO_PLAYER_H
19 #define CORE_AUDIO_PLAYER_H
18 #ifndef CORE_AUDIO_PLAYER_HPP
19 #define CORE_AUDIO_PLAYER_HPP
2020
2121 #include <AudioToolbox/AudioQueue.h>
2222 #include <CoreAudio/CoreAudioTypes.h>
2323 #include <CoreFoundation/CFRunLoop.h>
2424
2525 #include "player.hpp"
26
27 namespace player
28 {
29
30 static constexpr auto COREAUDIO = "coreaudio";
2631
2732 /// Audio Player
2833 /**
4045 virtual ~CoreAudioPlayer();
4146
4247 void playerCallback(AudioQueueRef queue, AudioQueueBufferRef bufferRef);
43 static std::vector<PcmDevice> pcm_list(void);
48 static std::vector<PcmDevice> pcm_list();
4449
4550 protected:
4651 void worker() override;
5762 long lastChunkTick;
5863 };
5964
65 } // namespace player
6066
6167 #endif
2626
2727 using namespace std;
2828
29 namespace player
30 {
31
2932 static constexpr auto LOG_TAG = "FilePlayer";
3033 static constexpr auto kDefaultBuffer = 50ms;
3134
4649 {
4750 file_.reset(stderr, [](auto p) { std::ignore = p; });
4851 }
49 else
52 else if (filename != "null")
5053 {
5154 std::string mode = "w";
5255 if (params.find("mode") != params.end())
9093 {
9194 adjustVolume(static_cast<char*>(buffer_.data()), numFrames);
9295 }
93 fwrite(buffer_.data(), 1, needed, file_.get());
94 fflush(file_.get());
96 if (file_)
97 {
98 fwrite(buffer_.data(), 1, needed, file_.get());
99 fflush(file_.get());
100 }
95101 loop();
96102 }
97103
124130 LOG(INFO, LOG_TAG) << "Stop\n";
125131 timer_.cancel();
126132 }
133
134 } // namespace player
2222 #include <cstdio>
2323 #include <memory>
2424
25 namespace player
26 {
27
28 static constexpr auto FILE = "file";
29
2530 /// File Player
2631 /// Used for testing and doesn't even write the received audio to file at the moment,
2732 /// but just discards it
4146 boost::asio::steady_timer timer_;
4247 std::vector<char> buffer_;
4348 std::chrono::time_point<std::chrono::steady_clock> next_request_;
44 std::shared_ptr<FILE> file_;
49 std::shared_ptr<::FILE> file_;
4550 };
4651
52 } // namespace player
4753
4854 #endif
2424 #include "oboe_player.hpp"
2525
2626 using namespace std;
27
28 namespace player
29 {
2730
2831 static constexpr auto LOG_TAG = "OboePlayer";
2932 static constexpr double kDefaultLatency = 50;
7578 // The builder set methods can be chained for convenience.
7679 oboe::AudioStreamBuilder builder;
7780 auto result = builder.setSharingMode(sharing_mode)
78 ->setPerformanceMode(oboe::PerformanceMode::LowLatency)
81 ->setPerformanceMode(oboe::PerformanceMode::None)
7982 ->setChannelCount(stream_->getFormat().channels())
8083 ->setSampleRate(stream_->getFormat().rate())
8184 ->setFormat(oboe::AudioFormat::I16)
82 ->setCallback(this)
85 ->setDataCallback(this)
86 ->setErrorCallback(this)
8387 ->setDirection(oboe::Direction::Output)
8488 //->setFramesPerCallback((8 * stream->getFormat().rate) / 1000)
8589 //->setFramesPerCallback(2 * oboe::DefaultStreamValues::FramesPerBurst)
199203 if (result != oboe::Result::OK)
200204 LOG(ERROR, LOG_TAG) << "Error in requestStop: " << oboe::convertToText(result) << "\n";
201205 }
206
207 } // namespace player
2323
2424 #include "player.hpp"
2525
26 namespace player
27 {
28
29 static constexpr auto OBOE = "oboe";
2630
2731 /// Android Oboe Audio Player
2832 /**
2933 * Player implementation for Android Oboe
3034 */
31 class OboePlayer : public Player, public oboe::AudioStreamCallback
35 class OboePlayer : public Player, public oboe::AudioStreamDataCallback, public oboe::AudioStreamErrorCallback
3236 {
3337 public:
3438 OboePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream);
3842 void stop() override;
3943
4044 protected:
41 // AudioStreamCallback overrides
45 // AudioStreamDataCallback overrides
4246 oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboeStream, void* audioData, int32_t numFrames) override;
47
48 // AudioStreamErrorCallback overrides
4349 void onErrorBeforeClose(oboe::AudioStream* oboeStream, oboe::Result error) override;
4450 void onErrorAfterClose(oboe::AudioStream* oboeStream, oboe::Result error) override;
4551
5359 std::unique_ptr<oboe::LatencyTuner> mLatencyTuner;
5460 };
5561
62 } // namespace player
5663
5764 #endif
2424 #include "opensl_player.hpp"
2525
2626 using namespace std;
27
28 namespace player
29 {
2730
2831 static constexpr auto LOG_TAG = "OpenSlPlayer";
2932
278281 //// SLint32 streamType = SL_ANDROID_STREAM_VOICE;
279282 result = (*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
280283 throwUnsuccess(kPhaseInit, "PlayerConfig::SetConfiguration", result);
284 // Set the performance mode.
285 SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE;
286 result = (*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(performanceMode));
281287
282288 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
283289 throwUnsuccess(kPhaseInit, "PlayerObject::Realize", result);
374380 (*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue);
375381 throwUnsuccess(kPhaseStop, "PlayerPlay::SetPlayState", result);
376382 }
383
384 } // namespace player
2323 #include <string>
2424
2525 #include "player.hpp"
26
27 namespace player
28 {
29
30 static constexpr auto OPENSL = "opensl";
2631
2732 typedef int (*AndroidAudioCallback)(short* buffer, int num_samples);
2833
7176 std::shared_ptr<Stream> pubStream_;
7277 };
7378
79 } // namespace player
7480
7581 #endif
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 ***/
1717
18 #ifndef PCM_DEVICE_H
19 #define PCM_DEVICE_H
18 #ifndef PCM_DEVICE_HPP
19 #define PCM_DEVICE_HPP
2020
2121 #include <string>
2222
23 namespace player
24 {
25
26 static constexpr char DEFAULT_DEVICE[] = "default";
2327
2428 struct PcmDevice
2529 {
26 PcmDevice() : idx(-1), name("default"){};
30 PcmDevice() : idx(-1), name(DEFAULT_DEVICE){};
2731
2832 PcmDevice(int idx, const std::string& name, const std::string& description = "") : idx(idx), name(name), description(description){};
2933
3236 std::string description;
3337 };
3438
39 } // namespace player
3540
3641 #endif
4040
4141 using namespace std;
4242
43 namespace player
44 {
45
4346 static constexpr auto LOG_TAG = "Player";
4447
4548 Player::Player(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream)
148151 std::ignore = volume;
149152 std::ignore = muted;
150153 throw SnapException("Failed to get hardware mixer volume: not supported");
151 return false;
152154 }
153155
154156
246248 }
247249 }
248250 }
251
252 } // namespace player
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 ***/
1717
18 #ifndef PLAYER_H
19 #define PLAYER_H
18 #ifndef PLAYER_HPP
19 #define PLAYER_HPP
2020
2121 #include "client_settings.hpp"
2222 #include "common/aixlog.hpp"
3131 #include <thread>
3232 #include <vector>
3333
34 namespace player
35 {
3436
3537 /// Audio Player
3638 /**
111113 }
112114 };
113115
116 } // namespace player
114117
115118 #endif
0 /***
1 This file is part of snapcast
2 Copyright (C) 2014-2020 Johannes Pohl
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ***/
17
18 #include <assert.h>
19 #include <iostream>
20
21 #include "common/aixlog.hpp"
22 #include "common/snap_exception.hpp"
23 #include "common/str_compat.hpp"
24 #include "common/utils/string_utils.hpp"
25 #include "pulse_player.hpp"
26
27 using namespace std::chrono_literals;
28 using namespace std;
29
30 namespace player
31 {
32
33 static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms;
34
35 static constexpr auto LOG_TAG = "PulsePlayer";
36
37 // Example code:
38 // https://code.qt.io/cgit/qt/qtmultimedia.git/tree/src/plugins/pulseaudio/qaudioinput_pulse.cpp?h=dev
39 // http://www.videolan.org/developers/vlc/modules/audio_output/pulse.c
40 // https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Clients/Samples/AsyncPlayback/
41
42
43 vector<PcmDevice> PulsePlayer::pcm_list()
44 {
45 auto pa_ml = std::shared_ptr<pa_mainloop>(pa_mainloop_new(), [](pa_mainloop* pa_ml) { pa_mainloop_free(pa_ml); });
46 pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml.get());
47 auto pa_ctx = std::shared_ptr<pa_context>(pa_context_new(pa_mlapi, "Snapcast"), [](pa_context* pa_ctx) {
48 pa_context_disconnect(pa_ctx);
49 pa_context_unref(pa_ctx);
50 });
51 if (pa_context_connect(pa_ctx.get(), nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0)
52 throw SnapException("Failed to connect to PulseAudio context: " + std::string(pa_strerror(pa_context_errno(pa_ctx.get()))));
53
54 static int pa_ready = 0;
55 pa_context_set_state_callback(
56 pa_ctx.get(),
57 [](pa_context* c, void* userdata) {
58 std::ignore = userdata;
59 pa_context_state_t state = pa_context_get_state(c);
60 switch (state)
61 {
62 case PA_CONTEXT_FAILED:
63 case PA_CONTEXT_TERMINATED:
64 pa_ready = 2;
65 break;
66 case PA_CONTEXT_READY:
67 pa_ready = 1;
68 break;
69 default:
70 break;
71 }
72 },
73 nullptr);
74
75 // We can't do anything until PA is ready, so just iterate the mainloop
76 // and continue
77 auto wait_start = std::chrono::steady_clock::now();
78 while (pa_ready == 0)
79 {
80 auto now = std::chrono::steady_clock::now();
81 if (now - wait_start > 5s)
82 throw SnapException("Timeout while waiting for PulseAudio to become ready");
83 if (pa_mainloop_iterate(pa_ml.get(), 1, nullptr) < 0)
84 throw SnapException("Error while waiting for PulseAudio to become ready: " + std::string(pa_strerror(pa_context_errno(pa_ctx.get()))));
85 this_thread::sleep_for(1ms);
86 }
87
88 static std::vector<PcmDevice> devices;
89 auto op = pa_context_get_sink_info_list(
90 pa_ctx.get(),
91 [](pa_context* ctx, const pa_sink_info* i, int eol, void* userdata) mutable {
92 std::ignore = ctx;
93 std::ignore = userdata;
94 // auto self = static_cast<PulsePlayer*>(userdata);
95 // If eol is set to a positive number, you're at the end of the list
96 if (eol <= 0)
97 devices.emplace_back(i->index, i->name, i->description);
98 },
99 nullptr);
100
101 wait_start = std::chrono::steady_clock::now();
102
103 while (pa_operation_get_state(op) != PA_OPERATION_DONE)
104 {
105 if (pa_operation_get_state(op) == PA_OPERATION_CANCELED)
106 throw SnapException("PulseAudio operation canceled");
107
108 auto now = std::chrono::steady_clock::now();
109 if (now - wait_start > 2s)
110 break;
111 pa_mainloop_iterate(pa_ml.get(), 1, nullptr);
112 }
113 int max_idx = -1;
114 for (const auto& device : devices)
115 max_idx = std::max(max_idx, device.idx);
116
117 devices.emplace(devices.begin(), max_idx + 1, DEFAULT_DEVICE, "Let PulseAudio server choose the device");
118 return devices;
119 }
120
121
122 PulsePlayer::PulsePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream)
123 : Player(io_context, settings, stream), latency_(BUFFER_TIME), pa_ml_(nullptr), pa_ctx_(nullptr), playstream_(nullptr)
124 {
125 auto params = utils::string::split_pairs(settings.parameter, ',', '=');
126 if (params.find("buffer_time") != params.end())
127 latency_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10));
128
129 LOG(INFO, LOG_TAG) << "Using buffer_time: " << latency_.count() / 1000 << " ms\n";
130 }
131
132
133 PulsePlayer::~PulsePlayer()
134 {
135 LOG(DEBUG, LOG_TAG) << "Destructor\n";
136 stop();
137 }
138
139
140 bool PulsePlayer::needsThread() const
141 {
142 return true;
143 }
144
145
146 void PulsePlayer::worker()
147 {
148 pa_mainloop_run(pa_ml_, nullptr);
149 }
150
151
152 void PulsePlayer::setHardwareVolume(double volume, bool muted)
153 {
154 last_change_ = std::chrono::steady_clock::now();
155 pa_cvolume cvolume;
156 if (muted)
157 pa_cvolume_set(&cvolume, stream_->getFormat().channels(), PA_VOLUME_MUTED);
158 else
159 pa_cvolume_set(&cvolume, stream_->getFormat().channels(), volume * PA_VOLUME_NORM);
160 pa_context_set_sink_input_volume(pa_ctx_, pa_stream_get_index(playstream_), &cvolume, nullptr, nullptr);
161 }
162
163
164 bool PulsePlayer::getHardwareVolume(double& volume, bool& muted)
165 {
166 // This is called during start to send the initial volume to the server
167 // Because getting the volume works async, we return false here
168 // and instead trigger volume notification in pa_context_subscribe
169 std::ignore = volume;
170 std::ignore = muted;
171 return false;
172 }
173
174
175 void PulsePlayer::triggerVolumeUpdate()
176 {
177 pa_context_get_sink_input_info(
178 pa_ctx_, pa_stream_get_index(playstream_),
179 [](pa_context* ctx, const pa_sink_input_info* info, int eol, void* userdata) {
180 std::ignore = ctx;
181 LOG(DEBUG, LOG_TAG) << "pa_context_get_sink_info_by_index info: " << (info != nullptr) << ", eol: " << eol << "\n";
182 if (info)
183 {
184 auto self = static_cast<PulsePlayer*>(userdata);
185 auto volume = (double)pa_cvolume_avg(&(info->volume)) / (double)PA_VOLUME_NORM;
186 bool muted = (info->mute != 0);
187 LOG(DEBUG, LOG_TAG) << "volume changed: " << volume << ", muted: " << muted << "\n";
188
189 auto now = std::chrono::steady_clock::now();
190 if (now - self->last_change_ < 1s)
191 {
192 LOG(DEBUG, LOG_TAG) << "Last volume change by server: "
193 << std::chrono::duration_cast<std::chrono::milliseconds>(now - self->last_change_).count()
194 << " ms => ignoring volume change\n";
195 return;
196 }
197 self->notifyVolumeChange(volume, muted);
198 }
199 },
200 this);
201 }
202
203
204 void PulsePlayer::subscribeCallback(pa_context* ctx, pa_subscription_event_type_t event_type, uint32_t idx)
205 {
206 std::ignore = ctx;
207 LOG(TRACE, LOG_TAG) << "subscribeCallback, event type: " << event_type << ", idx: " << idx << "\n";
208 unsigned facility = event_type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
209 event_type = static_cast<pa_subscription_event_type_t>(static_cast<int>(event_type) & PA_SUBSCRIPTION_EVENT_TYPE_MASK);
210 if (facility == PA_SUBSCRIPTION_EVENT_SINK_INPUT)
211 {
212 LOG(DEBUG, LOG_TAG) << "event_type: " << event_type << ", facility: " << facility << "\n";
213 if (playstream_ && (idx == pa_stream_get_index(playstream_)))
214 triggerVolumeUpdate();
215 }
216 }
217
218
219 void PulsePlayer::underflowCallback(pa_stream* stream)
220 {
221 // We increase the latency by 50% if we get 6 underflows and latency is under 2s
222 // This is very useful for over the network playback that can't handle low latencies
223 underflows_++;
224 LOG(INFO, LOG_TAG) << "undeflow #" << underflows_ << ", latency: " << latency_.count() / 1000 << " ms\n";
225 if (underflows_ >= 6 && latency_ < 500ms)
226 {
227 latency_ = (latency_ * 3) / 2;
228 bufattr_.maxlength = pa_usec_to_bytes(latency_.count(), &pa_ss_);
229 bufattr_.tlength = pa_usec_to_bytes(latency_.count(), &pa_ss_);
230 pa_stream_set_buffer_attr(stream, &bufattr_, nullptr, nullptr);
231 underflows_ = 0;
232 LOG(INFO, LOG_TAG) << "latency increased to " << latency_.count() / 1000 << " ms\n";
233 }
234 }
235
236
237 void PulsePlayer::stateCallback(pa_context* ctx)
238 {
239 pa_context_state_t state = pa_context_get_state(ctx);
240 string str_state = "unknown";
241 pa_ready_ = 0;
242 switch (state)
243 {
244 // These are just here for reference
245 case PA_CONTEXT_UNCONNECTED:
246 str_state = "unconnected";
247 break;
248 case PA_CONTEXT_CONNECTING:
249 str_state = "connecting";
250 break;
251 case PA_CONTEXT_AUTHORIZING:
252 str_state = "authorizing";
253 break;
254 case PA_CONTEXT_SETTING_NAME:
255 str_state = "setting name";
256 break;
257 default:
258 str_state = "unknown";
259 break;
260 case PA_CONTEXT_FAILED:
261 str_state = "failed";
262 pa_ready_ = 2;
263 break;
264 case PA_CONTEXT_TERMINATED:
265 str_state = "terminated";
266 pa_ready_ = 2;
267 break;
268 case PA_CONTEXT_READY:
269 str_state = "ready";
270 pa_ready_ = 1;
271 break;
272 }
273 LOG(DEBUG, LOG_TAG) << "State changed " << state << ": " << str_state << "\n";
274 }
275
276
277 void PulsePlayer::writeCallback(pa_stream* stream, size_t nbytes)
278 {
279 pa_usec_t usec;
280 int neg;
281 pa_stream_get_latency(stream, &usec, &neg);
282
283 auto numFrames = nbytes / stream_->getFormat().frameSize();
284 if (buffer_.size() < nbytes)
285 buffer_.resize(nbytes);
286 // LOG(TRACE, LOG_TAG) << "writeCallback latency " << usec << " us, frames: " << numFrames << "\n";
287 if (!stream_->getPlayerChunk(buffer_.data(), std::chrono::microseconds(usec), numFrames))
288 {
289 // LOG(INFO, LOG_TAG) << "Failed to get chunk. Playing silence.\n";
290 memset(buffer_.data(), 0, numFrames);
291 }
292 else
293 {
294 adjustVolume(static_cast<char*>(buffer_.data()), numFrames);
295 }
296
297 pa_stream_write(stream, buffer_.data(), nbytes, nullptr, 0LL, PA_SEEK_RELATIVE);
298 }
299
300
301 void PulsePlayer::start()
302 {
303 if (settings_.pcm_device.idx == -1)
304 throw SnapException("Can't open " + settings_.pcm_device.name + ", error: No such device");
305
306 const SampleFormat& format = stream_->getFormat();
307 pa_ss_.rate = format.rate();
308 pa_ss_.channels = format.channels();
309 if (format.bits() == 8)
310 pa_ss_.format = PA_SAMPLE_U8;
311 else if (format.bits() == 16)
312 pa_ss_.format = PA_SAMPLE_S16LE;
313 else if ((format.bits() == 24) && (format.sampleSize() == 3))
314 pa_ss_.format = PA_SAMPLE_S24LE;
315 else if ((format.bits() == 24) && (format.sampleSize() == 4))
316 pa_ss_.format = PA_SAMPLE_S24_32LE;
317 else if (format.bits() == 32)
318 pa_ss_.format = PA_SAMPLE_S32LE;
319 else
320 throw SnapException("Unsupported sample format: " + cpt::to_string(format.bits()));
321
322 // Create a mainloop API and connection to the default server
323 pa_ready_ = 0;
324 pa_ml_ = pa_mainloop_new();
325 pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml_);
326 pa_ctx_ = pa_context_new(pa_mlapi, "Snapcast");
327 if (pa_context_connect(pa_ctx_, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0)
328 throw SnapException("Failed to connect to PulseAudio context: " + std::string(pa_strerror(pa_context_errno(pa_ctx_))));
329
330 // This function defines a callback so the server will tell us it's state.
331 // Our callback will wait for the state to be ready. The callback will
332 // modify the variable to 1 so we know when we have a connection and it's
333 // ready.
334 // If there's an error, the callback will set pa_ready to 2
335 pa_context_set_state_callback(
336 pa_ctx_,
337 [](pa_context* c, void* userdata) {
338 auto self = static_cast<PulsePlayer*>(userdata);
339 self->stateCallback(c);
340 },
341 this);
342
343 // We can't do anything until PA is ready, so just iterate the mainloop
344 // and continue
345 auto wait_start = std::chrono::steady_clock::now();
346 while (pa_ready_ == 0)
347 {
348 auto now = std::chrono::steady_clock::now();
349 if (now - wait_start > 5s)
350 throw SnapException("Timeout while waiting for PulseAudio to become ready");
351 if (pa_mainloop_iterate(pa_ml_, 1, nullptr) < 0)
352 throw SnapException("Error while waiting for PulseAudio to become ready: " + std::string(pa_strerror(pa_context_errno(pa_ctx_))));
353 this_thread::sleep_for(1ms);
354 }
355
356 if (pa_ready_ == 2)
357 throw SnapException("PulseAudio is not ready");
358
359 playstream_ = pa_stream_new(pa_ctx_, "Playback", &pa_ss_, nullptr);
360 if (!playstream_)
361 throw SnapException("Failed to create PulseAudio stream");
362
363 if (settings_.mixer.mode == ClientSettings::Mixer::Mode::hardware)
364 {
365 pa_context_set_subscribe_callback(
366 pa_ctx_,
367 [](pa_context* ctx, pa_subscription_event_type_t event_type, uint32_t idx, void* userdata) {
368 auto self = static_cast<PulsePlayer*>(userdata);
369 self->subscribeCallback(ctx, event_type, idx);
370 },
371 this);
372 const pa_subscription_mask_t mask = static_cast<pa_subscription_mask_t>(PA_SUBSCRIPTION_MASK_SINK_INPUT);
373
374 pa_context_subscribe(
375 pa_ctx_, mask,
376 [](pa_context* ctx, int success, void* userdata) {
377 std::ignore = ctx;
378 if (success)
379 {
380 auto self = static_cast<PulsePlayer*>(userdata);
381 self->triggerVolumeUpdate();
382 }
383 },
384 this);
385 }
386
387 pa_stream_set_write_callback(
388 playstream_,
389 [](pa_stream* stream, size_t length, void* userdata) {
390 auto self = static_cast<PulsePlayer*>(userdata);
391 self->writeCallback(stream, length);
392 },
393 this);
394
395 pa_stream_set_underflow_callback(
396 playstream_,
397 [](pa_stream* stream, void* userdata) {
398 auto self = static_cast<PulsePlayer*>(userdata);
399 self->underflowCallback(stream);
400 },
401 this);
402
403 bufattr_.fragsize = pa_usec_to_bytes(latency_.count(), &pa_ss_);
404 bufattr_.maxlength = pa_usec_to_bytes(latency_.count(), &pa_ss_);
405 bufattr_.minreq = static_cast<uint32_t>(-1);
406 bufattr_.prebuf = static_cast<uint32_t>(-1);
407 bufattr_.tlength = pa_usec_to_bytes(latency_.count(), &pa_ss_);
408
409 const char* device = nullptr;
410 if (settings_.pcm_device.name != DEFAULT_DEVICE)
411 device = settings_.pcm_device.name.c_str();
412
413 int result = pa_stream_connect_playback(
414 playstream_, device, &bufattr_, static_cast<pa_stream_flags>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE),
415 nullptr, nullptr);
416 if (result < 0)
417 {
418 // Old pulse audio servers don't like the ADJUST_LATENCY flag, so retry without that
419 result = pa_stream_connect_playback(playstream_, device, &bufattr_,
420 static_cast<pa_stream_flags>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr);
421 }
422 if (result < 0)
423 throw SnapException("Failed to connect PulseAudio playback stream");
424
425 Player::start();
426 }
427
428
429 void PulsePlayer::stop()
430 {
431 LOG(INFO, LOG_TAG) << "Stop\n";
432 if (pa_ml_)
433 {
434 pa_mainloop_quit(pa_ml_, 0);
435 }
436
437 Player::stop();
438
439 if (pa_ctx_)
440 {
441 pa_context_disconnect(pa_ctx_);
442 pa_context_unref(pa_ctx_);
443 pa_ctx_ = nullptr;
444 }
445
446 if (pa_ml_)
447 {
448 pa_mainloop_free(pa_ml_);
449 pa_ml_ = nullptr;
450 }
451
452 if (playstream_)
453 {
454 pa_stream_set_state_callback(playstream_, nullptr, nullptr);
455 pa_stream_set_read_callback(playstream_, nullptr, nullptr);
456 pa_stream_set_underflow_callback(playstream_, nullptr, nullptr);
457 pa_stream_set_overflow_callback(playstream_, nullptr, nullptr);
458
459 pa_stream_disconnect(playstream_);
460 pa_stream_unref(playstream_);
461 playstream_ = nullptr;
462 }
463 }
464
465 } // namespace player
0 /***
1 This file is part of snapcast
2 Copyright (C) 2014-2020 Johannes Pohl
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ***/
17
18 #ifndef PULSE_PLAYER_HPP
19 #define PULSE_PLAYER_HPP
20
21 #include "player.hpp"
22
23 #include <atomic>
24 #include <cstdio>
25 #include <memory>
26 #include <pulse/pulseaudio.h>
27
28 namespace player
29 {
30
31 static constexpr auto PULSE = "pulse";
32
33 /// File Player
34 /// Used for testing and doesn't even write the received audio to file at the moment,
35 /// but just discards it
36 class PulsePlayer : public Player
37 {
38 public:
39 PulsePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream);
40 virtual ~PulsePlayer();
41
42 void start() override;
43 void stop() override;
44
45 /// List the system's audio output devices
46 static std::vector<PcmDevice> pcm_list();
47
48 protected:
49 bool needsThread() const override;
50 void worker() override;
51
52 bool getHardwareVolume(double& volume, bool& muted) override;
53 void setHardwareVolume(double volume, bool muted) override;
54
55 void triggerVolumeUpdate();
56
57 void underflowCallback(pa_stream* stream);
58 void stateCallback(pa_context* ctx);
59 void writeCallback(pa_stream* stream, size_t nbytes);
60 void subscribeCallback(pa_context* ctx, pa_subscription_event_type_t event_type, uint32_t idx);
61
62 std::vector<char> buffer_;
63
64 std::chrono::microseconds latency_;
65 int underflows_ = 0;
66 std::atomic<int> pa_ready_;
67
68 pa_buffer_attr bufattr_;
69 pa_sample_spec pa_ss_;
70 pa_mainloop* pa_ml_;
71 pa_context* pa_ctx_;
72 pa_stream* playstream_;
73
74 // cache of the last volume change
75 std::chrono::time_point<std::chrono::steady_clock> last_change_;
76 };
77
78 } // namespace player
79
80 #endif
1919 using namespace std::chrono;
2020 using namespace std::chrono_literals;
2121
22 namespace player
23 {
24
2225 static constexpr auto LOG_TAG = "WASAPI";
2326
2427 template <typename T>
101104 CHECK_HR(hr);
102105
103106 desc.idx = idx;
104 desc.name = wstring_convert<codecvt_utf8<wchar_t>, wchar_t>().to_bytes(id);
105 desc.description = wstring_convert<codecvt_utf8<wchar_t>, wchar_t>().to_bytes(deviceName.pwszVal);
107
108 using converter = wstring_convert<codecvt_utf8_utf16<wchar_t>, wchar_t>;
109 desc.name = converter{}.to_bytes(id);
110 desc.description = converter{}.to_bytes(deviceName.pwszVal);
106111
107112 CoTaskMemFree(id);
108113
139144 CHECK_HR(hr);
140145
141146 auto dev = convertToDevice(0, defaultDevice);
142 dev.name = "default";
147 dev.name = DEFAULT_DEVICE;
143148 deviceList.push_back(dev);
144149 }
145150
155160 return deviceList;
156161 }
157162
163 #pragma warning(push)
164 #pragma warning(disable : 4127)
158165 void WASAPIPlayer::worker()
159166 {
160167 assert(sizeof(char) == sizeof(BYTE));
395402 }
396403 }
397404 }
405 #pragma warning(pop)
398406
399407 HRESULT STDMETHODCALLTYPE AudioSessionEventListener::QueryInterface(REFIID riid, VOID** ppvInterface)
400408 {
418426
419427 HRESULT STDMETHODCALLTYPE AudioSessionEventListener::OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext)
420428 {
429 std::ignore = EventContext;
421430 volume_ = NewVolume;
422431 muted_ = NewMute;
423432
501510 muted_ = pNotify->bMuted;
502511
503512 return S_OK;
504 }
513 }
514
515 } // namespace player
1818 #ifndef WASAPI_PLAYER_HPP
1919 #define WASAPI_PLAYER_HPP
2020
21 #pragma warning(push)
22 #pragma warning(disable : 4100)
23
2124 #include "player.hpp"
2225 #include <audiopolicy.h>
2326 #include <endpointvolume.h>
2427
28 namespace player
29 {
30
2531 class AudioSessionEventListener : public IAudioSessionEvents
2632 {
2733 LONG _cRef;
165171 HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify);
166172 };
167173
174 static constexpr auto WASAPI = "wasapi";
175
168176 class WASAPIPlayer : public Player
169177 {
170178 public:
171179 WASAPIPlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream);
172180 virtual ~WASAPIPlayer();
173181
174 static std::vector<PcmDevice> pcm_list(void);
182 static std::vector<PcmDevice> pcm_list();
175183
176184 protected:
177185 virtual void worker();
186194 ClientSettings::SharingMode mode_;
187195 };
188196
197 #pragma warning(pop)
198
199 } // namespace player
200
189201 #endif
2828 #ifdef HAS_ALSA
2929 #include "player/alsa_player.hpp"
3030 #endif
31 #ifdef HAS_PULSE
32 #include "player/pulse_player.hpp"
33 #endif
3134 #ifdef HAS_WASAPI
3235 #include "player/wasapi_player.hpp"
3336 #endif
37 #include "player/file_player.hpp"
3438 #ifdef HAS_DAEMON
3539 #include "common/daemon.hpp"
3640 #endif
4448
4549 using namespace std;
4650 using namespace popl;
51 using namespace player;
4752
4853 using namespace std::chrono_literals;
4954
5055 static constexpr auto LOG_TAG = "Snapclient";
5156
52 PcmDevice getPcmDevice(const std::string& soundcard)
57 PcmDevice getPcmDevice(const std::string& player, const std::string& soundcard)
5358 {
54 #if defined(HAS_ALSA) || defined(HAS_WASAPI)
55 vector<PcmDevice> pcmDevices =
56 #ifdef HAS_ALSA
57 AlsaPlayer::pcm_list();
58 #else
59 WASAPIPlayer::pcm_list();
60 #endif
61
59 #if defined(HAS_ALSA) || defined(HAS_PULSE) || defined(HAS_WASAPI)
60 vector<PcmDevice> pcm_devices;
61 #if defined(HAS_ALSA)
62 if (player == player::ALSA)
63 pcm_devices = AlsaPlayer::pcm_list();
64 #endif
65 #if defined(HAS_PULSE)
66 if (player == player::PULSE)
67 pcm_devices = PulsePlayer::pcm_list();
68 #endif
69 #if defined(HAS_WASAPI)
70 if (player == player::WASAPI)
71 pcm_devices = WASAPIPlayer::pcm_list();
72 #endif
6273 try
6374 {
6475 int soundcardIdx = cpt::stoi(soundcard);
65 for (auto dev : pcmDevices)
76 for (auto dev : pcm_devices)
6677 if (dev.idx == soundcardIdx)
6778 return dev;
6879 }
7081 {
7182 }
7283
73 for (auto dev : pcmDevices)
84 for (auto dev : pcm_devices)
7485 if (dev.name.find(soundcard) != string::npos)
7586 return dev;
76 std::ignore = soundcard;
77 #endif
78
79 PcmDevice pcmDevice;
80 pcmDevice.name = soundcard;
81 return pcmDevice;
87 #endif
88 std::ignore = player;
89 PcmDevice pcm_device;
90 pcm_device.name = soundcard;
91 return pcm_device;
8292 }
8393
8494 #ifdef WINDOWS
112122 {
113123 string meta_script("");
114124 ClientSettings settings;
115 string pcm_device("default");
125 string pcm_device(player::DEFAULT_DEVICE);
116126
117127 OptionParser op("Allowed options");
118128 auto helpSwitch = op.add<Switch>("", "help", "produce help message");
124134 op.add<Value<string>>("", "hostID", "unique host id, default is MAC address", "", &settings.host_id);
125135
126136 // PCM device specific
127 #if defined(HAS_ALSA) || defined(HAS_WASAPI)
137 #if defined(HAS_ALSA) || defined(HAS_PULSE) || defined(HAS_WASAPI)
128138 auto listSwitch = op.add<Switch>("l", "list", "list PCM devices");
129 /*auto soundcardValue =*/op.add<Value<string>>("s", "soundcard", "index or name of the pcm device", "default", &pcm_device);
139 /*auto soundcardValue =*/op.add<Value<string>>("s", "soundcard", "index or name of the pcm device", pcm_device, &pcm_device);
130140 #endif
131141 /*auto latencyValue =*/op.add<Value<int>>("", "latency", "latency of the PCM device", 0, &settings.player.latency);
132142 #ifdef HAS_SOXR
192202 exit(EXIT_SUCCESS);
193203 }
194204
195 #if defined(HAS_ALSA) || defined(HAS_WASAPI)
205 settings.player.player_name = utils::string::split_left(settings.player.player_name, ':', settings.player.parameter);
206
207 #if defined(HAS_ALSA) || defined(HAS_PULSE) || defined(HAS_WASAPI)
196208 if (listSwitch->is_set())
197209 {
198 vector<PcmDevice> pcmDevices =
199 #ifdef HAS_ALSA
200 AlsaPlayer::pcm_list();
201 #else
202 WASAPIPlayer::pcm_list();
203 #endif
204 for (auto dev : pcmDevices)
205 {
210 vector<PcmDevice> pcm_devices;
211 #if defined(HAS_ALSA)
212 if (settings.player.player_name == player::ALSA)
213 pcm_devices = AlsaPlayer::pcm_list();
214 #endif
215 #if defined(HAS_PULSE)
216 if (settings.player.player_name == player::PULSE)
217 pcm_devices = PulsePlayer::pcm_list();
218 #endif
219 #if defined(HAS_WASAPI)
220 if (settings.player.player_name == player::WASAPI)
221 pcm_devices = WASAPIPlayer::pcm_list();
222 #endif
223 #ifdef WINDOWS
224 // Set console code page to UTF-8 so console known how to interpret string data
225 SetConsoleOutputCP(CP_UTF8);
226 // Enable buffering to prevent VS from chopping up UTF-8 byte sequences
227 setvbuf(stdout, nullptr, _IOFBF, 1000);
228 #endif
229 for (const auto& dev : pcm_devices)
206230 cout << dev.idx << ": " << dev.name << "\n" << dev.description << "\n\n";
207 }
231
232 if (pcm_devices.empty())
233 cout << "No PCM device available for audio backend \"" << settings.player.player_name << "\"\n";
208234 exit(EXIT_SUCCESS);
209235 }
210236 #endif
260286 AixLog::Log::init<AixLog::SinkNull>();
261287 else
262288 throw SnapException("Invalid log sink: " + settings.logging.sink);
289
290 #if !defined(HAS_AVAHI) && !defined(HAS_BONJOUR)
291 if (settings.server.host.empty())
292 throw SnapException("Snapserver host not configured and mDNS not available, please configure with \"--host\".");
293 #endif
294
263295
264296 #ifdef HAS_DAEMON
265297 std::unique_ptr<Daemon> daemon;
291323 }
292324 #endif
293325
294 settings.player.pcm_device = getPcmDevice(pcm_device);
326 settings.player.pcm_device = getPcmDevice(settings.player.player_name, pcm_device);
295327 #if defined(HAS_ALSA)
296328 if (settings.player.pcm_device.idx == -1)
297329 {
316348 settings.player.sharing_mode = (sharing_mode->value() == "exclusive") ? ClientSettings::SharingMode::exclusive : ClientSettings::SharingMode::shared;
317349 #endif
318350
319 settings.player.player_name = utils::string::split_left(settings.player.player_name, ':', settings.player.parameter);
320351 if (settings.player.parameter == "?")
321352 {
322 if (settings.player.player_name == "file")
353 if (settings.player.player_name == player::FILE)
323354 {
324355 cout << "Options are a comma separated list of:\n"
325 << " \"filename:<filename>\" - with <filename> = \"stdout\", \"stderr\" or a filename\n"
326 << " \"mode:[w|a]\" - w: write (discarding the content), a: append (keeping the content)\n";
356 << " \"filename=<filename>\" - with <filename> = \"stdout\", \"stderr\", \"null\" or a filename\n"
357 << " \"mode=[w|a]\" - w: write (discarding the content), a: append (keeping the content)\n";
327358 }
359 #ifdef HAS_PULSE
360 else if (settings.player.player_name == player::PULSE)
361 {
362 cout << "Options are a comma separated list of:\n"
363 << " \"buffer_time=<buffer size [ms]>\" - default 80, min 10\n";
364 }
365 #endif
366 #ifdef HAS_ALSA
367 else if (settings.player.player_name == player::ALSA)
368 {
369 cout << "Options are a comma separated list of:\n"
370 << " \"buffer_time=<total buffer size [ms]>\" - default 80, min 10\n"
371 << " \"fragments=<number of buffers>\" - default 4, min 2\n";
372 }
373 #endif
328374 else
329375 {
330376 cout << "No options available for \"" << settings.player.player_name << "\n";
382428 exitcode = EXIT_FAILURE;
383429 }
384430
385 LOG(NOTICE, LOG_TAG) << "daemon terminated." << endl;
431 LOG(NOTICE, LOG_TAG) << "Snapclient terminated." << endl;
386432 exit(exitcode);
387433 }
2121
2222 #include "stream.hpp"
2323 #include "common/aixlog.hpp"
24 #include "common/snap_exception.hpp"
25 #include "common/str_compat.hpp"
2426 #include "time_provider.hpp"
2527 #include <cmath>
2628 #include <iostream>
114116 std::shared_ptr<msg::PcmChunk> front_;
115117 while (chunks_.front_copy(front_))
116118 {
117 auto age = std::chrono::duration_cast<cs::msec>(TimeProvider::serverNow() - front_->start());
119 age = std::chrono::duration_cast<cs::msec>(TimeProvider::serverNow() - front_->start());
118120 if ((age > 5s + bufferMs_) && chunks_.try_pop(front_))
119121 LOG(TRACE, LOG_TAG) << "Oldest chunk too old: " << age.count() << " ms, removing. Chunks in queue left: " << chunks_.size() << "\n";
120122 else
140142 cs::time_point_clk Stream::getNextPlayerChunk(void* outputBuffer, uint32_t frames)
141143 {
142144 if (!chunk_ && !chunks_.try_pop(chunk_))
143 throw 0;
145 throw SnapException("No chunks available, requested frames: " + cpt::to_string(frames));
144146
145147 cs::time_point_clk tp = chunk_->start();
146148 uint32_t read = 0;
147149 while (read < frames)
148150 {
149151 read += chunk_->readFrames(static_cast<char*>(outputBuffer) + read * format_.frameSize(), frames - read);
150 if (chunk_->isEndOfChunk() && !chunks_.try_pop(chunk_))
151 throw 0;
152 if ((read < frames) && chunk_->isEndOfChunk() && !chunks_.try_pop(chunk_))
153 throw SnapException("Not enough frames available, requested frames: " + cpt::to_string(frames) + ", available: " + cpt::to_string(read));
152154 }
153155 return tp;
154156 }
251253 if (now != lastUpdate_)
252254 {
253255 lastUpdate_ = now;
254 LOG(INFO, LOG_TAG) << "no chunks available\n";
256 LOG(INFO, LOG_TAG) << "No chunks available\n";
255257 }
256258 return false;
257259 }
431433 }
432434 return (abs(cs::duration<cs::msec>(age)) < 500);
433435 }
434 catch (int e)
435 {
436 LOG(INFO, LOG_TAG) << "Exception: " << e << "\n";
436 catch (const std::exception& e)
437 {
438 LOG(INFO, LOG_TAG) << "Exception: " << e.what() << "\n";
437439 hard_sync_ = true;
438440 return false;
439441 }
11 resampler.cpp
22 sample_format.cpp)
33
4 if(NOT WIN32)
4 if(NOT WIN32 AND NOT ANDROID)
55 list(APPEND SOURCES daemon.cpp)
66 endif()
77
1111
1212 add_library(common STATIC ${SOURCES})
1313
14 if (SOXR_FOUND)
14 if (ANDROID)
15 target_link_libraries(common soxr::soxr)
16 elseif(SOXR_FOUND)
1517 target_link_libraries(common ${SOXR_LIBRARIES})
16 endif (SOXR_FOUND)
18 endif()
177177
178178 static Severity to_severity(std::string severity, Severity def = Severity::info)
179179 {
180 std::transform(severity.begin(), severity.end(), severity.begin(), [](unsigned char c) { return std::tolower(c); });
180 std::transform(severity.begin(), severity.end(), severity.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
181181 if (severity == "trace")
182182 return Severity::trace;
183183 else if (severity == "debug")
840840 {
841841 }
842842
843 void log(const Metadata& metadata, const std::string& message) override
843 void log(const Metadata& /*metadata*/, const std::string& message) override
844844 {
845845 std::wstring wide = std::wstring(message.begin(), message.end());
846846 OutputDebugString(wide.c_str());
4141 {
4242 return SWAP_64(val);
4343 }
44 }
44 } // namespace endian
4545
4646 #endif
00 /*
11 __ _____ _____ _____
22 __| | __| | | | JSON for Modern C++
3 | | |__ | | | | | | version 3.1.2
3 | | |__ | | | | | | version 3.9.1
44 |_____|_____|_____|_|___| https://github.com/nlohmann/json
55
66 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
7 Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
7 SPDX-License-Identifier: MIT
8 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
89
910 Permission is hereby granted, free of charge, to any person obtaining a copy
1011 of this software and associated documentation files (the "Software"), to deal
2526 SOFTWARE.
2627 */
2728
28 #ifndef NLOHMANN_JSON_HPP
29 #define NLOHMANN_JSON_HPP
29 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
30 #define INCLUDE_NLOHMANN_JSON_HPP_
3031
3132 #define NLOHMANN_JSON_VERSION_MAJOR 3
32 #define NLOHMANN_JSON_VERSION_MINOR 1
33 #define NLOHMANN_JSON_VERSION_PATCH 2
34
35 #include <algorithm> // all_of, find, for_each
36 #include <cassert> // assert
37 #include <ciso646> // and, not, or
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <functional> // hash, less
33 #define NLOHMANN_JSON_VERSION_MINOR 9
34 #define NLOHMANN_JSON_VERSION_PATCH 1
35
36 #include <algorithm> // all_of, find, for_each
37 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
38 #include <functional> // hash, less
4039 #include <initializer_list> // initializer_list
41 #include <iosfwd> // istream, ostream
42 #include <iterator> // iterator_traits, random_access_iterator_tag
43 #include <numeric> // accumulate
44 #include <string> // string, stoi, to_string
45 #include <utility> // declval, forward, move, pair, swap
40 #include <iosfwd> // istream, ostream
41 #include <iterator> // random_access_iterator_tag
42 #include <memory> // unique_ptr
43 #include <numeric> // accumulate
44 #include <string> // string, stoi, to_string
45 #include <utility> // declval, forward, move, pair, swap
46 #include <vector> // vector
47
48 // #include <nlohmann/adl_serializer.hpp>
49
50
51 #include <utility>
52
53 // #include <nlohmann/detail/conversions/from_json.hpp>
54
55
56 #include <algorithm> // transform
57 #include <array> // array
58 #include <forward_list> // forward_list
59 #include <iterator> // inserter, front_inserter, end
60 #include <map> // map
61 #include <string> // string
62 #include <tuple> // tuple, make_tuple
63 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
64 #include <unordered_map> // unordered_map
65 #include <utility> // pair, declval
66 #include <valarray> // valarray
67
68 // #include <nlohmann/detail/exceptions.hpp>
69
70
71 #include <exception> // exception
72 #include <stdexcept> // runtime_error
73 #include <string> // to_string
74
75 // #include <nlohmann/detail/input/position_t.hpp>
76
77
78 #include <cstddef> // size_t
79
80 namespace nlohmann
81 {
82 namespace detail
83 {
84 /// struct to capture the start position of the current token
85 struct position_t
86 {
87 /// the total number of characters read
88 std::size_t chars_read_total = 0;
89 /// the number of characters read in the current line
90 std::size_t chars_read_current_line = 0;
91 /// the number of lines read
92 std::size_t lines_read = 0;
93
94 /// conversion to size_t to preserve SAX interface
95 constexpr operator size_t() const
96 {
97 return chars_read_total;
98 }
99 };
100
101 } // namespace detail
102 } // namespace nlohmann
103
104 // #include <nlohmann/detail/macro_scope.hpp>
105
106
107 #include <utility> // pair
108 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
109 /* Hedley - https://nemequ.github.io/hedley
110 * Created by Evan Nemerson <evan@nemerson.com>
111 *
112 * To the extent possible under law, the author(s) have dedicated all
113 * copyright and related and neighboring rights to this software to
114 * the public domain worldwide. This software is distributed without
115 * any warranty.
116 *
117 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
118 * SPDX-License-Identifier: CC0-1.0
119 */
120
121 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 13)
122 #if defined(JSON_HEDLEY_VERSION)
123 #undef JSON_HEDLEY_VERSION
124 #endif
125 #define JSON_HEDLEY_VERSION 13
126
127 #if defined(JSON_HEDLEY_STRINGIFY_EX)
128 #undef JSON_HEDLEY_STRINGIFY_EX
129 #endif
130 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
131
132 #if defined(JSON_HEDLEY_STRINGIFY)
133 #undef JSON_HEDLEY_STRINGIFY
134 #endif
135 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
136
137 #if defined(JSON_HEDLEY_CONCAT_EX)
138 #undef JSON_HEDLEY_CONCAT_EX
139 #endif
140 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
141
142 #if defined(JSON_HEDLEY_CONCAT)
143 #undef JSON_HEDLEY_CONCAT
144 #endif
145 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
146
147 #if defined(JSON_HEDLEY_CONCAT3_EX)
148 #undef JSON_HEDLEY_CONCAT3_EX
149 #endif
150 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
151
152 #if defined(JSON_HEDLEY_CONCAT3)
153 #undef JSON_HEDLEY_CONCAT3
154 #endif
155 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
156
157 #if defined(JSON_HEDLEY_VERSION_ENCODE)
158 #undef JSON_HEDLEY_VERSION_ENCODE
159 #endif
160 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
161
162 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
163 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
164 #endif
165 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
166
167 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
168 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
169 #endif
170 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
171
172 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
173 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
174 #endif
175 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
176
177 #if defined(JSON_HEDLEY_GNUC_VERSION)
178 #undef JSON_HEDLEY_GNUC_VERSION
179 #endif
180 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
181 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
182 #elif defined(__GNUC__)
183 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
184 #endif
185
186 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
187 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
188 #endif
189 #if defined(JSON_HEDLEY_GNUC_VERSION)
190 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
191 #else
192 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
193 #endif
194
195 #if defined(JSON_HEDLEY_MSVC_VERSION)
196 #undef JSON_HEDLEY_MSVC_VERSION
197 #endif
198 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
199 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
200 #elif defined(_MSC_FULL_VER)
201 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
202 #elif defined(_MSC_VER)
203 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
204 #endif
205
206 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
207 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
208 #endif
209 #if !defined(_MSC_VER)
210 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
211 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
212 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
213 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
214 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
215 #else
216 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
217 #endif
218
219 #if defined(JSON_HEDLEY_INTEL_VERSION)
220 #undef JSON_HEDLEY_INTEL_VERSION
221 #endif
222 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
223 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
224 #elif defined(__INTEL_COMPILER)
225 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
226 #endif
227
228 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
229 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
230 #endif
231 #if defined(JSON_HEDLEY_INTEL_VERSION)
232 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
233 #else
234 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
235 #endif
236
237 #if defined(JSON_HEDLEY_PGI_VERSION)
238 #undef JSON_HEDLEY_PGI_VERSION
239 #endif
240 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
241 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
242 #endif
243
244 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
245 #undef JSON_HEDLEY_PGI_VERSION_CHECK
246 #endif
247 #if defined(JSON_HEDLEY_PGI_VERSION)
248 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
249 #else
250 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
251 #endif
252
253 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
254 #undef JSON_HEDLEY_SUNPRO_VERSION
255 #endif
256 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
257 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
258 #elif defined(__SUNPRO_C)
259 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
260 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
261 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
262 #elif defined(__SUNPRO_CC)
263 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
264 #endif
265
266 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
267 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
268 #endif
269 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
270 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
271 #else
272 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
273 #endif
274
275 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
276 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
277 #endif
278 #if defined(__EMSCRIPTEN__)
279 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
280 #endif
281
282 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
283 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
284 #endif
285 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
286 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
287 #else
288 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
289 #endif
290
291 #if defined(JSON_HEDLEY_ARM_VERSION)
292 #undef JSON_HEDLEY_ARM_VERSION
293 #endif
294 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
295 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
296 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
297 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
298 #endif
299
300 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
301 #undef JSON_HEDLEY_ARM_VERSION_CHECK
302 #endif
303 #if defined(JSON_HEDLEY_ARM_VERSION)
304 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
305 #else
306 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
307 #endif
308
309 #if defined(JSON_HEDLEY_IBM_VERSION)
310 #undef JSON_HEDLEY_IBM_VERSION
311 #endif
312 #if defined(__ibmxl__)
313 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
314 #elif defined(__xlC__) && defined(__xlC_ver__)
315 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
316 #elif defined(__xlC__)
317 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
318 #endif
319
320 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
321 #undef JSON_HEDLEY_IBM_VERSION_CHECK
322 #endif
323 #if defined(JSON_HEDLEY_IBM_VERSION)
324 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
325 #else
326 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
327 #endif
328
329 #if defined(JSON_HEDLEY_TI_VERSION)
330 #undef JSON_HEDLEY_TI_VERSION
331 #endif
332 #if \
333 defined(__TI_COMPILER_VERSION__) && \
334 ( \
335 defined(__TMS470__) || defined(__TI_ARM__) || \
336 defined(__MSP430__) || \
337 defined(__TMS320C2000__) \
338 )
339 #if (__TI_COMPILER_VERSION__ >= 16000000)
340 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
341 #endif
342 #endif
343
344 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
345 #undef JSON_HEDLEY_TI_VERSION_CHECK
346 #endif
347 #if defined(JSON_HEDLEY_TI_VERSION)
348 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
349 #else
350 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
351 #endif
352
353 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
354 #undef JSON_HEDLEY_TI_CL2000_VERSION
355 #endif
356 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
357 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
358 #endif
359
360 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
361 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
362 #endif
363 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
364 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
365 #else
366 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
367 #endif
368
369 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
370 #undef JSON_HEDLEY_TI_CL430_VERSION
371 #endif
372 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
373 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
374 #endif
375
376 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
377 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
378 #endif
379 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
380 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
381 #else
382 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
383 #endif
384
385 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
386 #undef JSON_HEDLEY_TI_ARMCL_VERSION
387 #endif
388 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
389 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
390 #endif
391
392 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
393 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
394 #endif
395 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
396 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
397 #else
398 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
399 #endif
400
401 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
402 #undef JSON_HEDLEY_TI_CL6X_VERSION
403 #endif
404 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
405 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
406 #endif
407
408 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
409 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
410 #endif
411 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
412 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
413 #else
414 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
415 #endif
416
417 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
418 #undef JSON_HEDLEY_TI_CL7X_VERSION
419 #endif
420 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
421 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
422 #endif
423
424 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
425 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
426 #endif
427 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
428 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
429 #else
430 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
431 #endif
432
433 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
434 #undef JSON_HEDLEY_TI_CLPRU_VERSION
435 #endif
436 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
437 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
438 #endif
439
440 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
441 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
442 #endif
443 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
444 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
445 #else
446 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
447 #endif
448
449 #if defined(JSON_HEDLEY_CRAY_VERSION)
450 #undef JSON_HEDLEY_CRAY_VERSION
451 #endif
452 #if defined(_CRAYC)
453 #if defined(_RELEASE_PATCHLEVEL)
454 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
455 #else
456 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
457 #endif
458 #endif
459
460 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
461 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
462 #endif
463 #if defined(JSON_HEDLEY_CRAY_VERSION)
464 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
465 #else
466 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
467 #endif
468
469 #if defined(JSON_HEDLEY_IAR_VERSION)
470 #undef JSON_HEDLEY_IAR_VERSION
471 #endif
472 #if defined(__IAR_SYSTEMS_ICC__)
473 #if __VER__ > 1000
474 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
475 #else
476 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0)
477 #endif
478 #endif
479
480 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
481 #undef JSON_HEDLEY_IAR_VERSION_CHECK
482 #endif
483 #if defined(JSON_HEDLEY_IAR_VERSION)
484 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
485 #else
486 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
487 #endif
488
489 #if defined(JSON_HEDLEY_TINYC_VERSION)
490 #undef JSON_HEDLEY_TINYC_VERSION
491 #endif
492 #if defined(__TINYC__)
493 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
494 #endif
495
496 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
497 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
498 #endif
499 #if defined(JSON_HEDLEY_TINYC_VERSION)
500 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
501 #else
502 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
503 #endif
504
505 #if defined(JSON_HEDLEY_DMC_VERSION)
506 #undef JSON_HEDLEY_DMC_VERSION
507 #endif
508 #if defined(__DMC__)
509 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
510 #endif
511
512 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
513 #undef JSON_HEDLEY_DMC_VERSION_CHECK
514 #endif
515 #if defined(JSON_HEDLEY_DMC_VERSION)
516 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
517 #else
518 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
519 #endif
520
521 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
522 #undef JSON_HEDLEY_COMPCERT_VERSION
523 #endif
524 #if defined(__COMPCERT_VERSION__)
525 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
526 #endif
527
528 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
529 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
530 #endif
531 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
532 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
533 #else
534 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
535 #endif
536
537 #if defined(JSON_HEDLEY_PELLES_VERSION)
538 #undef JSON_HEDLEY_PELLES_VERSION
539 #endif
540 #if defined(__POCC__)
541 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
542 #endif
543
544 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
545 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
546 #endif
547 #if defined(JSON_HEDLEY_PELLES_VERSION)
548 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
549 #else
550 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
551 #endif
552
553 #if defined(JSON_HEDLEY_GCC_VERSION)
554 #undef JSON_HEDLEY_GCC_VERSION
555 #endif
556 #if \
557 defined(JSON_HEDLEY_GNUC_VERSION) && \
558 !defined(__clang__) && \
559 !defined(JSON_HEDLEY_INTEL_VERSION) && \
560 !defined(JSON_HEDLEY_PGI_VERSION) && \
561 !defined(JSON_HEDLEY_ARM_VERSION) && \
562 !defined(JSON_HEDLEY_TI_VERSION) && \
563 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
564 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
565 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
566 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
567 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
568 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
569 !defined(__COMPCERT__)
570 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
571 #endif
572
573 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
574 #undef JSON_HEDLEY_GCC_VERSION_CHECK
575 #endif
576 #if defined(JSON_HEDLEY_GCC_VERSION)
577 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578 #else
579 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
580 #endif
581
582 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
583 #undef JSON_HEDLEY_HAS_ATTRIBUTE
584 #endif
585 #if defined(__has_attribute)
586 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
587 #else
588 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
589 #endif
590
591 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
592 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
593 #endif
594 #if defined(__has_attribute)
595 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
596 #else
597 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
598 #endif
599
600 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
601 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
602 #endif
603 #if defined(__has_attribute)
604 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
605 #else
606 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
607 #endif
608
609 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
610 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
611 #endif
612 #if \
613 defined(__has_cpp_attribute) && \
614 defined(__cplusplus) && \
615 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
616 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
617 #else
618 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
619 #endif
620
621 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
622 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
623 #endif
624 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
625 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
626 #elif \
627 !defined(JSON_HEDLEY_PGI_VERSION) && \
628 !defined(JSON_HEDLEY_IAR_VERSION) && \
629 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
630 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
631 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
632 #else
633 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
634 #endif
635
636 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
637 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
638 #endif
639 #if defined(__has_cpp_attribute) && defined(__cplusplus)
640 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
641 #else
642 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
643 #endif
644
645 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
646 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
647 #endif
648 #if defined(__has_cpp_attribute) && defined(__cplusplus)
649 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
650 #else
651 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
652 #endif
653
654 #if defined(JSON_HEDLEY_HAS_BUILTIN)
655 #undef JSON_HEDLEY_HAS_BUILTIN
656 #endif
657 #if defined(__has_builtin)
658 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
659 #else
660 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
661 #endif
662
663 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
664 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
665 #endif
666 #if defined(__has_builtin)
667 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
668 #else
669 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
670 #endif
671
672 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
673 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
674 #endif
675 #if defined(__has_builtin)
676 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
677 #else
678 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
679 #endif
680
681 #if defined(JSON_HEDLEY_HAS_FEATURE)
682 #undef JSON_HEDLEY_HAS_FEATURE
683 #endif
684 #if defined(__has_feature)
685 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
686 #else
687 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
688 #endif
689
690 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
691 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
692 #endif
693 #if defined(__has_feature)
694 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
695 #else
696 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
697 #endif
698
699 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
700 #undef JSON_HEDLEY_GCC_HAS_FEATURE
701 #endif
702 #if defined(__has_feature)
703 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
704 #else
705 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
706 #endif
707
708 #if defined(JSON_HEDLEY_HAS_EXTENSION)
709 #undef JSON_HEDLEY_HAS_EXTENSION
710 #endif
711 #if defined(__has_extension)
712 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
713 #else
714 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
715 #endif
716
717 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
718 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
719 #endif
720 #if defined(__has_extension)
721 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
722 #else
723 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
724 #endif
725
726 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
727 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
728 #endif
729 #if defined(__has_extension)
730 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
731 #else
732 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
733 #endif
734
735 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
736 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
737 #endif
738 #if defined(__has_declspec_attribute)
739 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
740 #else
741 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
742 #endif
743
744 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
745 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
746 #endif
747 #if defined(__has_declspec_attribute)
748 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
749 #else
750 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
751 #endif
752
753 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
754 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
755 #endif
756 #if defined(__has_declspec_attribute)
757 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
758 #else
759 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
760 #endif
761
762 #if defined(JSON_HEDLEY_HAS_WARNING)
763 #undef JSON_HEDLEY_HAS_WARNING
764 #endif
765 #if defined(__has_warning)
766 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
767 #else
768 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
769 #endif
770
771 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
772 #undef JSON_HEDLEY_GNUC_HAS_WARNING
773 #endif
774 #if defined(__has_warning)
775 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
776 #else
777 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
778 #endif
779
780 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
781 #undef JSON_HEDLEY_GCC_HAS_WARNING
782 #endif
783 #if defined(__has_warning)
784 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
785 #else
786 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
787 #endif
788
789 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
790 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
791 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
792 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
793 #endif
794 #if defined(__cplusplus)
795 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
796 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
797 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
798 JSON_HEDLEY_DIAGNOSTIC_PUSH \
799 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
800 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
801 xpr \
802 JSON_HEDLEY_DIAGNOSTIC_POP
803 # else
804 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
805 JSON_HEDLEY_DIAGNOSTIC_PUSH \
806 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
807 xpr \
808 JSON_HEDLEY_DIAGNOSTIC_POP
809 # endif
810 # endif
811 #endif
812 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
813 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
814 #endif
815
816 #if defined(JSON_HEDLEY_CONST_CAST)
817 #undef JSON_HEDLEY_CONST_CAST
818 #endif
819 #if defined(__cplusplus)
820 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
821 #elif \
822 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
823 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
824 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
825 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
826 JSON_HEDLEY_DIAGNOSTIC_PUSH \
827 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
828 ((T) (expr)); \
829 JSON_HEDLEY_DIAGNOSTIC_POP \
830 }))
831 #else
832 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
833 #endif
834
835 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
836 #undef JSON_HEDLEY_REINTERPRET_CAST
837 #endif
838 #if defined(__cplusplus)
839 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
840 #else
841 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
842 #endif
843
844 #if defined(JSON_HEDLEY_STATIC_CAST)
845 #undef JSON_HEDLEY_STATIC_CAST
846 #endif
847 #if defined(__cplusplus)
848 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
849 #else
850 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
851 #endif
852
853 #if defined(JSON_HEDLEY_CPP_CAST)
854 #undef JSON_HEDLEY_CPP_CAST
855 #endif
856 #if defined(__cplusplus)
857 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
858 # define JSON_HEDLEY_CPP_CAST(T, expr) \
859 JSON_HEDLEY_DIAGNOSTIC_PUSH \
860 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
861 ((T) (expr)) \
862 JSON_HEDLEY_DIAGNOSTIC_POP
863 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
864 # define JSON_HEDLEY_CPP_CAST(T, expr) \
865 JSON_HEDLEY_DIAGNOSTIC_PUSH \
866 _Pragma("diag_suppress=Pe137") \
867 JSON_HEDLEY_DIAGNOSTIC_POP \
868 # else
869 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
870 # endif
871 #else
872 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
873 #endif
874
875 #if \
876 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
877 defined(__clang__) || \
878 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
879 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
880 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
881 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
882 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
883 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
884 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
885 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
886 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
887 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
888 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
889 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
890 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
891 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
892 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
893 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
894 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
895 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
896 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
897 #else
898 #define JSON_HEDLEY_PRAGMA(value)
899 #endif
900
901 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
902 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
903 #endif
904 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
905 #undef JSON_HEDLEY_DIAGNOSTIC_POP
906 #endif
907 #if defined(__clang__)
908 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
909 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
910 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
911 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
912 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
913 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
914 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
915 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
916 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
917 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
918 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
919 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
920 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
921 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
922 #elif \
923 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
924 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
925 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
926 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
927 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
928 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
929 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
930 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
931 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
932 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
933 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
934 #else
935 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
936 #define JSON_HEDLEY_DIAGNOSTIC_POP
937 #endif
938
939 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
940 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
941 #endif
942 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
943 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
944 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
945 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
946 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
947 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
948 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
949 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
950 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
951 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
952 #elif \
953 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
954 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
955 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
956 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
957 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
958 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
959 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
960 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
961 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
962 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
963 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
964 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
965 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
966 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
967 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
968 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
969 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
970 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
971 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
972 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
973 #else
974 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
975 #endif
976
977 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
978 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
979 #endif
980 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
981 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
982 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
983 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
984 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
985 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
986 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
987 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
988 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
989 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
990 #elif \
991 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
992 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
993 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
994 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
995 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
996 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
997 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
998 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
999 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1000 #else
1001 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1002 #endif
1003
1004 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1005 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1006 #endif
1007 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1008 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1009 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1010 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1011 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1012 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1013 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1014 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1015 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1016 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1017 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1018 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1019 #elif \
1020 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1021 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1022 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1023 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1024 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1025 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1026 #else
1027 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1028 #endif
1029
1030 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1031 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1032 #endif
1033 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1034 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1035 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1036 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1037 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1038 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1039 #else
1040 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1041 #endif
1042
1043 #if defined(JSON_HEDLEY_DEPRECATED)
1044 #undef JSON_HEDLEY_DEPRECATED
1045 #endif
1046 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1047 #undef JSON_HEDLEY_DEPRECATED_FOR
1048 #endif
1049 #if JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0)
1050 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1051 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1052 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1053 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1054 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1055 #elif \
1056 JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \
1057 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1058 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1059 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1060 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1061 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1062 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1063 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1064 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1065 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1066 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1067 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1068 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1069 #elif \
1070 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1071 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1072 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1073 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1074 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1075 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1076 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1077 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1078 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1079 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1080 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1081 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1082 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1083 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1084 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1085 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1086 #elif \
1087 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1088 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0)
1089 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1090 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1091 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1092 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1093 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1094 #else
1095 #define JSON_HEDLEY_DEPRECATED(since)
1096 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1097 #endif
1098
1099 #if defined(JSON_HEDLEY_UNAVAILABLE)
1100 #undef JSON_HEDLEY_UNAVAILABLE
1101 #endif
1102 #if \
1103 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1104 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1105 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1106 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1107 #else
1108 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1109 #endif
1110
1111 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1112 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1113 #endif
1114 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1115 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1116 #endif
1117 #if (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1118 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1119 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1120 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1121 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1122 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1123 #elif \
1124 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1125 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1126 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1127 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1128 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1129 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1130 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1131 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1132 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1133 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1134 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1135 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1136 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1137 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1138 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1139 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1140 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1141 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1142 #elif defined(_Check_return_) /* SAL */
1143 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1144 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1145 #else
1146 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1147 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1148 #endif
1149
1150 #if defined(JSON_HEDLEY_SENTINEL)
1151 #undef JSON_HEDLEY_SENTINEL
1152 #endif
1153 #if \
1154 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1155 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1156 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1157 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0)
1158 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1159 #else
1160 #define JSON_HEDLEY_SENTINEL(position)
1161 #endif
1162
1163 #if defined(JSON_HEDLEY_NO_RETURN)
1164 #undef JSON_HEDLEY_NO_RETURN
1165 #endif
1166 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1167 #define JSON_HEDLEY_NO_RETURN __noreturn
1168 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1169 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1170 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1171 #define JSON_HEDLEY_NO_RETURN _Noreturn
1172 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1173 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1174 #elif \
1175 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1176 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1177 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1178 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1179 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1180 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1181 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1182 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1183 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1184 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1185 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1186 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1187 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1188 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1189 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1190 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1191 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1192 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1193 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1194 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1195 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1196 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1197 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1198 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1199 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1200 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1201 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1202 #else
1203 #define JSON_HEDLEY_NO_RETURN
1204 #endif
1205
1206 #if defined(JSON_HEDLEY_NO_ESCAPE)
1207 #undef JSON_HEDLEY_NO_ESCAPE
1208 #endif
1209 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1210 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1211 #else
1212 #define JSON_HEDLEY_NO_ESCAPE
1213 #endif
1214
1215 #if defined(JSON_HEDLEY_UNREACHABLE)
1216 #undef JSON_HEDLEY_UNREACHABLE
1217 #endif
1218 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1219 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1220 #endif
1221 #if defined(JSON_HEDLEY_ASSUME)
1222 #undef JSON_HEDLEY_ASSUME
1223 #endif
1224 #if \
1225 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1226 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1227 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1228 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1229 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1230 #elif \
1231 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1232 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1233 #if defined(__cplusplus)
1234 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1235 #else
1236 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1237 #endif
1238 #endif
1239 #if \
1240 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1241 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1242 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1243 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1244 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
1245 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1246 #elif defined(JSON_HEDLEY_ASSUME)
1247 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1248 #endif
1249 #if !defined(JSON_HEDLEY_ASSUME)
1250 #if defined(JSON_HEDLEY_UNREACHABLE)
1251 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1252 #else
1253 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1254 #endif
1255 #endif
1256 #if defined(JSON_HEDLEY_UNREACHABLE)
1257 #if \
1258 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1259 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1260 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1261 #else
1262 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1263 #endif
1264 #else
1265 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1266 #endif
1267 #if !defined(JSON_HEDLEY_UNREACHABLE)
1268 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1269 #endif
1270
1271 JSON_HEDLEY_DIAGNOSTIC_PUSH
1272 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1273 #pragma clang diagnostic ignored "-Wpedantic"
1274 #endif
1275 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1276 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1277 #endif
1278 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1279 #if defined(__clang__)
1280 #pragma clang diagnostic ignored "-Wvariadic-macros"
1281 #elif defined(JSON_HEDLEY_GCC_VERSION)
1282 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1283 #endif
1284 #endif
1285 #if defined(JSON_HEDLEY_NON_NULL)
1286 #undef JSON_HEDLEY_NON_NULL
1287 #endif
1288 #if \
1289 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1290 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1291 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1292 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1293 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1294 #else
1295 #define JSON_HEDLEY_NON_NULL(...)
1296 #endif
1297 JSON_HEDLEY_DIAGNOSTIC_POP
1298
1299 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1300 #undef JSON_HEDLEY_PRINTF_FORMAT
1301 #endif
1302 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1303 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1304 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1305 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1306 #elif \
1307 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1308 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1309 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1310 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1311 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1312 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1313 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1314 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1315 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1316 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1317 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1318 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1319 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1320 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1321 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1322 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1323 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1324 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1325 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1326 #else
1327 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1328 #endif
1329
1330 #if defined(JSON_HEDLEY_CONSTEXPR)
1331 #undef JSON_HEDLEY_CONSTEXPR
1332 #endif
1333 #if defined(__cplusplus)
1334 #if __cplusplus >= 201103L
1335 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1336 #endif
1337 #endif
1338 #if !defined(JSON_HEDLEY_CONSTEXPR)
1339 #define JSON_HEDLEY_CONSTEXPR
1340 #endif
1341
1342 #if defined(JSON_HEDLEY_PREDICT)
1343 #undef JSON_HEDLEY_PREDICT
1344 #endif
1345 #if defined(JSON_HEDLEY_LIKELY)
1346 #undef JSON_HEDLEY_LIKELY
1347 #endif
1348 #if defined(JSON_HEDLEY_UNLIKELY)
1349 #undef JSON_HEDLEY_UNLIKELY
1350 #endif
1351 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1352 #undef JSON_HEDLEY_UNPREDICTABLE
1353 #endif
1354 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1355 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1356 #endif
1357 #if \
1358 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \
1359 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0)
1360 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1361 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1362 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1363 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1364 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1365 #elif \
1366 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \
1367 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1368 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1369 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1370 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1371 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1372 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1373 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1374 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1375 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1376 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1377 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1378 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1379 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1380 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1381 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1382 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1383 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1384 (__extension__ ({ \
1385 double hedley_probability_ = (probability); \
1386 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1387 }))
1388 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1389 (__extension__ ({ \
1390 double hedley_probability_ = (probability); \
1391 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1392 }))
1393 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1394 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1395 #else
1396 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1397 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1398 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1399 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1400 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1401 #endif
1402 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1403 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1404 #endif
1405
1406 #if defined(JSON_HEDLEY_MALLOC)
1407 #undef JSON_HEDLEY_MALLOC
1408 #endif
1409 #if \
1410 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1411 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1412 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1413 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1414 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1415 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1416 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1417 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1418 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1419 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1420 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1421 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1422 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1423 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1425 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1426 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1427 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1428 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1429 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1430 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0)
1431 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1432 #else
1433 #define JSON_HEDLEY_MALLOC
1434 #endif
1435
1436 #if defined(JSON_HEDLEY_PURE)
1437 #undef JSON_HEDLEY_PURE
1438 #endif
1439 #if \
1440 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1441 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1442 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1443 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1444 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1445 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1446 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1447 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1448 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1449 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1450 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1451 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1452 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1453 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1454 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1455 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1456 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1457 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1458 # define JSON_HEDLEY_PURE __attribute__((__pure__))
1459 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1460 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1461 #elif defined(__cplusplus) && \
1462 ( \
1463 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1464 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1465 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1466 )
1467 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1468 #else
1469 # define JSON_HEDLEY_PURE
1470 #endif
1471
1472 #if defined(JSON_HEDLEY_CONST)
1473 #undef JSON_HEDLEY_CONST
1474 #endif
1475 #if \
1476 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1477 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1478 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1479 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1480 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1481 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1482 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1483 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1484 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1485 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1486 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1487 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1488 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1489 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1491 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1492 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1493 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1494 #define JSON_HEDLEY_CONST __attribute__((__const__))
1495 #elif \
1496 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1497 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1498 #else
1499 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1500 #endif
1501
1502 #if defined(JSON_HEDLEY_RESTRICT)
1503 #undef JSON_HEDLEY_RESTRICT
1504 #endif
1505 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1506 #define JSON_HEDLEY_RESTRICT restrict
1507 #elif \
1508 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1509 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1510 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1511 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1512 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1513 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1514 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1515 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1516 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1517 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1518 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1519 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1520 defined(__clang__)
1521 #define JSON_HEDLEY_RESTRICT __restrict
1522 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1523 #define JSON_HEDLEY_RESTRICT _Restrict
1524 #else
1525 #define JSON_HEDLEY_RESTRICT
1526 #endif
1527
1528 #if defined(JSON_HEDLEY_INLINE)
1529 #undef JSON_HEDLEY_INLINE
1530 #endif
1531 #if \
1532 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1533 (defined(__cplusplus) && (__cplusplus >= 199711L))
1534 #define JSON_HEDLEY_INLINE inline
1535 #elif \
1536 defined(JSON_HEDLEY_GCC_VERSION) || \
1537 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1538 #define JSON_HEDLEY_INLINE __inline__
1539 #elif \
1540 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1541 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1542 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1543 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1544 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1545 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1546 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1547 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1548 #define JSON_HEDLEY_INLINE __inline
1549 #else
1550 #define JSON_HEDLEY_INLINE
1551 #endif
1552
1553 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1554 #undef JSON_HEDLEY_ALWAYS_INLINE
1555 #endif
1556 #if \
1557 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1558 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1559 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1560 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1561 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1562 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1563 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1564 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1565 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1566 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1567 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1568 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1569 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1570 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1571 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1572 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1573 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1574 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1575 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0)
1576 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1577 #elif defined(__cplusplus) && \
1578 ( \
1579 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1580 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1581 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1582 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1583 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1584 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1585 )
1586 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1587 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1588 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1589 #else
1590 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1591 #endif
1592
1593 #if defined(JSON_HEDLEY_NEVER_INLINE)
1594 #undef JSON_HEDLEY_NEVER_INLINE
1595 #endif
1596 #if \
1597 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1598 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1599 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1600 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1601 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1602 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1603 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1604 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1605 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1606 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1607 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1608 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1609 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1610 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1611 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1612 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1613 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1614 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1615 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1616 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1617 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1618 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1619 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1620 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1621 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1622 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1623 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1624 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1625 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1626 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1627 #else
1628 #define JSON_HEDLEY_NEVER_INLINE
1629 #endif
1630
1631 #if defined(JSON_HEDLEY_PRIVATE)
1632 #undef JSON_HEDLEY_PRIVATE
1633 #endif
1634 #if defined(JSON_HEDLEY_PUBLIC)
1635 #undef JSON_HEDLEY_PUBLIC
1636 #endif
1637 #if defined(JSON_HEDLEY_IMPORT)
1638 #undef JSON_HEDLEY_IMPORT
1639 #endif
1640 #if defined(_WIN32) || defined(__CYGWIN__)
1641 # define JSON_HEDLEY_PRIVATE
1642 # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1643 # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1644 #else
1645 # if \
1646 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1647 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1648 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1649 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1650 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1651 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1652 ( \
1653 defined(__TI_EABI__) && \
1654 ( \
1655 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1656 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1657 ) \
1658 )
1659 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1660 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1661 # else
1662 # define JSON_HEDLEY_PRIVATE
1663 # define JSON_HEDLEY_PUBLIC
1664 # endif
1665 # define JSON_HEDLEY_IMPORT extern
1666 #endif
1667
1668 #if defined(JSON_HEDLEY_NO_THROW)
1669 #undef JSON_HEDLEY_NO_THROW
1670 #endif
1671 #if \
1672 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1673 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1674 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1675 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1676 #elif \
1677 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1678 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1679 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1680 #else
1681 #define JSON_HEDLEY_NO_THROW
1682 #endif
1683
1684 #if defined(JSON_HEDLEY_FALL_THROUGH)
1685 #undef JSON_HEDLEY_FALL_THROUGH
1686 #endif
1687 #if \
1688 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1689 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0)
1690 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1691 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1692 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1693 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1694 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1695 #elif defined(__fallthrough) /* SAL */
1696 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1697 #else
1698 #define JSON_HEDLEY_FALL_THROUGH
1699 #endif
1700
1701 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1702 #undef JSON_HEDLEY_RETURNS_NON_NULL
1703 #endif
1704 #if \
1705 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1706 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
1707 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1708 #elif defined(_Ret_notnull_) /* SAL */
1709 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1710 #else
1711 #define JSON_HEDLEY_RETURNS_NON_NULL
1712 #endif
1713
1714 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1715 #undef JSON_HEDLEY_ARRAY_PARAM
1716 #endif
1717 #if \
1718 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1719 !defined(__STDC_NO_VLA__) && \
1720 !defined(__cplusplus) && \
1721 !defined(JSON_HEDLEY_PGI_VERSION) && \
1722 !defined(JSON_HEDLEY_TINYC_VERSION)
1723 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1724 #else
1725 #define JSON_HEDLEY_ARRAY_PARAM(name)
1726 #endif
1727
1728 #if defined(JSON_HEDLEY_IS_CONSTANT)
1729 #undef JSON_HEDLEY_IS_CONSTANT
1730 #endif
1731 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1732 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1733 #endif
1734 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1735 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1736 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1737 #undef JSON_HEDLEY_IS_CONSTEXPR_
1738 #endif
1739 #if \
1740 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1741 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1742 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1743 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1744 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1745 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1746 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1747 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1748 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1749 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1750 #endif
1751 #if !defined(__cplusplus)
1752 # if \
1753 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1754 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1755 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1756 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1757 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1758 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1759 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1760 #if defined(__INTPTR_TYPE__)
1761 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1762 #else
1763 #include <stdint.h>
1764 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1765 #endif
1766 # elif \
1767 ( \
1768 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1769 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1770 !defined(JSON_HEDLEY_PGI_VERSION) && \
1771 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1772 JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \
1773 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1774 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1775 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1776 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1777 #if defined(__INTPTR_TYPE__)
1778 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1779 #else
1780 #include <stdint.h>
1781 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1782 #endif
1783 # elif \
1784 defined(JSON_HEDLEY_GCC_VERSION) || \
1785 defined(JSON_HEDLEY_INTEL_VERSION) || \
1786 defined(JSON_HEDLEY_TINYC_VERSION) || \
1787 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1788 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1789 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1790 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1791 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1792 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1793 defined(__clang__)
1794 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1795 sizeof(void) != \
1796 sizeof(*( \
1797 1 ? \
1798 ((void*) ((expr) * 0L) ) : \
1799 ((struct { char v[sizeof(void) * 2]; } *) 1) \
1800 ) \
1801 ) \
1802 )
1803 # endif
1804 #endif
1805 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1806 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1807 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1808 #endif
1809 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1810 #else
1811 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1812 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1813 #endif
1814 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1815 #endif
1816
1817 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1818 #undef JSON_HEDLEY_BEGIN_C_DECLS
1819 #endif
1820 #if defined(JSON_HEDLEY_END_C_DECLS)
1821 #undef JSON_HEDLEY_END_C_DECLS
1822 #endif
1823 #if defined(JSON_HEDLEY_C_DECL)
1824 #undef JSON_HEDLEY_C_DECL
1825 #endif
1826 #if defined(__cplusplus)
1827 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1828 #define JSON_HEDLEY_END_C_DECLS }
1829 #define JSON_HEDLEY_C_DECL extern "C"
1830 #else
1831 #define JSON_HEDLEY_BEGIN_C_DECLS
1832 #define JSON_HEDLEY_END_C_DECLS
1833 #define JSON_HEDLEY_C_DECL
1834 #endif
1835
1836 #if defined(JSON_HEDLEY_STATIC_ASSERT)
1837 #undef JSON_HEDLEY_STATIC_ASSERT
1838 #endif
1839 #if \
1840 !defined(__cplusplus) && ( \
1841 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1842 JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \
1843 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1844 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1845 defined(_Static_assert) \
1846 )
1847 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1848 #elif \
1849 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1850 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0)
1851 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1852 #else
1853 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1854 #endif
1855
1856 #if defined(JSON_HEDLEY_NULL)
1857 #undef JSON_HEDLEY_NULL
1858 #endif
1859 #if defined(__cplusplus)
1860 #if __cplusplus >= 201103L
1861 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1862 #elif defined(NULL)
1863 #define JSON_HEDLEY_NULL NULL
1864 #else
1865 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1866 #endif
1867 #elif defined(NULL)
1868 #define JSON_HEDLEY_NULL NULL
1869 #else
1870 #define JSON_HEDLEY_NULL ((void*) 0)
1871 #endif
1872
1873 #if defined(JSON_HEDLEY_MESSAGE)
1874 #undef JSON_HEDLEY_MESSAGE
1875 #endif
1876 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1877 # define JSON_HEDLEY_MESSAGE(msg) \
1878 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1879 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1880 JSON_HEDLEY_PRAGMA(message msg) \
1881 JSON_HEDLEY_DIAGNOSTIC_POP
1882 #elif \
1883 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
1884 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1885 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
1886 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
1887 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
1888 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1889 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1890 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
1891 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1892 #else
1893 # define JSON_HEDLEY_MESSAGE(msg)
1894 #endif
1895
1896 #if defined(JSON_HEDLEY_WARNING)
1897 #undef JSON_HEDLEY_WARNING
1898 #endif
1899 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1900 # define JSON_HEDLEY_WARNING(msg) \
1901 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1902 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1903 JSON_HEDLEY_PRAGMA(clang warning msg) \
1904 JSON_HEDLEY_DIAGNOSTIC_POP
1905 #elif \
1906 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
1907 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1908 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1909 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
1910 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1911 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
1912 #else
1913 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
1914 #endif
1915
1916 #if defined(JSON_HEDLEY_REQUIRE)
1917 #undef JSON_HEDLEY_REQUIRE
1918 #endif
1919 #if defined(JSON_HEDLEY_REQUIRE_MSG)
1920 #undef JSON_HEDLEY_REQUIRE_MSG
1921 #endif
1922 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
1923 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
1924 # define JSON_HEDLEY_REQUIRE(expr) \
1925 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1926 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1927 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
1928 JSON_HEDLEY_DIAGNOSTIC_POP
1929 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
1930 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1931 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1932 __attribute__((diagnose_if(!(expr), msg, "error"))) \
1933 JSON_HEDLEY_DIAGNOSTIC_POP
1934 # else
1935 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
1936 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
1937 # endif
1938 #else
1939 # define JSON_HEDLEY_REQUIRE(expr)
1940 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
1941 #endif
1942
1943 #if defined(JSON_HEDLEY_FLAGS)
1944 #undef JSON_HEDLEY_FLAGS
1945 #endif
1946 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum)
1947 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
1948 #endif
1949
1950 #if defined(JSON_HEDLEY_FLAGS_CAST)
1951 #undef JSON_HEDLEY_FLAGS_CAST
1952 #endif
1953 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
1954 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
1955 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1956 _Pragma("warning(disable:188)") \
1957 ((T) (expr)); \
1958 JSON_HEDLEY_DIAGNOSTIC_POP \
1959 }))
1960 #else
1961 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
1962 #endif
1963
1964 #if defined(JSON_HEDLEY_EMPTY_BASES)
1965 #undef JSON_HEDLEY_EMPTY_BASES
1966 #endif
1967 #if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)
1968 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
1969 #else
1970 #define JSON_HEDLEY_EMPTY_BASES
1971 #endif
1972
1973 /* Remaining macros are deprecated. */
1974
1975 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
1976 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
1977 #endif
1978 #if defined(__clang__)
1979 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
1980 #else
1981 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1982 #endif
1983
1984 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
1985 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
1986 #endif
1987 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
1988
1989 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
1990 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
1991 #endif
1992 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
1993
1994 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
1995 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
1996 #endif
1997 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
1998
1999 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2000 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2001 #endif
2002 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2003
2004 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2005 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2006 #endif
2007 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2008
2009 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2010 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2011 #endif
2012 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2013
2014 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2015 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2016 #endif
2017 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2018
2019 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2020
2021
2022 // This file contains all internal macro definitions
2023 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2024
2025 // exclude unsupported compilers
2026 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2027 #if defined(__clang__)
2028 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2029 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2030 #endif
2031 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2032 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2033 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2034 #endif
2035 #endif
2036 #endif
2037
2038 // C++ language standard detection
2039 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2040 #define JSON_HAS_CPP_20
2041 #define JSON_HAS_CPP_17
2042 #define JSON_HAS_CPP_14
2043 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2044 #define JSON_HAS_CPP_17
2045 #define JSON_HAS_CPP_14
2046 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2047 #define JSON_HAS_CPP_14
2048 #endif
2049
2050 // disable float-equal warnings on GCC/clang
2051 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
2052 #pragma GCC diagnostic push
2053 #pragma GCC diagnostic ignored "-Wfloat-equal"
2054 #endif
2055
2056 // disable documentation warnings on clang
2057 #if defined(__clang__)
2058 #pragma GCC diagnostic push
2059 #pragma GCC diagnostic ignored "-Wdocumentation"
2060 #endif
2061
2062 // allow to disable exceptions
2063 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2064 #define JSON_THROW(exception) throw exception
2065 #define JSON_TRY try
2066 #define JSON_CATCH(exception) catch(exception)
2067 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2068 #else
2069 #include <cstdlib>
2070 #define JSON_THROW(exception) std::abort()
2071 #define JSON_TRY if(true)
2072 #define JSON_CATCH(exception) if(false)
2073 #define JSON_INTERNAL_CATCH(exception) if(false)
2074 #endif
2075
2076 // override exception macros
2077 #if defined(JSON_THROW_USER)
2078 #undef JSON_THROW
2079 #define JSON_THROW JSON_THROW_USER
2080 #endif
2081 #if defined(JSON_TRY_USER)
2082 #undef JSON_TRY
2083 #define JSON_TRY JSON_TRY_USER
2084 #endif
2085 #if defined(JSON_CATCH_USER)
2086 #undef JSON_CATCH
2087 #define JSON_CATCH JSON_CATCH_USER
2088 #undef JSON_INTERNAL_CATCH
2089 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2090 #endif
2091 #if defined(JSON_INTERNAL_CATCH_USER)
2092 #undef JSON_INTERNAL_CATCH
2093 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2094 #endif
2095
2096 // allow to override assert
2097 #if !defined(JSON_ASSERT)
2098 #include <cassert> // assert
2099 #define JSON_ASSERT(x) assert(x)
2100 #endif
2101
2102 /*!
2103 @brief macro to briefly define a mapping between an enum and JSON
2104 @def NLOHMANN_JSON_SERIALIZE_ENUM
2105 @since version 3.4.0
2106 */
2107 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2108 template<typename BasicJsonType> \
2109 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2110 { \
2111 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2112 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2113 auto it = std::find_if(std::begin(m), std::end(m), \
2114 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2115 { \
2116 return ej_pair.first == e; \
2117 }); \
2118 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2119 } \
2120 template<typename BasicJsonType> \
2121 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2122 { \
2123 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2124 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2125 auto it = std::find_if(std::begin(m), std::end(m), \
2126 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2127 { \
2128 return ej_pair.second == j; \
2129 }); \
2130 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2131 }
2132
2133 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2134 // may be removed in the future once the class is split.
2135
2136 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2137 template<template<typename, typename, typename...> class ObjectType, \
2138 template<typename, typename...> class ArrayType, \
2139 class StringType, class BooleanType, class NumberIntegerType, \
2140 class NumberUnsignedType, class NumberFloatType, \
2141 template<typename> class AllocatorType, \
2142 template<typename, typename = void> class JSONSerializer, \
2143 class BinaryType>
2144
2145 #define NLOHMANN_BASIC_JSON_TPL \
2146 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2147 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2148 AllocatorType, JSONSerializer, BinaryType>
2149
2150 // Macros to simplify conversion from/to types
2151
2152 #define NLOHMANN_JSON_EXPAND( x ) x
2153 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2154 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2155 NLOHMANN_JSON_PASTE64, \
2156 NLOHMANN_JSON_PASTE63, \
2157 NLOHMANN_JSON_PASTE62, \
2158 NLOHMANN_JSON_PASTE61, \
2159 NLOHMANN_JSON_PASTE60, \
2160 NLOHMANN_JSON_PASTE59, \
2161 NLOHMANN_JSON_PASTE58, \
2162 NLOHMANN_JSON_PASTE57, \
2163 NLOHMANN_JSON_PASTE56, \
2164 NLOHMANN_JSON_PASTE55, \
2165 NLOHMANN_JSON_PASTE54, \
2166 NLOHMANN_JSON_PASTE53, \
2167 NLOHMANN_JSON_PASTE52, \
2168 NLOHMANN_JSON_PASTE51, \
2169 NLOHMANN_JSON_PASTE50, \
2170 NLOHMANN_JSON_PASTE49, \
2171 NLOHMANN_JSON_PASTE48, \
2172 NLOHMANN_JSON_PASTE47, \
2173 NLOHMANN_JSON_PASTE46, \
2174 NLOHMANN_JSON_PASTE45, \
2175 NLOHMANN_JSON_PASTE44, \
2176 NLOHMANN_JSON_PASTE43, \
2177 NLOHMANN_JSON_PASTE42, \
2178 NLOHMANN_JSON_PASTE41, \
2179 NLOHMANN_JSON_PASTE40, \
2180 NLOHMANN_JSON_PASTE39, \
2181 NLOHMANN_JSON_PASTE38, \
2182 NLOHMANN_JSON_PASTE37, \
2183 NLOHMANN_JSON_PASTE36, \
2184 NLOHMANN_JSON_PASTE35, \
2185 NLOHMANN_JSON_PASTE34, \
2186 NLOHMANN_JSON_PASTE33, \
2187 NLOHMANN_JSON_PASTE32, \
2188 NLOHMANN_JSON_PASTE31, \
2189 NLOHMANN_JSON_PASTE30, \
2190 NLOHMANN_JSON_PASTE29, \
2191 NLOHMANN_JSON_PASTE28, \
2192 NLOHMANN_JSON_PASTE27, \
2193 NLOHMANN_JSON_PASTE26, \
2194 NLOHMANN_JSON_PASTE25, \
2195 NLOHMANN_JSON_PASTE24, \
2196 NLOHMANN_JSON_PASTE23, \
2197 NLOHMANN_JSON_PASTE22, \
2198 NLOHMANN_JSON_PASTE21, \
2199 NLOHMANN_JSON_PASTE20, \
2200 NLOHMANN_JSON_PASTE19, \
2201 NLOHMANN_JSON_PASTE18, \
2202 NLOHMANN_JSON_PASTE17, \
2203 NLOHMANN_JSON_PASTE16, \
2204 NLOHMANN_JSON_PASTE15, \
2205 NLOHMANN_JSON_PASTE14, \
2206 NLOHMANN_JSON_PASTE13, \
2207 NLOHMANN_JSON_PASTE12, \
2208 NLOHMANN_JSON_PASTE11, \
2209 NLOHMANN_JSON_PASTE10, \
2210 NLOHMANN_JSON_PASTE9, \
2211 NLOHMANN_JSON_PASTE8, \
2212 NLOHMANN_JSON_PASTE7, \
2213 NLOHMANN_JSON_PASTE6, \
2214 NLOHMANN_JSON_PASTE5, \
2215 NLOHMANN_JSON_PASTE4, \
2216 NLOHMANN_JSON_PASTE3, \
2217 NLOHMANN_JSON_PASTE2, \
2218 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2219 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2220 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2221 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2222 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2223 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2224 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2225 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2226 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2227 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2228 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2229 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2230 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2231 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2232 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2233 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2234 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2235 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2236 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2237 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2238 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2239 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2240 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2241 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2242 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2243 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2244 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2245 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2246 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2247 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2248 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2249 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2250 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2251 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2252 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2253 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2254 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2255 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2256 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2257 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2258 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2259 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2260 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2261 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2262 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2263 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2264 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2265 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2266 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2267 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2268 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2269 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2270 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2271 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2272 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2273 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2274 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2275 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2276 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2277 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2278 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2279 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2280 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2281 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2282
2283 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2284 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2285
2286 /*!
2287 @brief macro
2288 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2289 @since version 3.9.0
2290 */
2291 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2292 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2293 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2294
2295 /*!
2296 @brief macro
2297 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2298 @since version 3.9.0
2299 */
2300 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2301 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2302 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2303
2304 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2305 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2306 #endif
2307
2308 #if JSON_USE_IMPLICIT_CONVERSIONS
2309 #define JSON_EXPLICIT
2310 #else
2311 #define JSON_EXPLICIT explicit
2312 #endif
2313
2314
2315 namespace nlohmann
2316 {
2317 namespace detail
2318 {
2319 ////////////////
2320 // exceptions //
2321 ////////////////
2322
2323 /*!
2324 @brief general exception of the @ref basic_json class
2325
2326 This class is an extension of `std::exception` objects with a member @a id for
2327 exception ids. It is used as the base class for all exceptions thrown by the
2328 @ref basic_json class. This class can hence be used as "wildcard" to catch
2329 exceptions.
2330
2331 Subclasses:
2332 - @ref parse_error for exceptions indicating a parse error
2333 - @ref invalid_iterator for exceptions indicating errors with iterators
2334 - @ref type_error for exceptions indicating executing a member function with
2335 a wrong type
2336 - @ref out_of_range for exceptions indicating access out of the defined range
2337 - @ref other_error for exceptions indicating other library errors
2338
2339 @internal
2340 @note To have nothrow-copy-constructible exceptions, we internally use
2341 `std::runtime_error` which can cope with arbitrary-length error messages.
2342 Intermediate strings are built with static functions and then passed to
2343 the actual constructor.
2344 @endinternal
2345
2346 @liveexample{The following code shows how arbitrary library exceptions can be
2347 caught.,exception}
2348
2349 @since version 3.0.0
2350 */
2351 class exception : public std::exception
2352 {
2353 public:
2354 /// returns the explanatory string
2355 JSON_HEDLEY_RETURNS_NON_NULL
2356 const char* what() const noexcept override
2357 {
2358 return m.what();
2359 }
2360
2361 /// the id of the exception
2362 const int id;
2363
2364 protected:
2365 JSON_HEDLEY_NON_NULL(3)
2366 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
2367
2368 static std::string name(const std::string& ename, int id_)
2369 {
2370 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2371 }
2372
2373 private:
2374 /// an exception object as storage for error messages
2375 std::runtime_error m;
2376 };
2377
2378 /*!
2379 @brief exception indicating a parse error
2380
2381 This exception is thrown by the library when a parse error occurs. Parse errors
2382 can occur during the deserialization of JSON text, CBOR, MessagePack, as well
2383 as when using JSON Patch.
2384
2385 Member @a byte holds the byte index of the last read character in the input
2386 file.
2387
2388 Exceptions have ids 1xx.
2389
2390 name / id | example message | description
2391 ------------------------------ | --------------- | -------------------------
2392 json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
2393 json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
2394 json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
2395 json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
2396 json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
2397 json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
2398 json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
2399 json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
2400 json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
2401 json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
2402 json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
2403 json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
2404 json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
2405 json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
2406
2407 @note For an input with n bytes, 1 is the index of the first character and n+1
2408 is the index of the terminating null byte or the end of file. This also
2409 holds true when reading a byte vector (CBOR or MessagePack).
2410
2411 @liveexample{The following code shows how a `parse_error` exception can be
2412 caught.,parse_error}
2413
2414 @sa - @ref exception for the base class of the library exceptions
2415 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2416 @sa - @ref type_error for exceptions indicating executing a member function with
2417 a wrong type
2418 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2419 @sa - @ref other_error for exceptions indicating other library errors
2420
2421 @since version 3.0.0
2422 */
2423 class parse_error : public exception
2424 {
2425 public:
2426 /*!
2427 @brief create a parse error exception
2428 @param[in] id_ the id of the exception
2429 @param[in] pos the position where the error occurred (or with
2430 chars_read_total=0 if the position cannot be
2431 determined)
2432 @param[in] what_arg the explanatory string
2433 @return parse_error object
2434 */
2435 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
2436 {
2437 std::string w = exception::name("parse_error", id_) + "parse error" +
2438 position_string(pos) + ": " + what_arg;
2439 return parse_error(id_, pos.chars_read_total, w.c_str());
2440 }
2441
2442 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
2443 {
2444 std::string w = exception::name("parse_error", id_) + "parse error" +
2445 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2446 ": " + what_arg;
2447 return parse_error(id_, byte_, w.c_str());
2448 }
2449
2450 /*!
2451 @brief byte index of the parse error
2452
2453 The byte index of the last read character in the input file.
2454
2455 @note For an input with n bytes, 1 is the index of the first character and
2456 n+1 is the index of the terminating null byte or the end of file.
2457 This also holds true when reading a byte vector (CBOR or MessagePack).
2458 */
2459 const std::size_t byte;
2460
2461 private:
2462 parse_error(int id_, std::size_t byte_, const char* what_arg)
2463 : exception(id_, what_arg), byte(byte_) {}
2464
2465 static std::string position_string(const position_t& pos)
2466 {
2467 return " at line " + std::to_string(pos.lines_read + 1) +
2468 ", column " + std::to_string(pos.chars_read_current_line);
2469 }
2470 };
2471
2472 /*!
2473 @brief exception indicating errors with iterators
2474
2475 This exception is thrown if iterators passed to a library function do not match
2476 the expected semantics.
2477
2478 Exceptions have ids 2xx.
2479
2480 name / id | example message | description
2481 ----------------------------------- | --------------- | -------------------------
2482 json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2483 json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
2484 json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
2485 json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
2486 json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
2487 json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
2488 json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
2489 json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2490 json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2491 json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2492 json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
2493 json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
2494 json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
2495 json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
2496
2497 @liveexample{The following code shows how an `invalid_iterator` exception can be
2498 caught.,invalid_iterator}
2499
2500 @sa - @ref exception for the base class of the library exceptions
2501 @sa - @ref parse_error for exceptions indicating a parse error
2502 @sa - @ref type_error for exceptions indicating executing a member function with
2503 a wrong type
2504 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2505 @sa - @ref other_error for exceptions indicating other library errors
2506
2507 @since version 3.0.0
2508 */
2509 class invalid_iterator : public exception
2510 {
2511 public:
2512 static invalid_iterator create(int id_, const std::string& what_arg)
2513 {
2514 std::string w = exception::name("invalid_iterator", id_) + what_arg;
2515 return invalid_iterator(id_, w.c_str());
2516 }
2517
2518 private:
2519 JSON_HEDLEY_NON_NULL(3)
2520 invalid_iterator(int id_, const char* what_arg)
2521 : exception(id_, what_arg) {}
2522 };
2523
2524 /*!
2525 @brief exception indicating executing a member function with a wrong type
2526
2527 This exception is thrown in case of a type error; that is, a library function is
2528 executed on a JSON value whose type does not match the expected semantics.
2529
2530 Exceptions have ids 3xx.
2531
2532 name / id | example message | description
2533 ----------------------------- | --------------- | -------------------------
2534 json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
2535 json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
2536 json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
2537 json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
2538 json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
2539 json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
2540 json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
2541 json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
2542 json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
2543 json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
2544 json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
2545 json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
2546 json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
2547 json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
2548 json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
2549 json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
2550 json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
2551
2552 @liveexample{The following code shows how a `type_error` exception can be
2553 caught.,type_error}
2554
2555 @sa - @ref exception for the base class of the library exceptions
2556 @sa - @ref parse_error for exceptions indicating a parse error
2557 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2558 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2559 @sa - @ref other_error for exceptions indicating other library errors
2560
2561 @since version 3.0.0
2562 */
2563 class type_error : public exception
2564 {
2565 public:
2566 static type_error create(int id_, const std::string& what_arg)
2567 {
2568 std::string w = exception::name("type_error", id_) + what_arg;
2569 return type_error(id_, w.c_str());
2570 }
2571
2572 private:
2573 JSON_HEDLEY_NON_NULL(3)
2574 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2575 };
2576
2577 /*!
2578 @brief exception indicating access out of the defined range
2579
2580 This exception is thrown in case a library function is called on an input
2581 parameter that exceeds the expected range, for instance in case of array
2582 indices or nonexisting object keys.
2583
2584 Exceptions have ids 4xx.
2585
2586 name / id | example message | description
2587 ------------------------------- | --------------- | -------------------------
2588 json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
2589 json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
2590 json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
2591 json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
2592 json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
2593 json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
2594 json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
2595 json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
2596 json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
2597
2598 @liveexample{The following code shows how an `out_of_range` exception can be
2599 caught.,out_of_range}
2600
2601 @sa - @ref exception for the base class of the library exceptions
2602 @sa - @ref parse_error for exceptions indicating a parse error
2603 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2604 @sa - @ref type_error for exceptions indicating executing a member function with
2605 a wrong type
2606 @sa - @ref other_error for exceptions indicating other library errors
2607
2608 @since version 3.0.0
2609 */
2610 class out_of_range : public exception
2611 {
2612 public:
2613 static out_of_range create(int id_, const std::string& what_arg)
2614 {
2615 std::string w = exception::name("out_of_range", id_) + what_arg;
2616 return out_of_range(id_, w.c_str());
2617 }
2618
2619 private:
2620 JSON_HEDLEY_NON_NULL(3)
2621 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
2622 };
2623
2624 /*!
2625 @brief exception indicating other library errors
2626
2627 This exception is thrown in case of errors that cannot be classified with the
2628 other exception types.
2629
2630 Exceptions have ids 5xx.
2631
2632 name / id | example message | description
2633 ------------------------------ | --------------- | -------------------------
2634 json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
2635
2636 @sa - @ref exception for the base class of the library exceptions
2637 @sa - @ref parse_error for exceptions indicating a parse error
2638 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2639 @sa - @ref type_error for exceptions indicating executing a member function with
2640 a wrong type
2641 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2642
2643 @liveexample{The following code shows how an `other_error` exception can be
2644 caught.,other_error}
2645
2646 @since version 3.0.0
2647 */
2648 class other_error : public exception
2649 {
2650 public:
2651 static other_error create(int id_, const std::string& what_arg)
2652 {
2653 std::string w = exception::name("other_error", id_) + what_arg;
2654 return other_error(id_, w.c_str());
2655 }
2656
2657 private:
2658 JSON_HEDLEY_NON_NULL(3)
2659 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2660 };
2661 } // namespace detail
2662 } // namespace nlohmann
2663
2664 // #include <nlohmann/detail/macro_scope.hpp>
2665
2666 // #include <nlohmann/detail/meta/cpp_future.hpp>
2667
2668
2669 #include <cstddef> // size_t
2670 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2671
2672 namespace nlohmann
2673 {
2674 namespace detail
2675 {
2676 // alias templates to reduce boilerplate
2677 template<bool B, typename T = void>
2678 using enable_if_t = typename std::enable_if<B, T>::type;
2679
2680 template<typename T>
2681 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2682
2683 // implementation of C++14 index_sequence and affiliates
2684 // source: https://stackoverflow.com/a/32223343
2685 template<std::size_t... Ints>
2686 struct index_sequence
2687 {
2688 using type = index_sequence;
2689 using value_type = std::size_t;
2690 static constexpr std::size_t size() noexcept
2691 {
2692 return sizeof...(Ints);
2693 }
2694 };
2695
2696 template<class Sequence1, class Sequence2>
2697 struct merge_and_renumber;
2698
2699 template<std::size_t... I1, std::size_t... I2>
2700 struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
2701 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
2702
2703 template<std::size_t N>
2704 struct make_index_sequence
2705 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
2706 typename make_index_sequence < N - N / 2 >::type > {};
2707
2708 template<> struct make_index_sequence<0> : index_sequence<> {};
2709 template<> struct make_index_sequence<1> : index_sequence<0> {};
2710
2711 template<typename... Ts>
2712 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
2713
2714 // dispatch utility (taken from ranges-v3)
2715 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
2716 template<> struct priority_tag<0> {};
2717
2718 // taken from ranges-v3
2719 template<typename T>
2720 struct static_const
2721 {
2722 static constexpr T value{};
2723 };
2724
2725 template<typename T>
2726 constexpr T static_const<T>::value;
2727 } // namespace detail
2728 } // namespace nlohmann
2729
2730 // #include <nlohmann/detail/meta/type_traits.hpp>
2731
2732
2733 #include <limits> // numeric_limits
2734 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
2735 #include <utility> // declval
2736
2737 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
2738
2739
2740 #include <iterator> // random_access_iterator_tag
2741
2742 // #include <nlohmann/detail/meta/void_t.hpp>
2743
2744
2745 namespace nlohmann
2746 {
2747 namespace detail
2748 {
2749 template<typename ...Ts> struct make_void
2750 {
2751 using type = void;
2752 };
2753 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2754 } // namespace detail
2755 } // namespace nlohmann
2756
2757 // #include <nlohmann/detail/meta/cpp_future.hpp>
2758
2759
2760 namespace nlohmann
2761 {
2762 namespace detail
2763 {
2764 template<typename It, typename = void>
2765 struct iterator_types {};
2766
2767 template<typename It>
2768 struct iterator_types <
2769 It,
2770 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
2771 typename It::reference, typename It::iterator_category >>
2772 {
2773 using difference_type = typename It::difference_type;
2774 using value_type = typename It::value_type;
2775 using pointer = typename It::pointer;
2776 using reference = typename It::reference;
2777 using iterator_category = typename It::iterator_category;
2778 };
2779
2780 // This is required as some compilers implement std::iterator_traits in a way that
2781 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
2782 template<typename T, typename = void>
2783 struct iterator_traits
2784 {
2785 };
2786
2787 template<typename T>
2788 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
2789 : iterator_types<T>
2790 {
2791 };
2792
2793 template<typename T>
2794 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
2795 {
2796 using iterator_category = std::random_access_iterator_tag;
2797 using value_type = T;
2798 using difference_type = ptrdiff_t;
2799 using pointer = T*;
2800 using reference = T&;
2801 };
2802 } // namespace detail
2803 } // namespace nlohmann
2804
2805 // #include <nlohmann/detail/macro_scope.hpp>
2806
2807 // #include <nlohmann/detail/meta/cpp_future.hpp>
2808
2809 // #include <nlohmann/detail/meta/detected.hpp>
2810
2811
2812 #include <type_traits>
2813
2814 // #include <nlohmann/detail/meta/void_t.hpp>
2815
2816
2817 // https://en.cppreference.com/w/cpp/experimental/is_detected
2818 namespace nlohmann
2819 {
2820 namespace detail
2821 {
2822 struct nonesuch
2823 {
2824 nonesuch() = delete;
2825 ~nonesuch() = delete;
2826 nonesuch(nonesuch const&) = delete;
2827 nonesuch(nonesuch const&&) = delete;
2828 void operator=(nonesuch const&) = delete;
2829 void operator=(nonesuch&&) = delete;
2830 };
2831
2832 template<class Default,
2833 class AlwaysVoid,
2834 template<class...> class Op,
2835 class... Args>
2836 struct detector
2837 {
2838 using value_t = std::false_type;
2839 using type = Default;
2840 };
2841
2842 template<class Default, template<class...> class Op, class... Args>
2843 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2844 {
2845 using value_t = std::true_type;
2846 using type = Op<Args...>;
2847 };
2848
2849 template<template<class...> class Op, class... Args>
2850 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2851
2852 template<template<class...> class Op, class... Args>
2853 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2854
2855 template<class Default, template<class...> class Op, class... Args>
2856 using detected_or = detector<Default, void, Op, Args...>;
2857
2858 template<class Default, template<class...> class Op, class... Args>
2859 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2860
2861 template<class Expected, template<class...> class Op, class... Args>
2862 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2863
2864 template<class To, template<class...> class Op, class... Args>
2865 using is_detected_convertible =
2866 std::is_convertible<detected_t<Op, Args...>, To>;
2867 } // namespace detail
2868 } // namespace nlohmann
462869
472870 // #include <nlohmann/json_fwd.hpp>
48 #ifndef NLOHMANN_JSON_FWD_HPP
49 #define NLOHMANN_JSON_FWD_HPP
2871 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
2872 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
502873
512874 #include <cstdint> // int64_t, uint64_t
52 #include <map> // map
53 #include <memory> // allocator
54 #include <string> // string
55 #include <vector> // vector
56
57 #include "str_compat.hpp"
58
2875 #include <map> // map
2876 #include <memory> // allocator
2877 #include <string> // string
2878 #include <vector> // vector
592879
602880 /*!
612881 @brief namespace for Niels Lohmann
682888 @brief default JSONSerializer template argument
692889
702890 This serializer ignores the template arguments and uses ADL
71 ([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))
2891 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
722892 for serialization.
732893 */
74 template <typename = void, typename = void>
2894 template<typename T = void, typename SFINAE = void>
752895 struct adl_serializer;
762896
77 template <template <typename U, typename V, typename... Args> class ObjectType = std::map,
78 template <typename U, typename... Args> class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool,
79 class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double,
80 template <typename U> class AllocatorType = std::allocator, template <typename T, typename SFINAE = void> class JSONSerializer = adl_serializer>
2897 template<template<typename U, typename V, typename... Args> class ObjectType =
2898 std::map,
2899 template<typename U, typename... Args> class ArrayType = std::vector,
2900 class StringType = std::string, class BooleanType = bool,
2901 class NumberIntegerType = std::int64_t,
2902 class NumberUnsignedType = std::uint64_t,
2903 class NumberFloatType = double,
2904 template<typename U> class AllocatorType = std::allocator,
2905 template<typename T, typename SFINAE = void> class JSONSerializer =
2906 adl_serializer,
2907 class BinaryType = std::vector<std::uint8_t>>
812908 class basic_json;
822909
832910 /*!
912918
922919 @since version 2.0.0
932920 */
94 template <typename BasicJsonType>
2921 template<typename BasicJsonType>
952922 class json_pointer;
962923
972924 /*!
1032930 @since version 1.0.0
1042931 */
1052932 using json = basic_json<>;
106 }
107
108 #endif
109
110 // #include <nlohmann/detail/macro_scope.hpp>
111
112
113 // This file contains all internal macro definitions
114 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
115
116 // exclude unsupported compilers
117 #if defined(__clang__)
118 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
119 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
120 #endif
121 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
122 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
123 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
124 #endif
125 #endif
126
127 // disable float-equal warnings on GCC/clang
128 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
129 #pragma GCC diagnostic push
130 #pragma GCC diagnostic ignored "-Wfloat-equal"
131 #endif
132
133 // disable documentation warnings on clang
134 #if defined(__clang__)
135 #pragma GCC diagnostic push
136 #pragma GCC diagnostic ignored "-Wdocumentation"
137 #endif
138
139 // allow for portable deprecation warnings
140 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
141 #define JSON_DEPRECATED __attribute__((deprecated))
142 #elif defined(_MSC_VER)
143 #define JSON_DEPRECATED __declspec(deprecated)
144 #else
145 #define JSON_DEPRECATED
146 #endif
147
148 // allow to disable exceptions
149 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
150 #define JSON_THROW(exception) throw exception
151 #define JSON_TRY try
152 #define JSON_CATCH(exception) catch (exception)
153 #else
154 #define JSON_THROW(exception) std::abort()
155 #define JSON_TRY if (true)
156 #define JSON_CATCH(exception) if (false)
157 #endif
158
159 // override exception macros
160 #if defined(JSON_THROW_USER)
161 #undef JSON_THROW
162 #define JSON_THROW JSON_THROW_USER
163 #endif
164 #if defined(JSON_TRY_USER)
165 #undef JSON_TRY
166 #define JSON_TRY JSON_TRY_USER
167 #endif
168 #if defined(JSON_CATCH_USER)
169 #undef JSON_CATCH
170 #define JSON_CATCH JSON_CATCH_USER
171 #endif
172
173 // manual branch prediction
174 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
175 #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
176 #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
177 #else
178 #define JSON_LIKELY(x) x
179 #define JSON_UNLIKELY(x) x
180 #endif
181
182 // C++ language standard detection
183 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
184 #define JSON_HAS_CPP_17
185 #define JSON_HAS_CPP_14
186 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
187 #define JSON_HAS_CPP_14
188 #endif
189
190 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
191 // may be removed in the future once the class is split.
192
193 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
194 template <template <typename, typename, typename...> class ObjectType, template <typename, typename...> class ArrayType, class StringType, \
195 class BooleanType, class NumberIntegerType, class NumberUnsignedType, class NumberFloatType, template <typename> class AllocatorType, \
196 template <typename, typename = void> class JSONSerializer>
197
198 #define NLOHMANN_BASIC_JSON_TPL \
199 basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>
2933
2934 template<class Key, class T, class IgnoredLess, class Allocator>
2935 struct ordered_map;
2002936
2012937 /*!
202 @brief Helper to determine whether there's a key_type for T.
203
204 This helper is used to tell associative containers apart from other containers
205 such as sequence containers. For instance, `std::map` passes the test as it
206 contains a `mapped_type`, whereas `std::vector` fails the test.
207
208 @sa http://stackoverflow.com/a/7728728/266378
209 @since version 1.0.0, overworked in version 2.0.6
2938 @brief ordered JSON class
2939
2940 This type preserves the insertion order of object keys.
2941
2942 @since version 3.9.0
2102943 */
211 #define NLOHMANN_JSON_HAS_HELPER(type) \
212 template <typename T> \
213 struct has_##type \
214 { \
215 private: \
216 template <typename U, typename = typename U::type> \
217 static int detect(U&&); \
218 static void detect(...); \
219 \
220 public: \
221 static constexpr bool value = std::is_integral<decltype(detect(std::declval<T>()))>::value; \
222 }
223
224 // #include <nlohmann/detail/meta.hpp>
225
226
227 #include <ciso646> // not
228 #include <cstddef> // size_t
229 #include <limits> // numeric_limits
230 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
231 #include <utility> // declval
232
233 // #include <nlohmann/json_fwd.hpp>
234
235 // #include <nlohmann/detail/macro_scope.hpp>
2944 using ordered_json = basic_json<nlohmann::ordered_map>;
2945
2946 } // namespace nlohmann
2947
2948 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
2362949
2372950
2382951 namespace nlohmann
2512964 // helpers //
2522965 /////////////
2532966
254 template <typename>
255 struct is_basic_json : std::false_type
2967 // Note to maintainers:
2968 //
2969 // Every trait in this file expects a non CV-qualified type.
2970 // The only exceptions are in the 'aliases for detected' section
2971 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
2972 //
2973 // In this case, T has to be properly CV-qualified to constraint the function arguments
2974 // (e.g. to_json(BasicJsonType&, const T&))
2975
2976 template<typename> struct is_basic_json : std::false_type {};
2977
2978 NLOHMANN_BASIC_JSON_TPL_DECLARATION
2979 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
2980
2981 //////////////////////
2982 // json_ref helpers //
2983 //////////////////////
2984
2985 template<typename>
2986 class json_ref;
2987
2988 template<typename>
2989 struct is_json_ref : std::false_type {};
2990
2991 template<typename T>
2992 struct is_json_ref<json_ref<T>> : std::true_type {};
2993
2994 //////////////////////////
2995 // aliases for detected //
2996 //////////////////////////
2997
2998 template<typename T>
2999 using mapped_type_t = typename T::mapped_type;
3000
3001 template<typename T>
3002 using key_type_t = typename T::key_type;
3003
3004 template<typename T>
3005 using value_type_t = typename T::value_type;
3006
3007 template<typename T>
3008 using difference_type_t = typename T::difference_type;
3009
3010 template<typename T>
3011 using pointer_t = typename T::pointer;
3012
3013 template<typename T>
3014 using reference_t = typename T::reference;
3015
3016 template<typename T>
3017 using iterator_category_t = typename T::iterator_category;
3018
3019 template<typename T>
3020 using iterator_t = typename T::iterator;
3021
3022 template<typename T, typename... Args>
3023 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3024
3025 template<typename T, typename... Args>
3026 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3027
3028 template<typename T, typename U>
3029 using get_template_function = decltype(std::declval<T>().template get<U>());
3030
3031 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3032 template<typename BasicJsonType, typename T, typename = void>
3033 struct has_from_json : std::false_type {};
3034
3035 // trait checking if j.get<T> is valid
3036 // use this trait instead of std::is_constructible or std::is_convertible,
3037 // both rely on, or make use of implicit conversions, and thus fail when T
3038 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3039 template <typename BasicJsonType, typename T>
3040 struct is_getable
2563041 {
3042 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
2573043 };
2583044
259 NLOHMANN_BASIC_JSON_TPL_DECLARATION
260 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type
3045 template<typename BasicJsonType, typename T>
3046 struct has_from_json < BasicJsonType, T,
3047 enable_if_t < !is_basic_json<T>::value >>
2613048 {
3049 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3050
3051 static constexpr bool value =
3052 is_detected_exact<void, from_json_function, serializer,
3053 const BasicJsonType&, T&>::value;
2623054 };
2633055
264 // alias templates to reduce boilerplate
265 template <bool B, typename T = void>
266 using enable_if_t = typename std::enable_if<B, T>::type;
267
268 template <typename T>
269 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
270
271 // implementation of C++14 index_sequence and affiliates
272 // source: https://stackoverflow.com/a/32223343
273 template <std::size_t... Ints>
274 struct index_sequence
3056 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3057 // this overload is used for non-default-constructible user-defined-types
3058 template<typename BasicJsonType, typename T, typename = void>
3059 struct has_non_default_from_json : std::false_type {};
3060
3061 template<typename BasicJsonType, typename T>
3062 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
2753063 {
276 using type = index_sequence;
277 using value_type = std::size_t;
278 static constexpr std::size_t size() noexcept
279 {
280 return sizeof...(Ints);
281 }
3064 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3065
3066 static constexpr bool value =
3067 is_detected_exact<T, from_json_function, serializer,
3068 const BasicJsonType&>::value;
2823069 };
2833070
284 template <class Sequence1, class Sequence2>
285 struct merge_and_renumber;
286
287 template <std::size_t... I1, std::size_t... I2>
288 struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>> : index_sequence<I1..., (sizeof...(I1) + I2)...>
3071 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3072 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3073 template<typename BasicJsonType, typename T, typename = void>
3074 struct has_to_json : std::false_type {};
3075
3076 template<typename BasicJsonType, typename T>
3077 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
2893078 {
3079 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3080
3081 static constexpr bool value =
3082 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3083 T>::value;
2903084 };
2913085
292 template <std::size_t N>
293 struct make_index_sequence : merge_and_renumber<typename make_index_sequence<N / 2>::type, typename make_index_sequence<N - N / 2>::type>
3086
3087 ///////////////////
3088 // is_ functions //
3089 ///////////////////
3090
3091 template<typename T, typename = void>
3092 struct is_iterator_traits : std::false_type {};
3093
3094 template<typename T>
3095 struct is_iterator_traits<iterator_traits<T>>
2943096 {
3097 private:
3098 using traits = iterator_traits<T>;
3099
3100 public:
3101 static constexpr auto value =
3102 is_detected<value_type_t, traits>::value &&
3103 is_detected<difference_type_t, traits>::value &&
3104 is_detected<pointer_t, traits>::value &&
3105 is_detected<iterator_category_t, traits>::value &&
3106 is_detected<reference_t, traits>::value;
2953107 };
2963108
297 template <>
298 struct make_index_sequence<0> : index_sequence<>
3109 // source: https://stackoverflow.com/a/37193089/4116453
3110
3111 template<typename T, typename = void>
3112 struct is_complete_type : std::false_type {};
3113
3114 template<typename T>
3115 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3116
3117 template<typename BasicJsonType, typename CompatibleObjectType,
3118 typename = void>
3119 struct is_compatible_object_type_impl : std::false_type {};
3120
3121 template<typename BasicJsonType, typename CompatibleObjectType>
3122 struct is_compatible_object_type_impl <
3123 BasicJsonType, CompatibleObjectType,
3124 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3125 is_detected<key_type_t, CompatibleObjectType>::value >>
2993126 {
3127
3128 using object_t = typename BasicJsonType::object_t;
3129
3130 // macOS's is_constructible does not play well with nonesuch...
3131 static constexpr bool value =
3132 std::is_constructible<typename object_t::key_type,
3133 typename CompatibleObjectType::key_type>::value &&
3134 std::is_constructible<typename object_t::mapped_type,
3135 typename CompatibleObjectType::mapped_type>::value;
3003136 };
301 template <>
302 struct make_index_sequence<1> : index_sequence<0>
3137
3138 template<typename BasicJsonType, typename CompatibleObjectType>
3139 struct is_compatible_object_type
3140 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3141
3142 template<typename BasicJsonType, typename ConstructibleObjectType,
3143 typename = void>
3144 struct is_constructible_object_type_impl : std::false_type {};
3145
3146 template<typename BasicJsonType, typename ConstructibleObjectType>
3147 struct is_constructible_object_type_impl <
3148 BasicJsonType, ConstructibleObjectType,
3149 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3150 is_detected<key_type_t, ConstructibleObjectType>::value >>
3033151 {
3152 using object_t = typename BasicJsonType::object_t;
3153
3154 static constexpr bool value =
3155 (std::is_default_constructible<ConstructibleObjectType>::value &&
3156 (std::is_move_assignable<ConstructibleObjectType>::value ||
3157 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3158 (std::is_constructible<typename ConstructibleObjectType::key_type,
3159 typename object_t::key_type>::value &&
3160 std::is_same <
3161 typename object_t::mapped_type,
3162 typename ConstructibleObjectType::mapped_type >::value)) ||
3163 (has_from_json<BasicJsonType,
3164 typename ConstructibleObjectType::mapped_type>::value ||
3165 has_non_default_from_json <
3166 BasicJsonType,
3167 typename ConstructibleObjectType::mapped_type >::value);
3043168 };
3053169
306 template <typename... Ts>
307 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
308
309 /*
310 Implementation of two C++17 constructs: conjunction, negation. This is needed
311 to avoid evaluating all the traits in a condition
312
313 For example: not std::is_same<void, T>::value and has_value_type<T>::value
314 will not compile when T = void (on MSVC at least). Whereas
315 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
316 stop evaluating if negation<...>::value == false
317
318 Please note that those constructs must be used with caution, since symbols can
319 become very long quickly (which can slow down compilation and cause MSVC
320 internal compiler errors). Only use it when you have to (see example ahead).
321 */
322 template <class...>
323 struct conjunction : std::true_type
3170 template<typename BasicJsonType, typename ConstructibleObjectType>
3171 struct is_constructible_object_type
3172 : is_constructible_object_type_impl<BasicJsonType,
3173 ConstructibleObjectType> {};
3174
3175 template<typename BasicJsonType, typename CompatibleStringType,
3176 typename = void>
3177 struct is_compatible_string_type_impl : std::false_type {};
3178
3179 template<typename BasicJsonType, typename CompatibleStringType>
3180 struct is_compatible_string_type_impl <
3181 BasicJsonType, CompatibleStringType,
3182 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3183 value_type_t, CompatibleStringType>::value >>
3243184 {
3185 static constexpr auto value =
3186 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3253187 };
326 template <class B1>
327 struct conjunction<B1> : B1
3188
3189 template<typename BasicJsonType, typename ConstructibleStringType>
3190 struct is_compatible_string_type
3191 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3192
3193 template<typename BasicJsonType, typename ConstructibleStringType,
3194 typename = void>
3195 struct is_constructible_string_type_impl : std::false_type {};
3196
3197 template<typename BasicJsonType, typename ConstructibleStringType>
3198 struct is_constructible_string_type_impl <
3199 BasicJsonType, ConstructibleStringType,
3200 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3201 value_type_t, ConstructibleStringType>::value >>
3283202 {
3203 static constexpr auto value =
3204 std::is_constructible<ConstructibleStringType,
3205 typename BasicJsonType::string_t>::value;
3293206 };
330 template <class B1, class... Bn>
331 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type
3207
3208 template<typename BasicJsonType, typename ConstructibleStringType>
3209 struct is_constructible_string_type
3210 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3211
3212 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3213 struct is_compatible_array_type_impl : std::false_type {};
3214
3215 template<typename BasicJsonType, typename CompatibleArrayType>
3216 struct is_compatible_array_type_impl <
3217 BasicJsonType, CompatibleArrayType,
3218 enable_if_t < is_detected<value_type_t, CompatibleArrayType>::value&&
3219 is_detected<iterator_t, CompatibleArrayType>::value&&
3220 // This is needed because json_reverse_iterator has a ::iterator type...
3221 // Therefore it is detected as a CompatibleArrayType.
3222 // The real fix would be to have an Iterable concept.
3223 !is_iterator_traits <
3224 iterator_traits<CompatibleArrayType >>::value >>
3323225 {
3226 static constexpr bool value =
3227 std::is_constructible<BasicJsonType,
3228 typename CompatibleArrayType::value_type>::value;
3333229 };
3343230
335 template <class B>
336 struct negation : std::integral_constant<bool, not B::value>
3231 template<typename BasicJsonType, typename CompatibleArrayType>
3232 struct is_compatible_array_type
3233 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3234
3235 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3236 struct is_constructible_array_type_impl : std::false_type {};
3237
3238 template<typename BasicJsonType, typename ConstructibleArrayType>
3239 struct is_constructible_array_type_impl <
3240 BasicJsonType, ConstructibleArrayType,
3241 enable_if_t<std::is_same<ConstructibleArrayType,
3242 typename BasicJsonType::value_type>::value >>
3243 : std::true_type {};
3244
3245 template<typename BasicJsonType, typename ConstructibleArrayType>
3246 struct is_constructible_array_type_impl <
3247 BasicJsonType, ConstructibleArrayType,
3248 enable_if_t < !std::is_same<ConstructibleArrayType,
3249 typename BasicJsonType::value_type>::value&&
3250 std::is_default_constructible<ConstructibleArrayType>::value&&
3251 (std::is_move_assignable<ConstructibleArrayType>::value ||
3252 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3253 is_detected<value_type_t, ConstructibleArrayType>::value&&
3254 is_detected<iterator_t, ConstructibleArrayType>::value&&
3255 is_complete_type <
3256 detected_t<value_type_t, ConstructibleArrayType >>::value >>
3373257 {
3258 static constexpr bool value =
3259 // This is needed because json_reverse_iterator has a ::iterator type,
3260 // furthermore, std::back_insert_iterator (and other iterators) have a
3261 // base class `iterator`... Therefore it is detected as a
3262 // ConstructibleArrayType. The real fix would be to have an Iterable
3263 // concept.
3264 !is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value &&
3265
3266 (std::is_same<typename ConstructibleArrayType::value_type,
3267 typename BasicJsonType::array_t::value_type>::value ||
3268 has_from_json<BasicJsonType,
3269 typename ConstructibleArrayType::value_type>::value ||
3270 has_non_default_from_json <
3271 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
3383272 };
3393273
340 // dispatch utility (taken from ranges-v3)
341 template <unsigned N>
342 struct priority_tag : priority_tag<N - 1>
343 {
344 };
345 template <>
346 struct priority_tag<0>
347 {
348 };
349
350 ////////////////////////
351 // has_/is_ functions //
352 ////////////////////////
353
354 // source: https://stackoverflow.com/a/37193089/4116453
355
356 template <typename T, typename = void>
357 struct is_complete_type : std::false_type
358 {
359 };
360
361 template <typename T>
362 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type
363 {
364 };
365
366 NLOHMANN_JSON_HAS_HELPER(mapped_type);
367 NLOHMANN_JSON_HAS_HELPER(key_type);
368 NLOHMANN_JSON_HAS_HELPER(value_type);
369 NLOHMANN_JSON_HAS_HELPER(iterator);
370
371 template <bool B, class RealType, class CompatibleObjectType>
372 struct is_compatible_object_type_impl : std::false_type
373 {
374 };
375
376 template <class RealType, class CompatibleObjectType>
377 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
378 {
379 static constexpr auto value = std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
380 std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
381 };
382
383 template <class BasicJsonType, class CompatibleObjectType>
384 struct is_compatible_object_type
385 {
386 static auto constexpr value = is_compatible_object_type_impl<
387 conjunction<negation<std::is_same<void, CompatibleObjectType>>, has_mapped_type<CompatibleObjectType>, has_key_type<CompatibleObjectType>>::value,
388 typename BasicJsonType::object_t, CompatibleObjectType>::value;
389 };
390
391 template <typename BasicJsonType, typename T>
392 struct is_basic_json_nested_type
393 {
394 static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or std::is_same<T, typename BasicJsonType::const_iterator>::value or
395 std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
396 std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
397 };
398
399 template <class BasicJsonType, class CompatibleArrayType>
400 struct is_compatible_array_type
401 {
402 static auto constexpr value =
403 conjunction<negation<std::is_same<void, CompatibleArrayType>>, negation<is_compatible_object_type<BasicJsonType, CompatibleArrayType>>,
404 negation<std::is_constructible<typename BasicJsonType::string_t, CompatibleArrayType>>,
405 negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>, has_value_type<CompatibleArrayType>,
406 has_iterator<CompatibleArrayType>>::value;
407 };
408
409 template <bool, typename, typename>
410 struct is_compatible_integer_type_impl : std::false_type
411 {
412 };
413
414 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
415 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
3274 template<typename BasicJsonType, typename ConstructibleArrayType>
3275 struct is_constructible_array_type
3276 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3277
3278 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3279 typename = void>
3280 struct is_compatible_integer_type_impl : std::false_type {};
3281
3282 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3283 struct is_compatible_integer_type_impl <
3284 RealIntegerType, CompatibleNumberIntegerType,
3285 enable_if_t < std::is_integral<RealIntegerType>::value&&
3286 std::is_integral<CompatibleNumberIntegerType>::value&&
3287 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4163288 {
4173289 // is there an assert somewhere on overflows?
4183290 using RealLimits = std::numeric_limits<RealIntegerType>;
4193291 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4203292
421 static constexpr auto value = std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and CompatibleLimits::is_integer and
422 RealLimits::is_signed == CompatibleLimits::is_signed;
3293 static constexpr auto value =
3294 std::is_constructible<RealIntegerType,
3295 CompatibleNumberIntegerType>::value &&
3296 CompatibleLimits::is_integer &&
3297 RealLimits::is_signed == CompatibleLimits::is_signed;
4233298 };
4243299
425 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
3300 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4263301 struct is_compatible_integer_type
3302 : is_compatible_integer_type_impl<RealIntegerType,
3303 CompatibleNumberIntegerType> {};
3304
3305 template<typename BasicJsonType, typename CompatibleType, typename = void>
3306 struct is_compatible_type_impl: std::false_type {};
3307
3308 template<typename BasicJsonType, typename CompatibleType>
3309 struct is_compatible_type_impl <
3310 BasicJsonType, CompatibleType,
3311 enable_if_t<is_complete_type<CompatibleType>::value >>
4273312 {
428 static constexpr auto value = is_compatible_integer_type_impl < std::is_integral<CompatibleNumberIntegerType>::value and
429 not std::is_same<bool, CompatibleNumberIntegerType>::value,
430 RealIntegerType, CompatibleNumberIntegerType > ::value;
3313 static constexpr bool value =
3314 has_to_json<BasicJsonType, CompatibleType>::value;
4313315 };
4323316
433 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
434 template <typename BasicJsonType, typename T>
435 struct has_from_json
436 {
437 private:
438 // also check the return type of from_json
439 template <typename U,
440 typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
441 static int detect(U&&);
442 static void detect(...);
443
444 public:
445 static constexpr bool value = std::is_integral<decltype(detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
446 };
447
448 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
449 // this overload is used for non-default-constructible user-defined-types
450 template <typename BasicJsonType, typename T>
451 struct has_non_default_from_json
452 {
453 private:
454 template <typename U, typename = enable_if_t<std::is_same<T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value>>
455 static int detect(U&&);
456 static void detect(...);
457
458 public:
459 static constexpr bool value = std::is_integral<decltype(detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
460 };
461
462 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
463 template <typename BasicJsonType, typename T>
464 struct has_to_json
465 {
466 private:
467 template <typename U, typename = decltype(uncvref_t<U>::to_json(std::declval<BasicJsonType&>(), std::declval<T>()))>
468 static int detect(U&&);
469 static void detect(...);
470
471 public:
472 static constexpr bool value = std::is_integral<decltype(detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
473 };
474
475 template <typename BasicJsonType, typename CompatibleCompleteType>
476 struct is_compatible_complete_type
477 {
478 static constexpr bool value = not std::is_base_of<std::istream, CompatibleCompleteType>::value and not is_basic_json<CompatibleCompleteType>::value and
479 not is_basic_json_nested_type<BasicJsonType, CompatibleCompleteType>::value and
480 has_to_json<BasicJsonType, CompatibleCompleteType>::value;
481 };
482
483 template <typename BasicJsonType, typename CompatibleType>
484 struct is_compatible_type : conjunction<is_complete_type<CompatibleType>, is_compatible_complete_type<BasicJsonType, CompatibleType>>
485 {
486 };
487
488 // taken from ranges-v3
489 template <typename T>
490 struct static_const
491 {
492 static constexpr T value{};
493 };
494
495 template <typename T>
496 constexpr T static_const<T>::value;
497 }
498 }
499
500 // #include <nlohmann/detail/exceptions.hpp>
501
502
503 #include <exception> // exception
504 #include <stdexcept> // runtime_error
505 #include <string> // to_string
506
507 namespace nlohmann
508 {
509 namespace detail
510 {
511 ////////////////
512 // exceptions //
513 ////////////////
514
515 /*!
516 @brief general exception of the @ref basic_json class
517
518 This class is an extension of `std::exception` objects with a member @a id for
519 exception ids. It is used as the base class for all exceptions thrown by the
520 @ref basic_json class. This class can hence be used as "wildcard" to catch
521 exceptions.
522
523 Subclasses:
524 - @ref parse_error for exceptions indicating a parse error
525 - @ref invalid_iterator for exceptions indicating errors with iterators
526 - @ref type_error for exceptions indicating executing a member function with
527 a wrong type
528 - @ref out_of_range for exceptions indicating access out of the defined range
529 - @ref other_error for exceptions indicating other library errors
530
531 @internal
532 @note To have nothrow-copy-constructible exceptions, we internally use
533 `std::runtime_error` which can cope with arbitrary-length error messages.
534 Intermediate strings are built with static functions and then passed to
535 the actual constructor.
536 @endinternal
537
538 @liveexample{The following code shows how arbitrary library exceptions can be
539 caught.,exception}
540
541 @since version 3.0.0
542 */
543 class exception : public std::exception
544 {
545 public:
546 /// returns the explanatory string
547 const char* what() const noexcept override
548 {
549 return m.what();
550 }
551
552 /// the id of the exception
553 const int id;
554
555 protected:
556 exception(int id_, const char* what_arg) : id(id_), m(what_arg)
557 {
558 }
559
560 static std::string name(const std::string& ename, int id_)
561 {
562 return "[json.exception." + ename + "." + cpt::to_string(id_) + "] ";
563 }
564
565 private:
566 /// an exception object as storage for error messages
567 std::runtime_error m;
568 };
569
570 /*!
571 @brief exception indicating a parse error
572
573 This exception is thrown by the library when a parse error occurs. Parse errors
574 can occur during the deserialization of JSON text, CBOR, MessagePack, as well
575 as when using JSON Patch.
576
577 Member @a byte holds the byte index of the last read character in the input
578 file.
579
580 Exceptions have ids 1xx.
581
582 name / id | example message | description
583 ------------------------------ | --------------- | -------------------------
584 json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a
585 JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
586 json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points
587 above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid
588 code point.
589 json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF
590 are invalid.
591 json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch
592 document to be a JSON document that represents an array of objects.
593 json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op"
594 member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
595 json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC
596 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
597 json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a
598 sequence of zero or more reference tokens, each prefixed by a `/` character.
599 json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape
600 sequences.
601 json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
602 json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete
603 value has been read.
604 json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception
605 occurs if an unsupported byte was read.
606 json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been
607 read.
608
609 @note For an input with n bytes, 1 is the index of the first character and n+1
610 is the index of the terminating null byte or the end of file. This also
611 holds true when reading a byte vector (CBOR or MessagePack).
612
613 @liveexample{The following code shows how a `parse_error` exception can be
614 caught.,parse_error}
615
616 @sa @ref exception for the base class of the library exceptions
617 @sa @ref invalid_iterator for exceptions indicating errors with iterators
618 @sa @ref type_error for exceptions indicating executing a member function with
619 a wrong type
620 @sa @ref out_of_range for exceptions indicating access out of the defined range
621 @sa @ref other_error for exceptions indicating other library errors
622
623 @since version 3.0.0
624 */
625 class parse_error : public exception
626 {
627 public:
628 /*!
629 @brief create a parse error exception
630 @param[in] id_ the id of the exception
631 @param[in] byte_ the byte index where the error occurred (or 0 if the
632 position cannot be determined)
633 @param[in] what_arg the explanatory string
634 @return parse_error object
635 */
636 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
637 {
638 std::string w = exception::name("parse_error", id_) + "parse error" + (byte_ != 0 ? (" at " + cpt::to_string(byte_)) : "") + ": " + what_arg;
639 return parse_error(id_, byte_, w.c_str());
640 }
641
642 /*!
643 @brief byte index of the parse error
644
645 The byte index of the last read character in the input file.
646
647 @note For an input with n bytes, 1 is the index of the first character and
648 n+1 is the index of the terminating null byte or the end of file.
649 This also holds true when reading a byte vector (CBOR or MessagePack).
650 */
651 const std::size_t byte;
652
653 private:
654 parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_)
655 {
656 }
657 };
658
659 /*!
660 @brief exception indicating errors with iterators
661
662 This exception is thrown if iterators passed to a library function do not match
663 the expected semantics.
664
665 Exceptions have ids 2xx.
666
667 name / id | example message | description
668 ----------------------------------- | --------------- | -------------------------
669 json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not
670 compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
671 json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the
672 JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
673 json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last)
674 does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
675 json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a
676 constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed.
677 All other ranges are invalid.
678 json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function,
679 the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
680 json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT
681 last) belong to a JSON null value and hence to not define a valid range.
682 json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON
683 object, because other types do not have a concept of a key.
684 json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators
685 belonging to a JSON object, because JSON objects are unordered.
686 json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a
687 JSON object, because JSON objects are unordered.
688 json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to
689 the same container. Therefore, the range (@a first, @a last) is invalid.
690 json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of
691 the container to insert to.
692 json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same
693 container.
694 json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are
695 unordered.
696 json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a
697 primitive type (number, boolean, or string), but the iterator is different to @ref begin().
698
699 @liveexample{The following code shows how an `invalid_iterator` exception can be
700 caught.,invalid_iterator}
701
702 @sa @ref exception for the base class of the library exceptions
703 @sa @ref parse_error for exceptions indicating a parse error
704 @sa @ref type_error for exceptions indicating executing a member function with
705 a wrong type
706 @sa @ref out_of_range for exceptions indicating access out of the defined range
707 @sa @ref other_error for exceptions indicating other library errors
708
709 @since version 3.0.0
710 */
711 class invalid_iterator : public exception
712 {
713 public:
714 static invalid_iterator create(int id_, const std::string& what_arg)
715 {
716 std::string w = exception::name("invalid_iterator", id_) + what_arg;
717 return invalid_iterator(id_, w.c_str());
718 }
719
720 private:
721 invalid_iterator(int id_, const char* what_arg) : exception(id_, what_arg)
722 {
723 }
724 };
725
726 /*!
727 @brief exception indicating executing a member function with a wrong type
728
729 This exception is thrown in case of a type error; that is, a library function is
730 executed on a JSON value whose type does not match the expected semantics.
731
732 Exceptions have ids 3xx.
733
734 name / id | example message | description
735 ----------------------------- | --------------- | -------------------------
736 json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist
737 only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
738 json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target
739 type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
740 json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json
741 object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
742 json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
743 json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
744 json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
745 json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
746 json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain
747 JSON types.
748 json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
749 json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
750 json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
751 json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
752 json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary
753 nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
754 json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
755 json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose
756 values are primitive.
757 json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a
758 `std::string` to a JSON value, make sure it is UTF-8 encoded. |
759
760 @liveexample{The following code shows how a `type_error` exception can be
761 caught.,type_error}
762
763 @sa @ref exception for the base class of the library exceptions
764 @sa @ref parse_error for exceptions indicating a parse error
765 @sa @ref invalid_iterator for exceptions indicating errors with iterators
766 @sa @ref out_of_range for exceptions indicating access out of the defined range
767 @sa @ref other_error for exceptions indicating other library errors
768
769 @since version 3.0.0
770 */
771 class type_error : public exception
772 {
773 public:
774 static type_error create(int id_, const std::string& what_arg)
775 {
776 std::string w = exception::name("type_error", id_) + what_arg;
777 return type_error(id_, w.c_str());
778 }
779
780 private:
781 type_error(int id_, const char* what_arg) : exception(id_, what_arg)
782 {
783 }
784 };
785
786 /*!
787 @brief exception indicating access out of the defined range
788
789 This exception is thrown in case a library function is called on an input
790 parameter that exceeds the expected range, for instance in case of array
791 indices or nonexisting object keys.
792
793 Exceptions have ids 4xx.
794
795 name / id | example message | description
796 ------------------------------- | --------------- | -------------------------
797 json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
798 json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the
799 array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
800 json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
801 json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
802 json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON
803 value.
804 json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
805 json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
806 json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal
807 capacity. |
808
809 @liveexample{The following code shows how an `out_of_range` exception can be
810 caught.,out_of_range}
811
812 @sa @ref exception for the base class of the library exceptions
813 @sa @ref parse_error for exceptions indicating a parse error
814 @sa @ref invalid_iterator for exceptions indicating errors with iterators
815 @sa @ref type_error for exceptions indicating executing a member function with
816 a wrong type
817 @sa @ref other_error for exceptions indicating other library errors
818
819 @since version 3.0.0
820 */
821 class out_of_range : public exception
822 {
823 public:
824 static out_of_range create(int id_, const std::string& what_arg)
825 {
826 std::string w = exception::name("out_of_range", id_) + what_arg;
827 return out_of_range(id_, w.c_str());
828 }
829
830 private:
831 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg)
832 {
833 }
834 };
835
836 /*!
837 @brief exception indicating other library errors
838
839 This exception is thrown in case of errors that cannot be classified with the
840 other exception types.
841
842 Exceptions have ids 5xx.
843
844 name / id | example message | description
845 ------------------------------ | --------------- | -------------------------
846 json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is
847 also printed.
848
849 @sa @ref exception for the base class of the library exceptions
850 @sa @ref parse_error for exceptions indicating a parse error
851 @sa @ref invalid_iterator for exceptions indicating errors with iterators
852 @sa @ref type_error for exceptions indicating executing a member function with
853 a wrong type
854 @sa @ref out_of_range for exceptions indicating access out of the defined range
855
856 @liveexample{The following code shows how an `other_error` exception can be
857 caught.,other_error}
858
859 @since version 3.0.0
860 */
861 class other_error : public exception
862 {
863 public:
864 static other_error create(int id_, const std::string& what_arg)
865 {
866 std::string w = exception::name("other_error", id_) + what_arg;
867 return other_error(id_, w.c_str());
868 }
869
870 private:
871 other_error(int id_, const char* what_arg) : exception(id_, what_arg)
872 {
873 }
874 };
875 }
876 }
3317 template<typename BasicJsonType, typename CompatibleType>
3318 struct is_compatible_type
3319 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3320
3321 // https://en.cppreference.com/w/cpp/types/conjunction
3322 template<class...> struct conjunction : std::true_type { };
3323 template<class B1> struct conjunction<B1> : B1 { };
3324 template<class B1, class... Bn>
3325 struct conjunction<B1, Bn...>
3326 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3327
3328 template<typename T1, typename T2>
3329 struct is_constructible_tuple : std::false_type {};
3330
3331 template<typename T1, typename... Args>
3332 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
3333 } // namespace detail
3334 } // namespace nlohmann
8773335
8783336 // #include <nlohmann/detail/value_t.hpp>
8793337
8803338
881 #include <array> // array
882 #include <ciso646> // and
3339 #include <array> // array
8833340 #include <cstddef> // size_t
8843341 #include <cstdint> // uint8_t
3342 #include <string> // string
8853343
8863344 namespace nlohmann
8873345 {
9173375 */
9183376 enum class value_t : std::uint8_t
9193377 {
920 null, ///< null value
921 object, ///< object (unordered set of name/value pairs)
922 array, ///< array (ordered collection of values)
923 string, ///< string value
924 boolean, ///< boolean value
925 number_integer, ///< number value (signed integer)
926 number_unsigned, ///< number value (unsigned integer)
927 number_float, ///< number value (floating-point)
928 discarded ///< discarded by the the parser callback function
3378 null, ///< null value
3379 object, ///< object (unordered set of name/value pairs)
3380 array, ///< array (ordered collection of values)
3381 string, ///< string value
3382 boolean, ///< boolean value
3383 number_integer, ///< number value (signed integer)
3384 number_unsigned, ///< number value (unsigned integer)
3385 number_float, ///< number value (floating-point)
3386 binary, ///< binary array (ordered collection of bytes)
3387 discarded ///< discarded by the parser callback function
9293388 };
9303389
9313390 /*!
9323391 @brief comparison operator for JSON types
9333392
9343393 Returns an ordering that is similar to Python:
935 - order: null < boolean < number < object < array < string
3394 - order: null < boolean < number < object < array < string < binary
9363395 - furthermore, each type is not smaller than itself
9373396 - discarded values are not comparable
3397 - binary is represented as a b"" string in python and directly comparable to a
3398 string; however, making a binary array directly comparable with a string would
3399 be surprising behavior in a JSON file.
9383400
9393401 @since version 1.0.0
9403402 */
9413403 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
9423404 {
943 static constexpr std::array<std::uint8_t, 8> order = {{
944 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
945 }};
3405 static constexpr std::array<std::uint8_t, 9> order = {{
3406 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3407 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3408 6 /* binary */
3409 }
3410 };
9463411
9473412 const auto l_index = static_cast<std::size_t>(lhs);
9483413 const auto r_index = static_cast<std::size_t>(rhs);
949 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
3414 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
9503415 }
951 }
952 }
953
954 // #include <nlohmann/detail/conversions/from_json.hpp>
955
956
957 #include <algorithm> // transform
958 #include <array> // array
959 #include <ciso646> // and, not
960 #include <forward_list> // forward_list
961 #include <iterator> // inserter, front_inserter, end
962 #include <string> // string
963 #include <tuple> // tuple, make_tuple
964 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
965 #include <utility> // pair, declval
966 #include <valarray> // valarray
967
968 // #include <nlohmann/detail/exceptions.hpp>
969
970 // #include <nlohmann/detail/macro_scope.hpp>
971
972 // #include <nlohmann/detail/meta.hpp>
973
974 // #include <nlohmann/detail/value_t.hpp>
3416 } // namespace detail
3417 } // namespace nlohmann
9753418
9763419
9773420 namespace nlohmann
9783421 {
9793422 namespace detail
9803423 {
3424 template<typename BasicJsonType>
3425 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3426 {
3427 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3428 {
3429 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
3430 }
3431 n = nullptr;
3432 }
3433
9813434 // overloads for basic_json template parameters
982 template <typename BasicJsonType, typename ArithmeticType,
983 enable_if_t<std::is_arithmetic<ArithmeticType>::value and not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int> = 0>
3435 template < typename BasicJsonType, typename ArithmeticType,
3436 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3437 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3438 int > = 0 >
9843439 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
9853440 {
9863441 switch (static_cast<value_t>(j))
10063461 }
10073462 }
10083463
1009 template <typename BasicJsonType>
3464 template<typename BasicJsonType>
10103465 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
10113466 {
1012 if (JSON_UNLIKELY(not j.is_boolean()))
3467 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
10133468 {
10143469 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
10153470 }
10163471 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
10173472 }
10183473
1019 template <typename BasicJsonType>
3474 template<typename BasicJsonType>
10203475 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
10213476 {
1022 if (JSON_UNLIKELY(not j.is_string()))
3477 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
10233478 {
10243479 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
10253480 }
10263481 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
10273482 }
10283483
1029 template <typename BasicJsonType>
3484 template <
3485 typename BasicJsonType, typename ConstructibleStringType,
3486 enable_if_t <
3487 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3488 !std::is_same<typename BasicJsonType::string_t,
3489 ConstructibleStringType>::value,
3490 int > = 0 >
3491 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3492 {
3493 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3494 {
3495 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
3496 }
3497
3498 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3499 }
3500
3501 template<typename BasicJsonType>
10303502 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
10313503 {
10323504 get_arithmetic_value(j, val);
10333505 }
10343506
1035 template <typename BasicJsonType>
3507 template<typename BasicJsonType>
10363508 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
10373509 {
10383510 get_arithmetic_value(j, val);
10393511 }
10403512
1041 template <typename BasicJsonType>
3513 template<typename BasicJsonType>
10423514 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
10433515 {
10443516 get_arithmetic_value(j, val);
10453517 }
10463518
1047 template <typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3519 template<typename BasicJsonType, typename EnumType,
3520 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
10483521 void from_json(const BasicJsonType& j, EnumType& e)
10493522 {
10503523 typename std::underlying_type<EnumType>::type val;
10523525 e = static_cast<EnumType>(val);
10533526 }
10543527
1055 template <typename BasicJsonType>
1056 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
3528 // forward_list doesn't have an insert method
3529 template<typename BasicJsonType, typename T, typename Allocator,
3530 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3531 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
10573532 {
1058 if (JSON_UNLIKELY(not j.is_array()))
3533 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
10593534 {
10603535 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
10613536 }
3537 l.clear();
3538 std::transform(j.rbegin(), j.rend(),
3539 std::front_inserter(l), [](const BasicJsonType & i)
3540 {
3541 return i.template get<T>();
3542 });
3543 }
3544
3545 // valarray doesn't have an insert method
3546 template<typename BasicJsonType, typename T,
3547 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3548 void from_json(const BasicJsonType& j, std::valarray<T>& l)
3549 {
3550 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3551 {
3552 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3553 }
3554 l.resize(j.size());
3555 std::transform(j.begin(), j.end(), std::begin(l),
3556 [](const BasicJsonType & elem)
3557 {
3558 return elem.template get<T>();
3559 });
3560 }
3561
3562 template<typename BasicJsonType, typename T, std::size_t N>
3563 auto from_json(const BasicJsonType& j, T (&arr)[N])
3564 -> decltype(j.template get<T>(), void())
3565 {
3566 for (std::size_t i = 0; i < N; ++i)
3567 {
3568 arr[i] = j.at(i).template get<T>();
3569 }
3570 }
3571
3572 template<typename BasicJsonType>
3573 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3574 {
10623575 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
10633576 }
10643577
1065 // forward_list doesn't have an insert method
1066 template <typename BasicJsonType, typename T, typename Allocator, enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1067 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3578 template<typename BasicJsonType, typename T, std::size_t N>
3579 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3580 priority_tag<2> /*unused*/)
3581 -> decltype(j.template get<T>(), void())
10683582 {
1069 if (JSON_UNLIKELY(not j.is_array()))
1070 {
1071 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1072 }
1073 std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType& i) { return i.template get<T>(); });
3583 for (std::size_t i = 0; i < N; ++i)
3584 {
3585 arr[i] = j.at(i).template get<T>();
3586 }
10743587 }
10753588
1076 // valarray doesn't have an insert method
1077 template <typename BasicJsonType, typename T, enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1078 void from_json(const BasicJsonType& j, std::valarray<T>& l)
1079 {
1080 if (JSON_UNLIKELY(not j.is_array()))
1081 {
1082 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1083 }
1084 l.resize(j.size());
1085 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1086 }
1087
1088 template <typename BasicJsonType, typename CompatibleArrayType>
1089 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
3589 template<typename BasicJsonType, typename ConstructibleArrayType>
3590 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
3591 -> decltype(
3592 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
3593 j.template get<typename ConstructibleArrayType::value_type>(),
3594 void())
10903595 {
10913596 using std::end;
10923597
1093 std::transform(j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType& i) {
3598 ConstructibleArrayType ret;
3599 ret.reserve(j.size());
3600 std::transform(j.begin(), j.end(),
3601 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
3602 {
10943603 // get<BasicJsonType>() returns *this, this won't call a from_json
10953604 // method when value_type is BasicJsonType
1096 return i.template get<typename CompatibleArrayType::value_type>();
3605 return i.template get<typename ConstructibleArrayType::value_type>();
10973606 });
3607 arr = std::move(ret);
10983608 }
10993609
1100 template <typename BasicJsonType, typename CompatibleArrayType>
1101 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
1102 -> decltype(arr.reserve(std::declval<typename CompatibleArrayType::size_type>()), void())
3610 template<typename BasicJsonType, typename ConstructibleArrayType>
3611 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
3612 priority_tag<0> /*unused*/)
11033613 {
11043614 using std::end;
11053615
1106 arr.reserve(j.size());
1107 std::transform(j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType& i) {
3616 ConstructibleArrayType ret;
3617 std::transform(
3618 j.begin(), j.end(), std::inserter(ret, end(ret)),
3619 [](const BasicJsonType & i)
3620 {
11083621 // get<BasicJsonType>() returns *this, this won't call a from_json
11093622 // method when value_type is BasicJsonType
1110 return i.template get<typename CompatibleArrayType::value_type>();
3623 return i.template get<typename ConstructibleArrayType::value_type>();
11113624 });
3625 arr = std::move(ret);
11123626 }
11133627
1114 template <typename BasicJsonType, typename T, std::size_t N>
1115 void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
3628 template < typename BasicJsonType, typename ConstructibleArrayType,
3629 enable_if_t <
3630 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
3631 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
3632 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3633 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
3634 !is_basic_json<ConstructibleArrayType>::value,
3635 int > = 0 >
3636 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
3637 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
3638 j.template get<typename ConstructibleArrayType::value_type>(),
3639 void())
11163640 {
1117 for (std::size_t i = 0; i < N; ++i)
1118 {
1119 arr[i] = j.at(i).template get<T>();
1120 }
3641 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3642 {
3643 JSON_THROW(type_error::create(302, "type must be array, but is " +
3644 std::string(j.type_name())));
3645 }
3646
3647 from_json_array_impl(j, arr, priority_tag<3> {});
11213648 }
11223649
1123 template <typename BasicJsonType, typename CompatibleArrayType,
1124 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
1125 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value and
1126 std::is_constructible<BasicJsonType, typename CompatibleArrayType::value_type>::value,
1127 int> = 0>
1128 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
3650 template<typename BasicJsonType>
3651 void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
11293652 {
1130 if (JSON_UNLIKELY(not j.is_array()))
1131 {
1132 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1133 }
1134
1135 from_json_array_impl(j, arr, priority_tag<2>{});
3653 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
3654 {
3655 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
3656 }
3657
3658 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
11363659 }
11373660
1138 template <typename BasicJsonType, typename CompatibleObjectType, enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1139 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
3661 template<typename BasicJsonType, typename ConstructibleObjectType,
3662 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
3663 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
11403664 {
1141 if (JSON_UNLIKELY(not j.is_object()))
3665 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
11423666 {
11433667 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
11443668 }
11453669
3670 ConstructibleObjectType ret;
11463671 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1147 using value_type = typename CompatibleObjectType::value_type;
1148 std::transform(inner_object->begin(), inner_object->end(), std::inserter(obj, obj.begin()), [](typename BasicJsonType::object_t::value_type const& p) {
1149 return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
3672 using value_type = typename ConstructibleObjectType::value_type;
3673 std::transform(
3674 inner_object->begin(), inner_object->end(),
3675 std::inserter(ret, ret.begin()),
3676 [](typename BasicJsonType::object_t::value_type const & p)
3677 {
3678 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
11503679 });
3680 obj = std::move(ret);
11513681 }
11523682
11533683 // overload for arithmetic types, not chosen for basic_json template arguments
11543684 // (BooleanType, etc..); note: Is it really necessary to provide explicit
11553685 // overloads for boolean_t etc. in case of a custom BooleanType which is not
11563686 // an arithmetic type?
1157 template <typename BasicJsonType, typename ArithmeticType,
1158 enable_if_t<std::is_arithmetic<ArithmeticType>::value and not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1159 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1160 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1161 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1162 int> = 0>
3687 template < typename BasicJsonType, typename ArithmeticType,
3688 enable_if_t <
3689 std::is_arithmetic<ArithmeticType>::value&&
3690 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
3691 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
3692 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
3693 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3694 int > = 0 >
11633695 void from_json(const BasicJsonType& j, ArithmeticType& val)
11643696 {
11653697 switch (static_cast<value_t>(j))
11903722 }
11913723 }
11923724
1193 template <typename BasicJsonType, typename A1, typename A2>
3725 template<typename BasicJsonType, typename A1, typename A2>
11943726 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
11953727 {
11963728 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
11973729 }
11983730
1199 template <typename BasicJsonType, typename Tuple, std::size_t... Idx>
1200 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
3731 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
3732 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
12013733 {
12023734 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
12033735 }
12043736
1205 template <typename BasicJsonType, typename... Args>
3737 template<typename BasicJsonType, typename... Args>
12063738 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
12073739 {
1208 from_json_tuple_impl(j, t, index_sequence_for<Args...>{});
3740 from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
3741 }
3742
3743 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
3744 typename = enable_if_t < !std::is_constructible <
3745 typename BasicJsonType::string_t, Key >::value >>
3746 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
3747 {
3748 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3749 {
3750 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3751 }
3752 m.clear();
3753 for (const auto& p : j)
3754 {
3755 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3756 {
3757 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3758 }
3759 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3760 }
3761 }
3762
3763 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
3764 typename = enable_if_t < !std::is_constructible <
3765 typename BasicJsonType::string_t, Key >::value >>
3766 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
3767 {
3768 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3769 {
3770 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3771 }
3772 m.clear();
3773 for (const auto& p : j)
3774 {
3775 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3776 {
3777 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3778 }
3779 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3780 }
12093781 }
12103782
12113783 struct from_json_fn
12123784 {
1213 private:
1214 template <typename BasicJsonType, typename T>
1215 auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void())
3785 template<typename BasicJsonType, typename T>
3786 auto operator()(const BasicJsonType& j, T& val) const
3787 noexcept(noexcept(from_json(j, val)))
3788 -> decltype(from_json(j, val), void())
12163789 {
12173790 return from_json(j, val);
12183791 }
1219
1220 template <typename BasicJsonType, typename T>
1221 void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1222 {
1223 static_assert(sizeof(BasicJsonType) == 0, "could not find from_json() method in T's namespace");
1224 #ifdef _MSC_VER
1225 // MSVC does not show a stacktrace for the above assert
1226 using decayed = uncvref_t<T>;
1227 static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, "forcing MSVC stacktrace to show which T we're talking about.");
1228 #endif
1229 }
1230
1231 public:
1232 template <typename BasicJsonType, typename T>
1233 void operator()(const BasicJsonType& j, T& val) const noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1>{})))
1234 {
1235 return call(j, val, priority_tag<1>{});
1236 }
12373792 };
1238 }
3793 } // namespace detail
12393794
12403795 /// namespace to hold default `from_json` function
12413796 /// to see why this is required:
12433798 namespace
12443799 {
12453800 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
3801 } // namespace
3802 } // namespace nlohmann
3803
3804 // #include <nlohmann/detail/conversions/to_json.hpp>
3805
3806
3807 #include <algorithm> // copy
3808 #include <iterator> // begin, end
3809 #include <string> // string
3810 #include <tuple> // tuple, get
3811 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
3812 #include <utility> // move, forward, declval, pair
3813 #include <valarray> // valarray
3814 #include <vector> // vector
3815
3816 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
3817
3818
3819 #include <cstddef> // size_t
3820 #include <iterator> // input_iterator_tag
3821 #include <string> // string, to_string
3822 #include <tuple> // tuple_size, get, tuple_element
3823
3824 // #include <nlohmann/detail/meta/type_traits.hpp>
3825
3826 // #include <nlohmann/detail/value_t.hpp>
3827
3828
3829 namespace nlohmann
3830 {
3831 namespace detail
3832 {
3833 template<typename string_type>
3834 void int_to_string( string_type& target, std::size_t value )
3835 {
3836 // For ADL
3837 using std::to_string;
3838 target = to_string(value);
12463839 }
3840 template<typename IteratorType> class iteration_proxy_value
3841 {
3842 public:
3843 using difference_type = std::ptrdiff_t;
3844 using value_type = iteration_proxy_value;
3845 using pointer = value_type * ;
3846 using reference = value_type & ;
3847 using iterator_category = std::input_iterator_tag;
3848 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
3849
3850 private:
3851 /// the iterator
3852 IteratorType anchor;
3853 /// an index for arrays (used to create key names)
3854 std::size_t array_index = 0;
3855 /// last stringified array index
3856 mutable std::size_t array_index_last = 0;
3857 /// a string representation of the array index
3858 mutable string_type array_index_str = "0";
3859 /// an empty string (to return a reference for primitive values)
3860 const string_type empty_str = "";
3861
3862 public:
3863 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
3864
3865 /// dereference operator (needed for range-based for)
3866 iteration_proxy_value& operator*()
3867 {
3868 return *this;
3869 }
3870
3871 /// increment operator (needed for range-based for)
3872 iteration_proxy_value& operator++()
3873 {
3874 ++anchor;
3875 ++array_index;
3876
3877 return *this;
3878 }
3879
3880 /// equality operator (needed for InputIterator)
3881 bool operator==(const iteration_proxy_value& o) const
3882 {
3883 return anchor == o.anchor;
3884 }
3885
3886 /// inequality operator (needed for range-based for)
3887 bool operator!=(const iteration_proxy_value& o) const
3888 {
3889 return anchor != o.anchor;
3890 }
3891
3892 /// return key of the iterator
3893 const string_type& key() const
3894 {
3895 JSON_ASSERT(anchor.m_object != nullptr);
3896
3897 switch (anchor.m_object->type())
3898 {
3899 // use integer array index as key
3900 case value_t::array:
3901 {
3902 if (array_index != array_index_last)
3903 {
3904 int_to_string( array_index_str, array_index );
3905 array_index_last = array_index;
3906 }
3907 return array_index_str;
3908 }
3909
3910 // use key from the object
3911 case value_t::object:
3912 return anchor.key();
3913
3914 // use an empty key for all primitive types
3915 default:
3916 return empty_str;
3917 }
3918 }
3919
3920 /// return value of the iterator
3921 typename IteratorType::reference value() const
3922 {
3923 return anchor.value();
3924 }
3925 };
3926
3927 /// proxy class for the items() function
3928 template<typename IteratorType> class iteration_proxy
3929 {
3930 private:
3931 /// the container to iterate
3932 typename IteratorType::reference container;
3933
3934 public:
3935 /// construct iteration proxy from a container
3936 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
3937 : container(cont) {}
3938
3939 /// return iterator begin (needed for range-based for)
3940 iteration_proxy_value<IteratorType> begin() noexcept
3941 {
3942 return iteration_proxy_value<IteratorType>(container.begin());
3943 }
3944
3945 /// return iterator end (needed for range-based for)
3946 iteration_proxy_value<IteratorType> end() noexcept
3947 {
3948 return iteration_proxy_value<IteratorType>(container.end());
3949 }
3950 };
3951 // Structured Bindings Support
3952 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3953 // And see https://github.com/nlohmann/json/pull/1391
3954 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
3955 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
3956 {
3957 return i.key();
12473958 }
1248
1249 // #include <nlohmann/detail/conversions/to_json.hpp>
1250
1251
1252 #include <ciso646> // or, and, not
1253 #include <iterator> // begin, end
1254 #include <tuple> // tuple, get
1255 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1256 #include <utility> // move, forward, declval, pair
1257 #include <valarray> // valarray
1258 #include <vector> // vector
1259
1260 // #include <nlohmann/detail/meta.hpp>
3959 // Structured Bindings Support
3960 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3961 // And see https://github.com/nlohmann/json/pull/1391
3962 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
3963 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
3964 {
3965 return i.value();
3966 }
3967 } // namespace detail
3968 } // namespace nlohmann
3969
3970 // The Addition to the STD Namespace is required to add
3971 // Structured Bindings Support to the iteration_proxy_value class
3972 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3973 // And see https://github.com/nlohmann/json/pull/1391
3974 namespace std
3975 {
3976 #if defined(__clang__)
3977 // Fix: https://github.com/nlohmann/json/issues/1401
3978 #pragma clang diagnostic push
3979 #pragma clang diagnostic ignored "-Wmismatched-tags"
3980 #endif
3981 template<typename IteratorType>
3982 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
3983 : public std::integral_constant<std::size_t, 2> {};
3984
3985 template<std::size_t N, typename IteratorType>
3986 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
3987 {
3988 public:
3989 using type = decltype(
3990 get<N>(std::declval <
3991 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
3992 };
3993 #if defined(__clang__)
3994 #pragma clang diagnostic pop
3995 #endif
3996 } // namespace std
3997
3998 // #include <nlohmann/detail/meta/cpp_future.hpp>
3999
4000 // #include <nlohmann/detail/meta/type_traits.hpp>
12614001
12624002 // #include <nlohmann/detail/value_t.hpp>
12634003
12704010 // constructors //
12714011 //////////////////
12724012
1273 template <value_t>
1274 struct external_constructor;
1275
1276 template <>
4013 template<value_t> struct external_constructor;
4014
4015 template<>
12774016 struct external_constructor<value_t::boolean>
12784017 {
1279 template <typename BasicJsonType>
4018 template<typename BasicJsonType>
12804019 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
12814020 {
12824021 j.m_type = value_t::boolean;
12854024 }
12864025 };
12874026
1288 template <>
4027 template<>
12894028 struct external_constructor<value_t::string>
12904029 {
1291 template <typename BasicJsonType>
4030 template<typename BasicJsonType>
12924031 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
12934032 {
12944033 j.m_type = value_t::string;
12964035 j.assert_invariant();
12974036 }
12984037
1299 template <typename BasicJsonType>
4038 template<typename BasicJsonType>
13004039 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
13014040 {
13024041 j.m_type = value_t::string;
13034042 j.m_value = std::move(s);
13044043 j.assert_invariant();
13054044 }
4045
4046 template < typename BasicJsonType, typename CompatibleStringType,
4047 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4048 int > = 0 >
4049 static void construct(BasicJsonType& j, const CompatibleStringType& str)
4050 {
4051 j.m_type = value_t::string;
4052 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4053 j.assert_invariant();
4054 }
13064055 };
13074056
1308 template <>
4057 template<>
4058 struct external_constructor<value_t::binary>
4059 {
4060 template<typename BasicJsonType>
4061 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4062 {
4063 j.m_type = value_t::binary;
4064 typename BasicJsonType::binary_t value{b};
4065 j.m_value = value;
4066 j.assert_invariant();
4067 }
4068
4069 template<typename BasicJsonType>
4070 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4071 {
4072 j.m_type = value_t::binary;
4073 typename BasicJsonType::binary_t value{std::move(b)};
4074 j.m_value = value;
4075 j.assert_invariant();
4076 }
4077 };
4078
4079 template<>
13094080 struct external_constructor<value_t::number_float>
13104081 {
1311 template <typename BasicJsonType>
4082 template<typename BasicJsonType>
13124083 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
13134084 {
13144085 j.m_type = value_t::number_float;
13174088 }
13184089 };
13194090
1320 template <>
4091 template<>
13214092 struct external_constructor<value_t::number_unsigned>
13224093 {
1323 template <typename BasicJsonType>
4094 template<typename BasicJsonType>
13244095 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
13254096 {
13264097 j.m_type = value_t::number_unsigned;
13294100 }
13304101 };
13314102
1332 template <>
4103 template<>
13334104 struct external_constructor<value_t::number_integer>
13344105 {
1335 template <typename BasicJsonType>
4106 template<typename BasicJsonType>
13364107 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
13374108 {
13384109 j.m_type = value_t::number_integer;
13414112 }
13424113 };
13434114
1344 template <>
4115 template<>
13454116 struct external_constructor<value_t::array>
13464117 {
1347 template <typename BasicJsonType>
4118 template<typename BasicJsonType>
13484119 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
13494120 {
13504121 j.m_type = value_t::array;
13524123 j.assert_invariant();
13534124 }
13544125
1355 template <typename BasicJsonType>
4126 template<typename BasicJsonType>
13564127 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
13574128 {
13584129 j.m_type = value_t::array;
13604131 j.assert_invariant();
13614132 }
13624133
1363 template <typename BasicJsonType, typename CompatibleArrayType,
1364 enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, int> = 0>
4134 template < typename BasicJsonType, typename CompatibleArrayType,
4135 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4136 int > = 0 >
13654137 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
13664138 {
13674139 using std::begin;
13714143 j.assert_invariant();
13724144 }
13734145
1374 template <typename BasicJsonType>
4146 template<typename BasicJsonType>
13754147 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
13764148 {
13774149 j.m_type = value_t::array;
13844156 j.assert_invariant();
13854157 }
13864158
1387 template <typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4159 template<typename BasicJsonType, typename T,
4160 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
13884161 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
13894162 {
13904163 j.m_type = value_t::array;
13914164 j.m_value = value_t::array;
13924165 j.m_value.array->resize(arr.size());
1393 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4166 if (arr.size() > 0)
4167 {
4168 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4169 }
13944170 j.assert_invariant();
13954171 }
13964172 };
13974173
1398 template <>
4174 template<>
13994175 struct external_constructor<value_t::object>
14004176 {
1401 template <typename BasicJsonType>
4177 template<typename BasicJsonType>
14024178 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
14034179 {
14044180 j.m_type = value_t::object;
14064182 j.assert_invariant();
14074183 }
14084184
1409 template <typename BasicJsonType>
4185 template<typename BasicJsonType>
14104186 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
14114187 {
14124188 j.m_type = value_t::object;
14144190 j.assert_invariant();
14154191 }
14164192
1417 template <typename BasicJsonType, typename CompatibleObjectType,
1418 enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
4193 template < typename BasicJsonType, typename CompatibleObjectType,
4194 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
14194195 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
14204196 {
14214197 using std::begin;
14314207 // to_json //
14324208 /////////////
14334209
1434 template <typename BasicJsonType, typename T, enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4210 template<typename BasicJsonType, typename T,
4211 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
14354212 void to_json(BasicJsonType& j, T b) noexcept
14364213 {
14374214 external_constructor<value_t::boolean>::construct(j, b);
14384215 }
14394216
1440 template <typename BasicJsonType, typename CompatibleString,
1441 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4217 template<typename BasicJsonType, typename CompatibleString,
4218 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
14424219 void to_json(BasicJsonType& j, const CompatibleString& s)
14434220 {
14444221 external_constructor<value_t::string>::construct(j, s);
14454222 }
14464223
1447 template <typename BasicJsonType>
4224 template<typename BasicJsonType>
14484225 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
14494226 {
14504227 external_constructor<value_t::string>::construct(j, std::move(s));
14514228 }
14524229
1453 template <typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4230 template<typename BasicJsonType, typename FloatType,
4231 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
14544232 void to_json(BasicJsonType& j, FloatType val) noexcept
14554233 {
14564234 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
14574235 }
14584236
1459 template <typename BasicJsonType, typename CompatibleNumberUnsignedType,
1460 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4237 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4238 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
14614239 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
14624240 {
14634241 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
14644242 }
14654243
1466 template <typename BasicJsonType, typename CompatibleNumberIntegerType,
1467 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4244 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4245 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
14684246 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
14694247 {
14704248 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
14714249 }
14724250
1473 template <typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4251 template<typename BasicJsonType, typename EnumType,
4252 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
14744253 void to_json(BasicJsonType& j, EnumType e) noexcept
14754254 {
14764255 using underlying_type = typename std::underlying_type<EnumType>::type;
14774256 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
14784257 }
14794258
1480 template <typename BasicJsonType>
4259 template<typename BasicJsonType>
14814260 void to_json(BasicJsonType& j, const std::vector<bool>& e)
14824261 {
14834262 external_constructor<value_t::array>::construct(j, e);
14844263 }
14854264
1486 template <typename BasicJsonType, typename CompatibleArrayType, enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
1487 std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
1488 int> = 0>
4265 template < typename BasicJsonType, typename CompatibleArrayType,
4266 enable_if_t < is_compatible_array_type<BasicJsonType,
4267 CompatibleArrayType>::value&&
4268 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4269 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4270 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4271 !is_basic_json<CompatibleArrayType>::value,
4272 int > = 0 >
14894273 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
14904274 {
14914275 external_constructor<value_t::array>::construct(j, arr);
14924276 }
14934277
1494 template <typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1495 void to_json(BasicJsonType& j, std::valarray<T> arr)
4278 template<typename BasicJsonType>
4279 void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4280 {
4281 external_constructor<value_t::binary>::construct(j, bin);
4282 }
4283
4284 template<typename BasicJsonType, typename T,
4285 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4286 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
14964287 {
14974288 external_constructor<value_t::array>::construct(j, std::move(arr));
14984289 }
14994290
1500 template <typename BasicJsonType>
4291 template<typename BasicJsonType>
15014292 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
15024293 {
15034294 external_constructor<value_t::array>::construct(j, std::move(arr));
15044295 }
15054296
1506 template <typename BasicJsonType, typename CompatibleObjectType, enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
4297 template < typename BasicJsonType, typename CompatibleObjectType,
4298 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
15074299 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
15084300 {
15094301 external_constructor<value_t::object>::construct(j, obj);
15104302 }
15114303
1512 template <typename BasicJsonType>
4304 template<typename BasicJsonType>
15134305 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
15144306 {
15154307 external_constructor<value_t::object>::construct(j, std::move(obj));
15164308 }
15174309
1518 template <typename BasicJsonType, typename T, std::size_t N, enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0>
1519 void to_json(BasicJsonType& j, T (&arr)[N])
4310 template <
4311 typename BasicJsonType, typename T, std::size_t N,
4312 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4313 const T(&)[N]>::value,
4314 int > = 0 >
4315 void to_json(BasicJsonType& j, const T(&arr)[N])
15204316 {
15214317 external_constructor<value_t::array>::construct(j, arr);
15224318 }
15234319
1524 template <typename BasicJsonType, typename... Args>
1525 void to_json(BasicJsonType& j, const std::pair<Args...>& p)
4320 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4321 void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
15264322 {
1527 j = {p.first, p.second};
4323 j = { p.first, p.second };
15284324 }
15294325
1530 template <typename BasicJsonType, typename Tuple, std::size_t... Idx>
1531 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
4326 // for https://github.com/nlohmann/json/pull/1134
4327 template<typename BasicJsonType, typename T,
4328 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4329 void to_json(BasicJsonType& j, const T& b)
15324330 {
1533 j = {std::get<Idx>(t)...};
4331 j = { {b.key(), b.value()} };
15344332 }
15354333
1536 template <typename BasicJsonType, typename... Args>
1537 void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
4334 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4335 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
15384336 {
1539 to_json_tuple_impl(j, t, index_sequence_for<Args...>{});
4337 j = { std::get<Idx>(t)... };
4338 }
4339
4340 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4341 void to_json(BasicJsonType& j, const T& t)
4342 {
4343 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
15404344 }
15414345
15424346 struct to_json_fn
15434347 {
1544 private:
1545 template <typename BasicJsonType, typename T>
1546 auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1547 -> decltype(to_json(j, std::forward<T>(val)), void())
4348 template<typename BasicJsonType, typename T>
4349 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4350 -> decltype(to_json(j, std::forward<T>(val)), void())
15484351 {
15494352 return to_json(j, std::forward<T>(val));
15504353 }
1551
1552 template <typename BasicJsonType, typename T>
1553 void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1554 {
1555 static_assert(sizeof(BasicJsonType) == 0, "could not find to_json() method in T's namespace");
1556
1557 #ifdef _MSC_VER
1558 // MSVC does not show a stacktrace for the above assert
1559 using decayed = uncvref_t<T>;
1560 static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, "forcing MSVC stacktrace to show which T we're talking about.");
1561 #endif
1562 }
1563
1564 public:
1565 template <typename BasicJsonType, typename T>
1566 void operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1>{})))
1567 {
1568 return call(j, std::forward<T>(val), priority_tag<1>{});
1569 }
15704354 };
1571 }
4355 } // namespace detail
15724356
15734357 /// namespace to hold default `to_json` function
15744358 namespace
15754359 {
15764360 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1577 }
1578 }
1579
1580 // #include <nlohmann/detail/input/input_adapters.hpp>
1581
1582
1583 #include <algorithm> // min
1584 #include <array> // array
1585 #include <cassert> // assert
1586 #include <cstddef> // size_t
1587 #include <cstring> // strlen
1588 #include <ios> // streamsize, streamoff, streampos
1589 #include <istream> // istream
1590 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
1591 #include <memory> // shared_ptr, make_shared, addressof
1592 #include <numeric> // accumulate
1593 #include <string> // string, char_traits
1594 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
1595 #include <utility> // pair, declval
1596
1597 // #include <nlohmann/detail/macro_scope.hpp>
1598
4361 } // namespace
4362 } // namespace nlohmann
4363
4364
4365 namespace nlohmann
4366 {
4367
4368 template<typename, typename>
4369 struct adl_serializer
4370 {
4371 /*!
4372 @brief convert a JSON value to any value type
4373
4374 This function is usually called by the `get()` function of the
4375 @ref basic_json class (either explicit or via conversion operators).
4376
4377 @param[in] j JSON value to read from
4378 @param[in,out] val value to write to
4379 */
4380 template<typename BasicJsonType, typename ValueType>
4381 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
4382 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4383 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4384 {
4385 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4386 }
4387
4388 /*!
4389 @brief convert any value type to a JSON value
4390
4391 This function is usually called by the constructors of the @ref basic_json
4392 class.
4393
4394 @param[in,out] j JSON value to write to
4395 @param[in] val value to read from
4396 */
4397 template<typename BasicJsonType, typename ValueType>
4398 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
4399 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
4400 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
4401 {
4402 ::nlohmann::to_json(j, std::forward<ValueType>(val));
4403 }
4404 };
4405
4406 } // namespace nlohmann
4407
4408 // #include <nlohmann/byte_container_with_subtype.hpp>
4409
4410
4411 #include <cstdint> // uint8_t
4412 #include <tuple> // tie
4413 #include <utility> // move
4414
4415 namespace nlohmann
4416 {
4417
4418 /*!
4419 @brief an internal type for a backed binary type
4420
4421 This type extends the template parameter @a BinaryType provided to `basic_json`
4422 with a subtype used by BSON and MessagePack. This type exists so that the user
4423 does not have to specify a type themselves with a specific naming scheme in
4424 order to override the binary type.
4425
4426 @tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
4427 default)
4428
4429 @since version 3.8.0
4430 */
4431 template<typename BinaryType>
4432 class byte_container_with_subtype : public BinaryType
4433 {
4434 public:
4435 /// the type of the underlying container
4436 using container_type = BinaryType;
4437
4438 byte_container_with_subtype() noexcept(noexcept(container_type()))
4439 : container_type()
4440 {}
4441
4442 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4443 : container_type(b)
4444 {}
4445
4446 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4447 : container_type(std::move(b))
4448 {}
4449
4450 byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
4451 : container_type(b)
4452 , m_subtype(subtype)
4453 , m_has_subtype(true)
4454 {}
4455
4456 byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
4457 : container_type(std::move(b))
4458 , m_subtype(subtype)
4459 , m_has_subtype(true)
4460 {}
4461
4462 bool operator==(const byte_container_with_subtype& rhs) const
4463 {
4464 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
4465 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
4466 }
4467
4468 bool operator!=(const byte_container_with_subtype& rhs) const
4469 {
4470 return !(rhs == *this);
4471 }
4472
4473 /*!
4474 @brief sets the binary subtype
4475
4476 Sets the binary subtype of the value, also flags a binary JSON value as
4477 having a subtype, which has implications for serialization.
4478
4479 @complexity Constant.
4480
4481 @exceptionsafety No-throw guarantee: this member function never throws
4482 exceptions.
4483
4484 @sa @ref subtype() -- return the binary subtype
4485 @sa @ref clear_subtype() -- clears the binary subtype
4486 @sa @ref has_subtype() -- returns whether or not the binary value has a
4487 subtype
4488
4489 @since version 3.8.0
4490 */
4491 void set_subtype(std::uint8_t subtype) noexcept
4492 {
4493 m_subtype = subtype;
4494 m_has_subtype = true;
4495 }
4496
4497 /*!
4498 @brief return the binary subtype
4499
4500 Returns the numerical subtype of the value if it has a subtype. If it does
4501 not have a subtype, this function will return size_t(-1) as a sentinel
4502 value.
4503
4504 @return the numerical subtype of the binary value
4505
4506 @complexity Constant.
4507
4508 @exceptionsafety No-throw guarantee: this member function never throws
4509 exceptions.
4510
4511 @sa @ref set_subtype() -- sets the binary subtype
4512 @sa @ref clear_subtype() -- clears the binary subtype
4513 @sa @ref has_subtype() -- returns whether or not the binary value has a
4514 subtype
4515
4516 @since version 3.8.0
4517 */
4518 constexpr std::uint8_t subtype() const noexcept
4519 {
4520 return m_subtype;
4521 }
4522
4523 /*!
4524 @brief return whether the value has a subtype
4525
4526 @return whether the value has a subtype
4527
4528 @complexity Constant.
4529
4530 @exceptionsafety No-throw guarantee: this member function never throws
4531 exceptions.
4532
4533 @sa @ref subtype() -- return the binary subtype
4534 @sa @ref set_subtype() -- sets the binary subtype
4535 @sa @ref clear_subtype() -- clears the binary subtype
4536
4537 @since version 3.8.0
4538 */
4539 constexpr bool has_subtype() const noexcept
4540 {
4541 return m_has_subtype;
4542 }
4543
4544 /*!
4545 @brief clears the binary subtype
4546
4547 Clears the binary subtype and flags the value as not having a subtype, which
4548 has implications for serialization; for instance MessagePack will prefer the
4549 bin family over the ext family.
4550
4551 @complexity Constant.
4552
4553 @exceptionsafety No-throw guarantee: this member function never throws
4554 exceptions.
4555
4556 @sa @ref subtype() -- return the binary subtype
4557 @sa @ref set_subtype() -- sets the binary subtype
4558 @sa @ref has_subtype() -- returns whether or not the binary value has a
4559 subtype
4560
4561 @since version 3.8.0
4562 */
4563 void clear_subtype() noexcept
4564 {
4565 m_subtype = 0;
4566 m_has_subtype = false;
4567 }
4568
4569 private:
4570 std::uint8_t m_subtype = 0;
4571 bool m_has_subtype = false;
4572 };
4573
4574 } // namespace nlohmann
4575
4576 // #include <nlohmann/detail/conversions/from_json.hpp>
4577
4578 // #include <nlohmann/detail/conversions/to_json.hpp>
4579
4580 // #include <nlohmann/detail/exceptions.hpp>
4581
4582 // #include <nlohmann/detail/hash.hpp>
4583
4584
4585 #include <cstddef> // size_t, uint8_t
4586 #include <functional> // hash
15994587
16004588 namespace nlohmann
16014589 {
16024590 namespace detail
16034591 {
4592
4593 // boost::hash_combine
4594 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
4595 {
4596 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
4597 return seed;
4598 }
4599
4600 /*!
4601 @brief hash a JSON value
4602
4603 The hash function tries to rely on std::hash where possible. Furthermore, the
4604 type of the JSON value is taken into account to have different hash values for
4605 null, 0, 0U, and false, etc.
4606
4607 @tparam BasicJsonType basic_json specialization
4608 @param j JSON value to hash
4609 @return hash value of j
4610 */
4611 template<typename BasicJsonType>
4612 std::size_t hash(const BasicJsonType& j)
4613 {
4614 using string_t = typename BasicJsonType::string_t;
4615 using number_integer_t = typename BasicJsonType::number_integer_t;
4616 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4617 using number_float_t = typename BasicJsonType::number_float_t;
4618
4619 const auto type = static_cast<std::size_t>(j.type());
4620 switch (j.type())
4621 {
4622 case BasicJsonType::value_t::null:
4623 case BasicJsonType::value_t::discarded:
4624 {
4625 return combine(type, 0);
4626 }
4627
4628 case BasicJsonType::value_t::object:
4629 {
4630 auto seed = combine(type, j.size());
4631 for (const auto& element : j.items())
4632 {
4633 const auto h = std::hash<string_t> {}(element.key());
4634 seed = combine(seed, h);
4635 seed = combine(seed, hash(element.value()));
4636 }
4637 return seed;
4638 }
4639
4640 case BasicJsonType::value_t::array:
4641 {
4642 auto seed = combine(type, j.size());
4643 for (const auto& element : j)
4644 {
4645 seed = combine(seed, hash(element));
4646 }
4647 return seed;
4648 }
4649
4650 case BasicJsonType::value_t::string:
4651 {
4652 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
4653 return combine(type, h);
4654 }
4655
4656 case BasicJsonType::value_t::boolean:
4657 {
4658 const auto h = std::hash<bool> {}(j.template get<bool>());
4659 return combine(type, h);
4660 }
4661
4662 case BasicJsonType::value_t::number_integer:
4663 {
4664 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
4665 return combine(type, h);
4666 }
4667
4668 case nlohmann::detail::value_t::number_unsigned:
4669 {
4670 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
4671 return combine(type, h);
4672 }
4673
4674 case nlohmann::detail::value_t::number_float:
4675 {
4676 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
4677 return combine(type, h);
4678 }
4679
4680 case nlohmann::detail::value_t::binary:
4681 {
4682 auto seed = combine(type, j.get_binary().size());
4683 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
4684 seed = combine(seed, h);
4685 seed = combine(seed, j.get_binary().subtype());
4686 for (const auto byte : j.get_binary())
4687 {
4688 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
4689 }
4690 return seed;
4691 }
4692
4693 default: // LCOV_EXCL_LINE
4694 JSON_ASSERT(false); // LCOV_EXCL_LINE
4695 }
4696 }
4697
4698 } // namespace detail
4699 } // namespace nlohmann
4700
4701 // #include <nlohmann/detail/input/binary_reader.hpp>
4702
4703
4704 #include <algorithm> // generate_n
4705 #include <array> // array
4706 #include <cmath> // ldexp
4707 #include <cstddef> // size_t
4708 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
4709 #include <cstdio> // snprintf
4710 #include <cstring> // memcpy
4711 #include <iterator> // back_inserter
4712 #include <limits> // numeric_limits
4713 #include <string> // char_traits, string
4714 #include <utility> // make_pair, move
4715
4716 // #include <nlohmann/detail/exceptions.hpp>
4717
4718 // #include <nlohmann/detail/input/input_adapters.hpp>
4719
4720
4721 #include <array> // array
4722 #include <cstddef> // size_t
4723 #include <cstdio> //FILE *
4724 #include <cstring> // strlen
4725 #include <istream> // istream
4726 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
4727 #include <memory> // shared_ptr, make_shared, addressof
4728 #include <numeric> // accumulate
4729 #include <string> // string, char_traits
4730 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
4731 #include <utility> // pair, declval
4732
4733 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
4734
4735 // #include <nlohmann/detail/macro_scope.hpp>
4736
4737
4738 namespace nlohmann
4739 {
4740 namespace detail
4741 {
4742 /// the supported input formats
4743 enum class input_format_t { json, cbor, msgpack, ubjson, bson };
4744
16044745 ////////////////////
16054746 // input adapters //
16064747 ////////////////////
16074748
16084749 /*!
1609 @brief abstract input adapter interface
1610
1611 Produces a stream of std::char_traits<char>::int_type characters from a
1612 std::istream, a buffer, or some other input type. Accepts the return of exactly
1613 one non-EOF character for future input. The int_type characters returned
1614 consist of all valid char values as positive values (typically unsigned char),
1615 plus an EOF value outside that range, specified by the value of the function
1616 std::char_traits<char>::eof(). This value is typically -1, but could be any
1617 arbitrary value which is not a valid char value.
4750 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
4751 buffer. This adapter is a very low level adapter.
16184752 */
1619 struct input_adapter_protocol
4753 class file_input_adapter
16204754 {
1621 /// get a character [0,255] or std::char_traits<char>::eof().
1622 virtual std::char_traits<char>::int_type get_character() = 0;
1623 /// restore the last non-eof() character to input
1624 virtual void unget_character() = 0;
1625 virtual ~input_adapter_protocol() = default;
4755 public:
4756 using char_type = char;
4757
4758 JSON_HEDLEY_NON_NULL(2)
4759 explicit file_input_adapter(std::FILE* f) noexcept
4760 : m_file(f)
4761 {}
4762
4763 // make class move-only
4764 file_input_adapter(const file_input_adapter&) = delete;
4765 file_input_adapter(file_input_adapter&&) = default;
4766 file_input_adapter& operator=(const file_input_adapter&) = delete;
4767 file_input_adapter& operator=(file_input_adapter&&) = delete;
4768
4769 std::char_traits<char>::int_type get_character() noexcept
4770 {
4771 return std::fgetc(m_file);
4772 }
4773
4774 private:
4775 /// the file pointer to read from
4776 std::FILE* m_file;
16264777 };
16274778
1628 /// a type to simplify interfaces
1629 using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
16304779
16314780 /*!
16324781 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
16374786 std::istream flags; any input errors (e.g., EOF) will be detected by the first
16384787 subsequent call for input from the std::istream.
16394788 */
1640 class input_stream_adapter : public input_adapter_protocol
4789 class input_stream_adapter
16414790 {
1642 public:
1643 ~input_stream_adapter() override
4791 public:
4792 using char_type = char;
4793
4794 ~input_stream_adapter()
16444795 {
16454796 // clear stream flags; we use underlying streambuf I/O, do not
1646 // maintain ifstream flags
1647 is.clear();
1648 }
1649
1650 explicit input_stream_adapter(std::istream& i) : is(i), sb(*i.rdbuf())
1651 {
1652 // skip byte order mark
1653 std::char_traits<char>::int_type c;
1654 if ((c = get_character()) == 0xEF)
1655 {
1656 if ((c = get_character()) == 0xBB)
1657 {
1658 if ((c = get_character()) == 0xBF)
1659 {
1660 return; // Ignore BOM
1661 }
1662 else if (c != std::char_traits<char>::eof())
1663 {
1664 is.unget();
1665 }
1666 is.putback('\xBB');
1667 }
1668 else if (c != std::char_traits<char>::eof())
1669 {
1670 is.unget();
1671 }
1672 is.putback('\xEF');
1673 }
1674 else if (c != std::char_traits<char>::eof())
1675 {
1676 is.unget(); // no byte order mark; process as usual
1677 }
1678 }
4797 // maintain ifstream flags, except eof
4798 if (is != nullptr)
4799 {
4800 is->clear(is->rdstate() & std::ios::eofbit);
4801 }
4802 }
4803
4804 explicit input_stream_adapter(std::istream& i)
4805 : is(&i), sb(i.rdbuf())
4806 {}
16794807
16804808 // delete because of pointer members
16814809 input_stream_adapter(const input_stream_adapter&) = delete;
16824810 input_stream_adapter& operator=(input_stream_adapter&) = delete;
4811 input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
4812
4813 input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb)
4814 {
4815 rhs.is = nullptr;
4816 rhs.sb = nullptr;
4817 }
16834818
16844819 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
16854820 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
16864821 // end up as the same value, eg. 0xFFFFFFFF.
1687 std::char_traits<char>::int_type get_character() override
1688 {
1689 return sb.sbumpc();
1690 }
1691
1692 void unget_character() override
1693 {
1694 sb.sungetc(); // is.unget() avoided for performance
1695 }
1696
1697 private:
4822 std::char_traits<char>::int_type get_character()
4823 {
4824 auto res = sb->sbumpc();
4825 // set eof manually, as we don't use the istream interface.
4826 if (JSON_HEDLEY_UNLIKELY(res == EOF))
4827 {
4828 is->clear(is->rdstate() | std::ios::eofbit);
4829 }
4830 return res;
4831 }
4832
4833 private:
16984834 /// the associated input stream
1699 std::istream& is;
1700 std::streambuf& sb;
4835 std::istream* is = nullptr;
4836 std::streambuf* sb = nullptr;
17014837 };
17024838
1703 /// input adapter for buffer input
1704 class input_buffer_adapter : public input_adapter_protocol
4839 // General-purpose iterator-based adapter. It might not be as fast as
4840 // theoretically possible for some containers, but it is extremely versatile.
4841 template<typename IteratorType>
4842 class iterator_input_adapter
17054843 {
1706 public:
1707 input_buffer_adapter(const char* b, const std::size_t l) : cursor(b), limit(b + l), start(b)
1708 {
1709 // skip byte order mark
1710 if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
1711 {
1712 cursor += 3;
1713 }
1714 }
1715
1716 // delete because of pointer members
1717 input_buffer_adapter(const input_buffer_adapter&) = delete;
1718 input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
1719
1720 std::char_traits<char>::int_type get_character() noexcept override
1721 {
1722 if (JSON_LIKELY(cursor < limit))
1723 {
1724 return std::char_traits<char>::to_int_type(*(cursor++));
1725 }
1726
1727 return std::char_traits<char>::eof();
1728 }
1729
1730 void unget_character() noexcept override
1731 {
1732 if (JSON_LIKELY(cursor > start))
1733 {
1734 --cursor;
1735 }
1736 }
1737
1738 private:
1739 /// pointer to the current character
1740 const char* cursor;
1741 /// pointer past the last character
1742 const char* limit;
1743 /// pointer to the first character
1744 const char* start;
4844 public:
4845 using char_type = typename std::iterator_traits<IteratorType>::value_type;
4846
4847 iterator_input_adapter(IteratorType first, IteratorType last)
4848 : current(std::move(first)), end(std::move(last)) {}
4849
4850 typename std::char_traits<char_type>::int_type get_character()
4851 {
4852 if (JSON_HEDLEY_LIKELY(current != end))
4853 {
4854 auto result = std::char_traits<char_type>::to_int_type(*current);
4855 std::advance(current, 1);
4856 return result;
4857 }
4858 else
4859 {
4860 return std::char_traits<char_type>::eof();
4861 }
4862 }
4863
4864 private:
4865 IteratorType current;
4866 IteratorType end;
4867
4868 template<typename BaseInputAdapter, size_t T>
4869 friend struct wide_string_input_helper;
4870
4871 bool empty() const
4872 {
4873 return current == end;
4874 }
4875
17454876 };
17464877
1747 class input_adapter
4878
4879 template<typename BaseInputAdapter, size_t T>
4880 struct wide_string_input_helper;
4881
4882 template<typename BaseInputAdapter>
4883 struct wide_string_input_helper<BaseInputAdapter, 4>
17484884 {
1749 public:
1750 // native support
1751
1752 /// input adapter for input stream
1753 input_adapter(std::istream& i) : ia(std::make_shared<input_stream_adapter>(i))
1754 {
1755 }
1756
1757 /// input adapter for input stream
1758 input_adapter(std::istream&& i) : ia(std::make_shared<input_stream_adapter>(i))
1759 {
1760 }
1761
1762 /// input adapter for buffer
1763 template <typename CharT, typename std::enable_if<std::is_pointer<CharT>::value and std::is_integral<typename std::remove_pointer<CharT>::type>::value and
1764 sizeof(typename std::remove_pointer<CharT>::type) == 1,
1765 int>::type = 0>
1766 input_adapter(CharT b, std::size_t l) : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l))
1767 {
1768 }
1769
1770 // derived support
1771
1772 /// input adapter for string literal
1773 template <typename CharT, typename std::enable_if<std::is_pointer<CharT>::value and std::is_integral<typename std::remove_pointer<CharT>::type>::value and
1774 sizeof(typename std::remove_pointer<CharT>::type) == 1,
1775 int>::type = 0>
1776 input_adapter(CharT b) : input_adapter(reinterpret_cast<const char*>(b), std::strlen(reinterpret_cast<const char*>(b)))
1777 {
1778 }
1779
1780 /// input adapter for iterator range with contiguous storage
1781 template <class IteratorType,
1782 typename std::enable_if<std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
1783 int>::type = 0>
1784 input_adapter(IteratorType first, IteratorType last)
1785 {
1786 // assertion to check that the iterator range is indeed contiguous,
1787 // see http://stackoverflow.com/a/35008842/266378 for more discussion
1788 assert(std::accumulate(first, last, std::pair<bool, int>(true, 0), [&first](std::pair<bool, int> res, decltype(*first) val) {
1789 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
1790 return res;
1791 }).first);
1792
1793 // assertion to check that each element is 1 byte long
1794 static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1, "each element in the iterator range must have the size of 1 byte");
1795
1796 const auto len = static_cast<size_t>(std::distance(first, last));
1797 if (JSON_LIKELY(len > 0))
1798 {
1799 // there is at least one element: use the address of first
1800 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
4885 // UTF-32
4886 static void fill_buffer(BaseInputAdapter& input,
4887 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4888 size_t& utf8_bytes_index,
4889 size_t& utf8_bytes_filled)
4890 {
4891 utf8_bytes_index = 0;
4892
4893 if (JSON_HEDLEY_UNLIKELY(input.empty()))
4894 {
4895 utf8_bytes[0] = std::char_traits<char>::eof();
4896 utf8_bytes_filled = 1;
18014897 }
18024898 else
18034899 {
1804 // the address of first cannot be used: use nullptr
1805 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
1806 }
1807 }
1808
1809 /// input adapter for array
1810 template <class T, std::size_t N>
1811 input_adapter(T (&array)[N]) : input_adapter(std::begin(array), std::end(array))
1812 {
1813 }
1814
1815 /// input adapter for contiguous container
1816 template <class ContiguousContainer,
1817 typename std::enable_if<
1818 not std::is_pointer<ContiguousContainer>::value and
1819 std::is_base_of<std::random_access_iterator_tag,
1820 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
1821 int>::type = 0>
1822 input_adapter(const ContiguousContainer& c) : input_adapter(std::begin(c), std::end(c))
1823 {
1824 }
1825
1826 operator input_adapter_t()
1827 {
1828 return ia;
1829 }
1830
1831 private:
1832 /// the actual adapter
1833 input_adapter_t ia = nullptr;
4900 // get the current character
4901 const auto wc = input.get_character();
4902
4903 // UTF-32 to UTF-8 encoding
4904 if (wc < 0x80)
4905 {
4906 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4907 utf8_bytes_filled = 1;
4908 }
4909 else if (wc <= 0x7FF)
4910 {
4911 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
4912 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4913 utf8_bytes_filled = 2;
4914 }
4915 else if (wc <= 0xFFFF)
4916 {
4917 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
4918 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4919 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4920 utf8_bytes_filled = 3;
4921 }
4922 else if (wc <= 0x10FFFF)
4923 {
4924 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
4925 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
4926 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4927 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4928 utf8_bytes_filled = 4;
4929 }
4930 else
4931 {
4932 // unknown character
4933 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4934 utf8_bytes_filled = 1;
4935 }
4936 }
4937 }
18344938 };
4939
4940 template<typename BaseInputAdapter>
4941 struct wide_string_input_helper<BaseInputAdapter, 2>
4942 {
4943 // UTF-16
4944 static void fill_buffer(BaseInputAdapter& input,
4945 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4946 size_t& utf8_bytes_index,
4947 size_t& utf8_bytes_filled)
4948 {
4949 utf8_bytes_index = 0;
4950
4951 if (JSON_HEDLEY_UNLIKELY(input.empty()))
4952 {
4953 utf8_bytes[0] = std::char_traits<char>::eof();
4954 utf8_bytes_filled = 1;
4955 }
4956 else
4957 {
4958 // get the current character
4959 const auto wc = input.get_character();
4960
4961 // UTF-16 to UTF-8 encoding
4962 if (wc < 0x80)
4963 {
4964 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4965 utf8_bytes_filled = 1;
4966 }
4967 else if (wc <= 0x7FF)
4968 {
4969 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
4970 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4971 utf8_bytes_filled = 2;
4972 }
4973 else if (0xD800 > wc || wc >= 0xE000)
4974 {
4975 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
4976 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4977 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4978 utf8_bytes_filled = 3;
4979 }
4980 else
4981 {
4982 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
4983 {
4984 const auto wc2 = static_cast<unsigned int>(input.get_character());
4985 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
4986 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
4987 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
4988 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
4989 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
4990 utf8_bytes_filled = 4;
4991 }
4992 else
4993 {
4994 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4995 utf8_bytes_filled = 1;
4996 }
4997 }
4998 }
4999 }
5000 };
5001
5002 // Wraps another input apdater to convert wide character types into individual bytes.
5003 template<typename BaseInputAdapter, typename WideCharType>
5004 class wide_string_input_adapter
5005 {
5006 public:
5007 using char_type = char;
5008
5009 wide_string_input_adapter(BaseInputAdapter base)
5010 : base_adapter(base) {}
5011
5012 typename std::char_traits<char>::int_type get_character() noexcept
5013 {
5014 // check if buffer needs to be filled
5015 if (utf8_bytes_index == utf8_bytes_filled)
5016 {
5017 fill_buffer<sizeof(WideCharType)>();
5018
5019 JSON_ASSERT(utf8_bytes_filled > 0);
5020 JSON_ASSERT(utf8_bytes_index == 0);
5021 }
5022
5023 // use buffer
5024 JSON_ASSERT(utf8_bytes_filled > 0);
5025 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5026 return utf8_bytes[utf8_bytes_index++];
5027 }
5028
5029 private:
5030 BaseInputAdapter base_adapter;
5031
5032 template<size_t T>
5033 void fill_buffer()
5034 {
5035 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5036 }
5037
5038 /// a buffer for UTF-8 bytes
5039 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5040
5041 /// index to the utf8_codes array for the next valid byte
5042 std::size_t utf8_bytes_index = 0;
5043 /// number of valid bytes in the utf8_codes array
5044 std::size_t utf8_bytes_filled = 0;
5045 };
5046
5047
5048 template<typename IteratorType, typename Enable = void>
5049 struct iterator_input_adapter_factory
5050 {
5051 using iterator_type = IteratorType;
5052 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5053 using adapter_type = iterator_input_adapter<iterator_type>;
5054
5055 static adapter_type create(IteratorType first, IteratorType last)
5056 {
5057 return adapter_type(std::move(first), std::move(last));
5058 }
5059 };
5060
5061 template<typename T>
5062 struct is_iterator_of_multibyte
5063 {
5064 using value_type = typename std::iterator_traits<T>::value_type;
5065 enum
5066 {
5067 value = sizeof(value_type) > 1
5068 };
5069 };
5070
5071 template<typename IteratorType>
5072 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5073 {
5074 using iterator_type = IteratorType;
5075 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5076 using base_adapter_type = iterator_input_adapter<iterator_type>;
5077 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5078
5079 static adapter_type create(IteratorType first, IteratorType last)
5080 {
5081 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5082 }
5083 };
5084
5085 // General purpose iterator-based input
5086 template<typename IteratorType>
5087 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5088 {
5089 using factory_type = iterator_input_adapter_factory<IteratorType>;
5090 return factory_type::create(first, last);
18355091 }
5092
5093 // Convenience shorthand from container to iterator
5094 template<typename ContainerType>
5095 auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
5096 {
5097 // Enable ADL
5098 using std::begin;
5099 using std::end;
5100
5101 return input_adapter(begin(container), end(container));
18365102 }
18375103
5104 // Special cases with fast paths
5105 inline file_input_adapter input_adapter(std::FILE* file)
5106 {
5107 return file_input_adapter(file);
5108 }
5109
5110 inline input_stream_adapter input_adapter(std::istream& stream)
5111 {
5112 return input_stream_adapter(stream);
5113 }
5114
5115 inline input_stream_adapter input_adapter(std::istream&& stream)
5116 {
5117 return input_stream_adapter(stream);
5118 }
5119
5120 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5121
5122 // Null-delimited strings, and the like.
5123 template < typename CharT,
5124 typename std::enable_if <
5125 std::is_pointer<CharT>::value&&
5126 !std::is_array<CharT>::value&&
5127 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5128 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5129 int >::type = 0 >
5130 contiguous_bytes_input_adapter input_adapter(CharT b)
5131 {
5132 auto length = std::strlen(reinterpret_cast<const char*>(b));
5133 const auto* ptr = reinterpret_cast<const char*>(b);
5134 return input_adapter(ptr, ptr + length);
5135 }
5136
5137 template<typename T, std::size_t N>
5138 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
5139 {
5140 return input_adapter(array, array + N);
5141 }
5142
5143 // This class only handles inputs of input_buffer_adapter type.
5144 // It's required so that expressions like {ptr, len} can be implicitely casted
5145 // to the correct adapter.
5146 class span_input_adapter
5147 {
5148 public:
5149 template < typename CharT,
5150 typename std::enable_if <
5151 std::is_pointer<CharT>::value&&
5152 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5153 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5154 int >::type = 0 >
5155 span_input_adapter(CharT b, std::size_t l)
5156 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5157
5158 template<class IteratorType,
5159 typename std::enable_if<
5160 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5161 int>::type = 0>
5162 span_input_adapter(IteratorType first, IteratorType last)
5163 : ia(input_adapter(first, last)) {}
5164
5165 contiguous_bytes_input_adapter&& get()
5166 {
5167 return std::move(ia);
5168 }
5169
5170 private:
5171 contiguous_bytes_input_adapter ia;
5172 };
5173 } // namespace detail
5174 } // namespace nlohmann
5175
5176 // #include <nlohmann/detail/input/json_sax.hpp>
5177
5178
5179 #include <cstddef>
5180 #include <string> // string
5181 #include <utility> // move
5182 #include <vector> // vector
5183
5184 // #include <nlohmann/detail/exceptions.hpp>
5185
5186 // #include <nlohmann/detail/macro_scope.hpp>
5187
5188
5189 namespace nlohmann
5190 {
5191
5192 /*!
5193 @brief SAX interface
5194
5195 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5196 Each function is called in different situations while the input is parsed. The
5197 boolean return value informs the parser whether to continue processing the
5198 input.
5199 */
5200 template<typename BasicJsonType>
5201 struct json_sax
5202 {
5203 using number_integer_t = typename BasicJsonType::number_integer_t;
5204 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5205 using number_float_t = typename BasicJsonType::number_float_t;
5206 using string_t = typename BasicJsonType::string_t;
5207 using binary_t = typename BasicJsonType::binary_t;
5208
5209 /*!
5210 @brief a null value was read
5211 @return whether parsing should proceed
5212 */
5213 virtual bool null() = 0;
5214
5215 /*!
5216 @brief a boolean value was read
5217 @param[in] val boolean value
5218 @return whether parsing should proceed
5219 */
5220 virtual bool boolean(bool val) = 0;
5221
5222 /*!
5223 @brief an integer number was read
5224 @param[in] val integer value
5225 @return whether parsing should proceed
5226 */
5227 virtual bool number_integer(number_integer_t val) = 0;
5228
5229 /*!
5230 @brief an unsigned integer number was read
5231 @param[in] val unsigned integer value
5232 @return whether parsing should proceed
5233 */
5234 virtual bool number_unsigned(number_unsigned_t val) = 0;
5235
5236 /*!
5237 @brief an floating-point number was read
5238 @param[in] val floating-point value
5239 @param[in] s raw token value
5240 @return whether parsing should proceed
5241 */
5242 virtual bool number_float(number_float_t val, const string_t& s) = 0;
5243
5244 /*!
5245 @brief a string was read
5246 @param[in] val string value
5247 @return whether parsing should proceed
5248 @note It is safe to move the passed string.
5249 */
5250 virtual bool string(string_t& val) = 0;
5251
5252 /*!
5253 @brief a binary string was read
5254 @param[in] val binary value
5255 @return whether parsing should proceed
5256 @note It is safe to move the passed binary.
5257 */
5258 virtual bool binary(binary_t& val) = 0;
5259
5260 /*!
5261 @brief the beginning of an object was read
5262 @param[in] elements number of object elements or -1 if unknown
5263 @return whether parsing should proceed
5264 @note binary formats may report the number of elements
5265 */
5266 virtual bool start_object(std::size_t elements) = 0;
5267
5268 /*!
5269 @brief an object key was read
5270 @param[in] val object key
5271 @return whether parsing should proceed
5272 @note It is safe to move the passed string.
5273 */
5274 virtual bool key(string_t& val) = 0;
5275
5276 /*!
5277 @brief the end of an object was read
5278 @return whether parsing should proceed
5279 */
5280 virtual bool end_object() = 0;
5281
5282 /*!
5283 @brief the beginning of an array was read
5284 @param[in] elements number of array elements or -1 if unknown
5285 @return whether parsing should proceed
5286 @note binary formats may report the number of elements
5287 */
5288 virtual bool start_array(std::size_t elements) = 0;
5289
5290 /*!
5291 @brief the end of an array was read
5292 @return whether parsing should proceed
5293 */
5294 virtual bool end_array() = 0;
5295
5296 /*!
5297 @brief a parse error occurred
5298 @param[in] position the position in the input where the error occurs
5299 @param[in] last_token the last read token
5300 @param[in] ex an exception object describing the error
5301 @return whether parsing should proceed (must return false)
5302 */
5303 virtual bool parse_error(std::size_t position,
5304 const std::string& last_token,
5305 const detail::exception& ex) = 0;
5306
5307 virtual ~json_sax() = default;
5308 };
5309
5310
5311 namespace detail
5312 {
5313 /*!
5314 @brief SAX implementation to create a JSON value from SAX events
5315
5316 This class implements the @ref json_sax interface and processes the SAX events
5317 to create a JSON value which makes it basically a DOM parser. The structure or
5318 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5319 a pointer to the respective array or object for each recursion depth.
5320
5321 After successful parsing, the value that is passed by reference to the
5322 constructor contains the parsed value.
5323
5324 @tparam BasicJsonType the JSON type
5325 */
5326 template<typename BasicJsonType>
5327 class json_sax_dom_parser
5328 {
5329 public:
5330 using number_integer_t = typename BasicJsonType::number_integer_t;
5331 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5332 using number_float_t = typename BasicJsonType::number_float_t;
5333 using string_t = typename BasicJsonType::string_t;
5334 using binary_t = typename BasicJsonType::binary_t;
5335
5336 /*!
5337 @param[in, out] r reference to a JSON value that is manipulated while
5338 parsing
5339 @param[in] allow_exceptions_ whether parse errors yield exceptions
5340 */
5341 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5342 : root(r), allow_exceptions(allow_exceptions_)
5343 {}
5344
5345 // make class move-only
5346 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5347 json_sax_dom_parser(json_sax_dom_parser&&) = default;
5348 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5349 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
5350 ~json_sax_dom_parser() = default;
5351
5352 bool null()
5353 {
5354 handle_value(nullptr);
5355 return true;
5356 }
5357
5358 bool boolean(bool val)
5359 {
5360 handle_value(val);
5361 return true;
5362 }
5363
5364 bool number_integer(number_integer_t val)
5365 {
5366 handle_value(val);
5367 return true;
5368 }
5369
5370 bool number_unsigned(number_unsigned_t val)
5371 {
5372 handle_value(val);
5373 return true;
5374 }
5375
5376 bool number_float(number_float_t val, const string_t& /*unused*/)
5377 {
5378 handle_value(val);
5379 return true;
5380 }
5381
5382 bool string(string_t& val)
5383 {
5384 handle_value(val);
5385 return true;
5386 }
5387
5388 bool binary(binary_t& val)
5389 {
5390 handle_value(std::move(val));
5391 return true;
5392 }
5393
5394 bool start_object(std::size_t len)
5395 {
5396 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5397
5398 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5399 {
5400 JSON_THROW(out_of_range::create(408,
5401 "excessive object size: " + std::to_string(len)));
5402 }
5403
5404 return true;
5405 }
5406
5407 bool key(string_t& val)
5408 {
5409 // add null at given key and store the reference for later
5410 object_element = &(ref_stack.back()->m_value.object->operator[](val));
5411 return true;
5412 }
5413
5414 bool end_object()
5415 {
5416 ref_stack.pop_back();
5417 return true;
5418 }
5419
5420 bool start_array(std::size_t len)
5421 {
5422 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5423
5424 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5425 {
5426 JSON_THROW(out_of_range::create(408,
5427 "excessive array size: " + std::to_string(len)));
5428 }
5429
5430 return true;
5431 }
5432
5433 bool end_array()
5434 {
5435 ref_stack.pop_back();
5436 return true;
5437 }
5438
5439 template<class Exception>
5440 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5441 const Exception& ex)
5442 {
5443 errored = true;
5444 static_cast<void>(ex);
5445 if (allow_exceptions)
5446 {
5447 JSON_THROW(ex);
5448 }
5449 return false;
5450 }
5451
5452 constexpr bool is_errored() const
5453 {
5454 return errored;
5455 }
5456
5457 private:
5458 /*!
5459 @invariant If the ref stack is empty, then the passed value will be the new
5460 root.
5461 @invariant If the ref stack contains a value, then it is an array or an
5462 object to which we can add elements
5463 */
5464 template<typename Value>
5465 JSON_HEDLEY_RETURNS_NON_NULL
5466 BasicJsonType* handle_value(Value&& v)
5467 {
5468 if (ref_stack.empty())
5469 {
5470 root = BasicJsonType(std::forward<Value>(v));
5471 return &root;
5472 }
5473
5474 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5475
5476 if (ref_stack.back()->is_array())
5477 {
5478 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
5479 return &(ref_stack.back()->m_value.array->back());
5480 }
5481
5482 JSON_ASSERT(ref_stack.back()->is_object());
5483 JSON_ASSERT(object_element);
5484 *object_element = BasicJsonType(std::forward<Value>(v));
5485 return object_element;
5486 }
5487
5488 /// the parsed JSON value
5489 BasicJsonType& root;
5490 /// stack to model hierarchy of values
5491 std::vector<BasicJsonType*> ref_stack {};
5492 /// helper to hold the reference for the next object element
5493 BasicJsonType* object_element = nullptr;
5494 /// whether a syntax error occurred
5495 bool errored = false;
5496 /// whether to throw exceptions in case of errors
5497 const bool allow_exceptions = true;
5498 };
5499
5500 template<typename BasicJsonType>
5501 class json_sax_dom_callback_parser
5502 {
5503 public:
5504 using number_integer_t = typename BasicJsonType::number_integer_t;
5505 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5506 using number_float_t = typename BasicJsonType::number_float_t;
5507 using string_t = typename BasicJsonType::string_t;
5508 using binary_t = typename BasicJsonType::binary_t;
5509 using parser_callback_t = typename BasicJsonType::parser_callback_t;
5510 using parse_event_t = typename BasicJsonType::parse_event_t;
5511
5512 json_sax_dom_callback_parser(BasicJsonType& r,
5513 const parser_callback_t cb,
5514 const bool allow_exceptions_ = true)
5515 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
5516 {
5517 keep_stack.push_back(true);
5518 }
5519
5520 // make class move-only
5521 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
5522 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
5523 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
5524 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
5525 ~json_sax_dom_callback_parser() = default;
5526
5527 bool null()
5528 {
5529 handle_value(nullptr);
5530 return true;
5531 }
5532
5533 bool boolean(bool val)
5534 {
5535 handle_value(val);
5536 return true;
5537 }
5538
5539 bool number_integer(number_integer_t val)
5540 {
5541 handle_value(val);
5542 return true;
5543 }
5544
5545 bool number_unsigned(number_unsigned_t val)
5546 {
5547 handle_value(val);
5548 return true;
5549 }
5550
5551 bool number_float(number_float_t val, const string_t& /*unused*/)
5552 {
5553 handle_value(val);
5554 return true;
5555 }
5556
5557 bool string(string_t& val)
5558 {
5559 handle_value(val);
5560 return true;
5561 }
5562
5563 bool binary(binary_t& val)
5564 {
5565 handle_value(std::move(val));
5566 return true;
5567 }
5568
5569 bool start_object(std::size_t len)
5570 {
5571 // check callback for object start
5572 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
5573 keep_stack.push_back(keep);
5574
5575 auto val = handle_value(BasicJsonType::value_t::object, true);
5576 ref_stack.push_back(val.second);
5577
5578 // check object limit
5579 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5580 {
5581 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
5582 }
5583
5584 return true;
5585 }
5586
5587 bool key(string_t& val)
5588 {
5589 BasicJsonType k = BasicJsonType(val);
5590
5591 // check callback for key
5592 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
5593 key_keep_stack.push_back(keep);
5594
5595 // add discarded value at given key and store the reference for later
5596 if (keep && ref_stack.back())
5597 {
5598 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
5599 }
5600
5601 return true;
5602 }
5603
5604 bool end_object()
5605 {
5606 if (ref_stack.back() && !callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
5607 {
5608 // discard object
5609 *ref_stack.back() = discarded;
5610 }
5611
5612 JSON_ASSERT(!ref_stack.empty());
5613 JSON_ASSERT(!keep_stack.empty());
5614 ref_stack.pop_back();
5615 keep_stack.pop_back();
5616
5617 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
5618 {
5619 // remove discarded value
5620 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
5621 {
5622 if (it->is_discarded())
5623 {
5624 ref_stack.back()->erase(it);
5625 break;
5626 }
5627 }
5628 }
5629
5630 return true;
5631 }
5632
5633 bool start_array(std::size_t len)
5634 {
5635 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
5636 keep_stack.push_back(keep);
5637
5638 auto val = handle_value(BasicJsonType::value_t::array, true);
5639 ref_stack.push_back(val.second);
5640
5641 // check array limit
5642 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5643 {
5644 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
5645 }
5646
5647 return true;
5648 }
5649
5650 bool end_array()
5651 {
5652 bool keep = true;
5653
5654 if (ref_stack.back())
5655 {
5656 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
5657 if (!keep)
5658 {
5659 // discard array
5660 *ref_stack.back() = discarded;
5661 }
5662 }
5663
5664 JSON_ASSERT(!ref_stack.empty());
5665 JSON_ASSERT(!keep_stack.empty());
5666 ref_stack.pop_back();
5667 keep_stack.pop_back();
5668
5669 // remove discarded value
5670 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
5671 {
5672 ref_stack.back()->m_value.array->pop_back();
5673 }
5674
5675 return true;
5676 }
5677
5678 template<class Exception>
5679 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5680 const Exception& ex)
5681 {
5682 errored = true;
5683 static_cast<void>(ex);
5684 if (allow_exceptions)
5685 {
5686 JSON_THROW(ex);
5687 }
5688 return false;
5689 }
5690
5691 constexpr bool is_errored() const
5692 {
5693 return errored;
5694 }
5695
5696 private:
5697 /*!
5698 @param[in] v value to add to the JSON value we build during parsing
5699 @param[in] skip_callback whether we should skip calling the callback
5700 function; this is required after start_array() and
5701 start_object() SAX events, because otherwise we would call the
5702 callback function with an empty array or object, respectively.
5703
5704 @invariant If the ref stack is empty, then the passed value will be the new
5705 root.
5706 @invariant If the ref stack contains a value, then it is an array or an
5707 object to which we can add elements
5708
5709 @return pair of boolean (whether value should be kept) and pointer (to the
5710 passed value in the ref_stack hierarchy; nullptr if not kept)
5711 */
5712 template<typename Value>
5713 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
5714 {
5715 JSON_ASSERT(!keep_stack.empty());
5716
5717 // do not handle this value if we know it would be added to a discarded
5718 // container
5719 if (!keep_stack.back())
5720 {
5721 return {false, nullptr};
5722 }
5723
5724 // create value
5725 auto value = BasicJsonType(std::forward<Value>(v));
5726
5727 // check callback
5728 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
5729
5730 // do not handle this value if we just learnt it shall be discarded
5731 if (!keep)
5732 {
5733 return {false, nullptr};
5734 }
5735
5736 if (ref_stack.empty())
5737 {
5738 root = std::move(value);
5739 return {true, &root};
5740 }
5741
5742 // skip this value if we already decided to skip the parent
5743 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
5744 if (!ref_stack.back())
5745 {
5746 return {false, nullptr};
5747 }
5748
5749 // we now only expect arrays and objects
5750 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5751
5752 // array
5753 if (ref_stack.back()->is_array())
5754 {
5755 ref_stack.back()->m_value.array->push_back(std::move(value));
5756 return {true, &(ref_stack.back()->m_value.array->back())};
5757 }
5758
5759 // object
5760 JSON_ASSERT(ref_stack.back()->is_object());
5761 // check if we should store an element for the current key
5762 JSON_ASSERT(!key_keep_stack.empty());
5763 const bool store_element = key_keep_stack.back();
5764 key_keep_stack.pop_back();
5765
5766 if (!store_element)
5767 {
5768 return {false, nullptr};
5769 }
5770
5771 JSON_ASSERT(object_element);
5772 *object_element = std::move(value);
5773 return {true, object_element};
5774 }
5775
5776 /// the parsed JSON value
5777 BasicJsonType& root;
5778 /// stack to model hierarchy of values
5779 std::vector<BasicJsonType*> ref_stack {};
5780 /// stack to manage which values to keep
5781 std::vector<bool> keep_stack {};
5782 /// stack to manage which object keys to keep
5783 std::vector<bool> key_keep_stack {};
5784 /// helper to hold the reference for the next object element
5785 BasicJsonType* object_element = nullptr;
5786 /// whether a syntax error occurred
5787 bool errored = false;
5788 /// callback function
5789 const parser_callback_t callback = nullptr;
5790 /// whether to throw exceptions in case of errors
5791 const bool allow_exceptions = true;
5792 /// a discarded value for the callback
5793 BasicJsonType discarded = BasicJsonType::value_t::discarded;
5794 };
5795
5796 template<typename BasicJsonType>
5797 class json_sax_acceptor
5798 {
5799 public:
5800 using number_integer_t = typename BasicJsonType::number_integer_t;
5801 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5802 using number_float_t = typename BasicJsonType::number_float_t;
5803 using string_t = typename BasicJsonType::string_t;
5804 using binary_t = typename BasicJsonType::binary_t;
5805
5806 bool null()
5807 {
5808 return true;
5809 }
5810
5811 bool boolean(bool /*unused*/)
5812 {
5813 return true;
5814 }
5815
5816 bool number_integer(number_integer_t /*unused*/)
5817 {
5818 return true;
5819 }
5820
5821 bool number_unsigned(number_unsigned_t /*unused*/)
5822 {
5823 return true;
5824 }
5825
5826 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
5827 {
5828 return true;
5829 }
5830
5831 bool string(string_t& /*unused*/)
5832 {
5833 return true;
5834 }
5835
5836 bool binary(binary_t& /*unused*/)
5837 {
5838 return true;
5839 }
5840
5841 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
5842 {
5843 return true;
5844 }
5845
5846 bool key(string_t& /*unused*/)
5847 {
5848 return true;
5849 }
5850
5851 bool end_object()
5852 {
5853 return true;
5854 }
5855
5856 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
5857 {
5858 return true;
5859 }
5860
5861 bool end_array()
5862 {
5863 return true;
5864 }
5865
5866 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
5867 {
5868 return false;
5869 }
5870 };
5871 } // namespace detail
5872
5873 } // namespace nlohmann
5874
18385875 // #include <nlohmann/detail/input/lexer.hpp>
18395876
18405877
1841 #include <clocale> // localeconv
1842 #include <cstddef> // size_t
1843 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
5878 #include <array> // array
5879 #include <clocale> // localeconv
5880 #include <cstddef> // size_t
5881 #include <cstdio> // snprintf
5882 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
18445883 #include <initializer_list> // initializer_list
1845 #include <iomanip> // setw, setfill
1846 #include <ios> // hex, uppercase
1847 #include <sstream> // stringstream
1848 #include <string> // char_traits, string
1849 #include <vector> // vector
5884 #include <string> // char_traits, string
5885 #include <utility> // move
5886 #include <vector> // vector
5887
5888 // #include <nlohmann/detail/input/input_adapters.hpp>
5889
5890 // #include <nlohmann/detail/input/position_t.hpp>
18505891
18515892 // #include <nlohmann/detail/macro_scope.hpp>
1852
1853 // #include <nlohmann/detail/input/input_adapters.hpp>
18545893
18555894
18565895 namespace nlohmann
18615900 // lexer //
18625901 ///////////
18635902
1864 /*!
1865 @brief lexical analysis
1866
1867 This class organizes the lexical analysis during JSON deserialization.
1868 */
1869 template <typename BasicJsonType>
1870 class lexer
5903 template<typename BasicJsonType>
5904 class lexer_base
18715905 {
1872 using number_integer_t = typename BasicJsonType::number_integer_t;
1873 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
1874 using number_float_t = typename BasicJsonType::number_float_t;
1875 using string_t = typename BasicJsonType::string_t;
1876
1877 public:
5906 public:
18785907 /// token types for the parser
18795908 enum class token_type
18805909 {
1881 uninitialized, ///< indicating the scanner is uninitialized
1882 literal_true, ///< the `true` literal
1883 literal_false, ///< the `false` literal
1884 literal_null, ///< the `null` literal
1885 value_string, ///< a string -- use get_string() for actual value
1886 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
1887 value_integer, ///< a signed integer -- use get_number_integer() for actual value
1888 value_float, ///< an floating point number -- use get_number_float() for actual value
1889 begin_array, ///< the character for array begin `[`
1890 begin_object, ///< the character for object begin `{`
1891 end_array, ///< the character for array end `]`
1892 end_object, ///< the character for object end `}`
1893 name_separator, ///< the name separator `:`
1894 value_separator, ///< the value separator `,`
1895 parse_error, ///< indicating a parse error
1896 end_of_input, ///< indicating the end of the input buffer
1897 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
5910 uninitialized, ///< indicating the scanner is uninitialized
5911 literal_true, ///< the `true` literal
5912 literal_false, ///< the `false` literal
5913 literal_null, ///< the `null` literal
5914 value_string, ///< a string -- use get_string() for actual value
5915 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
5916 value_integer, ///< a signed integer -- use get_number_integer() for actual value
5917 value_float, ///< an floating point number -- use get_number_float() for actual value
5918 begin_array, ///< the character for array begin `[`
5919 begin_object, ///< the character for object begin `{`
5920 end_array, ///< the character for array end `]`
5921 end_object, ///< the character for object end `}`
5922 name_separator, ///< the name separator `:`
5923 value_separator, ///< the value separator `,`
5924 parse_error, ///< indicating a parse error
5925 end_of_input, ///< indicating the end of the input buffer
5926 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
18985927 };
18995928
19005929 /// return name of values of type token_type (only used for errors)
5930 JSON_HEDLEY_RETURNS_NON_NULL
5931 JSON_HEDLEY_CONST
19015932 static const char* token_type_name(const token_type t) noexcept
19025933 {
19035934 switch (t)
19125943 return "null literal";
19135944 case token_type::value_string:
19145945 return "string literal";
1915 case lexer::token_type::value_unsigned:
1916 case lexer::token_type::value_integer:
1917 case lexer::token_type::value_float:
5946 case token_type::value_unsigned:
5947 case token_type::value_integer:
5948 case token_type::value_float:
19185949 return "number literal";
19195950 case token_type::begin_array:
19205951 return "'['";
19345965 return "end of input";
19355966 case token_type::literal_or_value:
19365967 return "'[', '{', or a literal";
1937 default: // catch non-enum values
1938 return "unknown token"; // LCOV_EXCL_LINE
1939 }
1940 }
1941
1942 explicit lexer(detail::input_adapter_t adapter) : ia(std::move(adapter)), decimal_point_char(get_decimal_point())
1943 {
1944 }
5968 // LCOV_EXCL_START
5969 default: // catch non-enum values
5970 return "unknown token";
5971 // LCOV_EXCL_STOP
5972 }
5973 }
5974 };
5975 /*!
5976 @brief lexical analysis
5977
5978 This class organizes the lexical analysis during JSON deserialization.
5979 */
5980 template<typename BasicJsonType, typename InputAdapterType>
5981 class lexer : public lexer_base<BasicJsonType>
5982 {
5983 using number_integer_t = typename BasicJsonType::number_integer_t;
5984 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5985 using number_float_t = typename BasicJsonType::number_float_t;
5986 using string_t = typename BasicJsonType::string_t;
5987 using char_type = typename InputAdapterType::char_type;
5988 using char_int_type = typename std::char_traits<char_type>::int_type;
5989
5990 public:
5991 using token_type = typename lexer_base<BasicJsonType>::token_type;
5992
5993 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
5994 : ia(std::move(adapter))
5995 , ignore_comments(ignore_comments_)
5996 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
5997 {}
19455998
19465999 // delete because of pointer members
19476000 lexer(const lexer&) = delete;
6001 lexer(lexer&&) = default;
19486002 lexer& operator=(lexer&) = delete;
1949
1950 private:
6003 lexer& operator=(lexer&&) = default;
6004 ~lexer() = default;
6005
6006 private:
19516007 /////////////////////
19526008 // locales
19536009 /////////////////////
19546010
19556011 /// return the locale-dependent decimal point
6012 JSON_HEDLEY_PURE
19566013 static char get_decimal_point() noexcept
19576014 {
1958 const auto loc = cpt::localeconv();
1959 assert(loc != nullptr);
6015 const auto* loc = localeconv();
6016 JSON_ASSERT(loc != nullptr);
19606017 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
19616018 }
19626019
19826039 int get_codepoint()
19836040 {
19846041 // this function only makes sense after reading `\u`
1985 assert(current == 'u');
6042 JSON_ASSERT(current == 'u');
19866043 int codepoint = 0;
19876044
1988 const auto factors = {12, 8, 4, 0};
6045 const auto factors = { 12u, 8u, 4u, 0u };
19896046 for (const auto factor : factors)
19906047 {
19916048 get();
19926049
1993 if (current >= '0' and current <= '9')
1994 {
1995 codepoint += ((current - 0x30) << factor);
1996 }
1997 else if (current >= 'A' and current <= 'F')
1998 {
1999 codepoint += ((current - 0x37) << factor);
2000 }
2001 else if (current >= 'a' and current <= 'f')
2002 {
2003 codepoint += ((current - 0x57) << factor);
6050 if (current >= '0' && current <= '9')
6051 {
6052 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6053 }
6054 else if (current >= 'A' && current <= 'F')
6055 {
6056 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6057 }
6058 else if (current >= 'a' && current <= 'f')
6059 {
6060 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
20046061 }
20056062 else
20066063 {
20086065 }
20096066 }
20106067
2011 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
6068 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
20126069 return codepoint;
20136070 }
20146071
20276084
20286085 @return true if and only if no range violation was detected
20296086 */
2030 bool next_byte_in_range(std::initializer_list<int> ranges)
2031 {
2032 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
6087 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6088 {
6089 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
20336090 add(current);
20346091
20356092 for (auto range = ranges.begin(); range != ranges.end(); ++range)
20366093 {
20376094 get();
2038 if (JSON_LIKELY(*range <= current and current <= *(++range)))
6095 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
20396096 {
20406097 add(current);
20416098 }
20706127 reset();
20716128
20726129 // we entered the function by reading an open quote
2073 assert(current == '\"');
6130 JSON_ASSERT(current == '\"');
20746131
20756132 while (true)
20766133 {
20786135 switch (get())
20796136 {
20806137 // end of file while parsing string
2081 case std::char_traits<char>::eof():
6138 case std::char_traits<char_type>::eof():
20826139 {
20836140 error_message = "invalid string: missing closing quote";
20846141 return token_type::parse_error;
21346191 const int codepoint1 = get_codepoint();
21356192 int codepoint = codepoint1; // start with codepoint1
21366193
2137 if (JSON_UNLIKELY(codepoint1 == -1))
6194 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
21386195 {
21396196 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
21406197 return token_type::parse_error;
21416198 }
21426199
21436200 // check if code point is a high surrogate
2144 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
6201 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
21456202 {
21466203 // expect next \uxxxx entry
2147 if (JSON_LIKELY(get() == '\\' and get() == 'u'))
6204 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
21486205 {
21496206 const int codepoint2 = get_codepoint();
21506207
2151 if (JSON_UNLIKELY(codepoint2 == -1))
6208 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
21526209 {
21536210 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
21546211 return token_type::parse_error;
21556212 }
21566213
21576214 // check if codepoint2 is a low surrogate
2158 if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
6215 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
21596216 {
21606217 // overwrite codepoint
2161 codepoint =
2162 // high surrogate occupies the most significant 22 bits
2163 (codepoint1 << 10)
2164 // low surrogate occupies the least significant 15 bits
2165 + codepoint2
2166 // there is still the 0xD800, 0xDC00 and 0x10000 noise
2167 // in the result so we have to subtract with:
2168 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2169 - 0x35FDC00;
6218 codepoint = static_cast<int>(
6219 // high surrogate occupies the most significant 22 bits
6220 (static_cast<unsigned int>(codepoint1) << 10u)
6221 // low surrogate occupies the least significant 15 bits
6222 + static_cast<unsigned int>(codepoint2)
6223 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6224 // in the result so we have to subtract with:
6225 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6226 - 0x35FDC00u);
21706227 }
21716228 else
21726229 {
2173 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
6230 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
21746231 return token_type::parse_error;
21756232 }
21766233 }
21776234 else
21786235 {
2179 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
6236 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
21806237 return token_type::parse_error;
21816238 }
21826239 }
21836240 else
21846241 {
2185 if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
6242 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
21866243 {
21876244 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
21886245 return token_type::parse_error;
21906247 }
21916248
21926249 // result of the above calculation yields a proper codepoint
2193 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
6250 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
21946251
21956252 // translate codepoint into bytes
21966253 if (codepoint < 0x80)
21976254 {
21986255 // 1-byte characters: 0xxxxxxx (ASCII)
2199 add(codepoint);
6256 add(static_cast<char_int_type>(codepoint));
22006257 }
22016258 else if (codepoint <= 0x7FF)
22026259 {
22036260 // 2-byte characters: 110xxxxx 10xxxxxx
2204 add(0xC0 | (codepoint >> 6));
2205 add(0x80 | (codepoint & 0x3F));
6261 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6262 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
22066263 }
22076264 else if (codepoint <= 0xFFFF)
22086265 {
22096266 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2210 add(0xE0 | (codepoint >> 12));
2211 add(0x80 | ((codepoint >> 6) & 0x3F));
2212 add(0x80 | (codepoint & 0x3F));
6267 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6268 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6269 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
22136270 }
22146271 else
22156272 {
22166273 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2217 add(0xF0 | (codepoint >> 18));
2218 add(0x80 | ((codepoint >> 12) & 0x3F));
2219 add(0x80 | ((codepoint >> 6) & 0x3F));
2220 add(0x80 | (codepoint & 0x3F));
6274 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6275 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6276 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6277 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
22216278 }
22226279
22236280 break;
22346291
22356292 // invalid control characters
22366293 case 0x00:
6294 {
6295 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6296 return token_type::parse_error;
6297 }
6298
22376299 case 0x01:
6300 {
6301 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6302 return token_type::parse_error;
6303 }
6304
22386305 case 0x02:
6306 {
6307 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6308 return token_type::parse_error;
6309 }
6310
22396311 case 0x03:
6312 {
6313 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6314 return token_type::parse_error;
6315 }
6316
22406317 case 0x04:
6318 {
6319 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6320 return token_type::parse_error;
6321 }
6322
22416323 case 0x05:
6324 {
6325 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6326 return token_type::parse_error;
6327 }
6328
22426329 case 0x06:
6330 {
6331 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6332 return token_type::parse_error;
6333 }
6334
22436335 case 0x07:
6336 {
6337 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6338 return token_type::parse_error;
6339 }
6340
22446341 case 0x08:
6342 {
6343 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6344 return token_type::parse_error;
6345 }
6346
22456347 case 0x09:
6348 {
6349 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6350 return token_type::parse_error;
6351 }
6352
22466353 case 0x0A:
6354 {
6355 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6356 return token_type::parse_error;
6357 }
6358
22476359 case 0x0B:
6360 {
6361 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6362 return token_type::parse_error;
6363 }
6364
22486365 case 0x0C:
6366 {
6367 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6368 return token_type::parse_error;
6369 }
6370
22496371 case 0x0D:
6372 {
6373 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6374 return token_type::parse_error;
6375 }
6376
22506377 case 0x0E:
6378 {
6379 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6380 return token_type::parse_error;
6381 }
6382
22516383 case 0x0F:
6384 {
6385 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6386 return token_type::parse_error;
6387 }
6388
22526389 case 0x10:
6390 {
6391 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6392 return token_type::parse_error;
6393 }
6394
22536395 case 0x11:
6396 {
6397 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6398 return token_type::parse_error;
6399 }
6400
22546401 case 0x12:
6402 {
6403 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6404 return token_type::parse_error;
6405 }
6406
22556407 case 0x13:
6408 {
6409 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6410 return token_type::parse_error;
6411 }
6412
22566413 case 0x14:
6414 {
6415 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6416 return token_type::parse_error;
6417 }
6418
22576419 case 0x15:
6420 {
6421 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6422 return token_type::parse_error;
6423 }
6424
22586425 case 0x16:
6426 {
6427 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6428 return token_type::parse_error;
6429 }
6430
22596431 case 0x17:
6432 {
6433 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6434 return token_type::parse_error;
6435 }
6436
22606437 case 0x18:
6438 {
6439 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6440 return token_type::parse_error;
6441 }
6442
22616443 case 0x19:
6444 {
6445 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6446 return token_type::parse_error;
6447 }
6448
22626449 case 0x1A:
6450 {
6451 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6452 return token_type::parse_error;
6453 }
6454
22636455 case 0x1B:
6456 {
6457 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6458 return token_type::parse_error;
6459 }
6460
22646461 case 0x1C:
6462 {
6463 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6464 return token_type::parse_error;
6465 }
6466
22656467 case 0x1D:
6468 {
6469 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
6470 return token_type::parse_error;
6471 }
6472
22666473 case 0x1E:
6474 {
6475 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
6476 return token_type::parse_error;
6477 }
6478
22676479 case 0x1F:
22686480 {
2269 error_message = "invalid string: control character must be escaped";
6481 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
22706482 return token_type::parse_error;
22716483 }
22726484
24026614 case 0xDE:
24036615 case 0xDF:
24046616 {
2405 if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
6617 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
24066618 {
24076619 return token_type::parse_error;
24086620 }
24126624 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
24136625 case 0xE0:
24146626 {
2415 if (JSON_UNLIKELY(not(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
6627 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
24166628 {
24176629 return token_type::parse_error;
24186630 }
24366648 case 0xEE:
24376649 case 0xEF:
24386650 {
2439 if (JSON_UNLIKELY(not(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
6651 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
24406652 {
24416653 return token_type::parse_error;
24426654 }
24466658 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
24476659 case 0xED:
24486660 {
2449 if (JSON_UNLIKELY(not(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
6661 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
24506662 {
24516663 return token_type::parse_error;
24526664 }
24566668 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
24576669 case 0xF0:
24586670 {
2459 if (JSON_UNLIKELY(not(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6671 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
24606672 {
24616673 return token_type::parse_error;
24626674 }
24686680 case 0xF2:
24696681 case 0xF3:
24706682 {
2471 if (JSON_UNLIKELY(not(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6683 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
24726684 {
24736685 return token_type::parse_error;
24746686 }
24786690 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
24796691 case 0xF4:
24806692 {
2481 if (JSON_UNLIKELY(not(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
6693 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
24826694 {
24836695 return token_type::parse_error;
24846696 }
24956707 }
24966708 }
24976709
6710 /*!
6711 * @brief scan a comment
6712 * @return whether comment could be scanned successfully
6713 */
6714 bool scan_comment()
6715 {
6716 switch (get())
6717 {
6718 // single-line comments skip input until a newline or EOF is read
6719 case '/':
6720 {
6721 while (true)
6722 {
6723 switch (get())
6724 {
6725 case '\n':
6726 case '\r':
6727 case std::char_traits<char_type>::eof():
6728 case '\0':
6729 return true;
6730
6731 default:
6732 break;
6733 }
6734 }
6735 }
6736
6737 // multi-line comments skip input until */ is read
6738 case '*':
6739 {
6740 while (true)
6741 {
6742 switch (get())
6743 {
6744 case std::char_traits<char_type>::eof():
6745 case '\0':
6746 {
6747 error_message = "invalid comment; missing closing '*/'";
6748 return false;
6749 }
6750
6751 case '*':
6752 {
6753 switch (get())
6754 {
6755 case '/':
6756 return true;
6757
6758 default:
6759 {
6760 unget();
6761 continue;
6762 }
6763 }
6764 }
6765
6766 default:
6767 continue;
6768 }
6769 }
6770 }
6771
6772 // unexpected character after reading '/'
6773 default:
6774 {
6775 error_message = "invalid comment; expecting '/' or '*' after '/'";
6776 return false;
6777 }
6778 }
6779 }
6780
6781 JSON_HEDLEY_NON_NULL(2)
24986782 static void strtof(float& f, const char* str, char** endptr) noexcept
24996783 {
2500 f = cpt::strtof(str, endptr);
2501 }
2502
6784 f = std::strtof(str, endptr);
6785 }
6786
6787 JSON_HEDLEY_NON_NULL(2)
25036788 static void strtof(double& f, const char* str, char** endptr) noexcept
25046789 {
25056790 f = std::strtod(str, endptr);
25066791 }
25076792
6793 JSON_HEDLEY_NON_NULL(2)
25086794 static void strtof(long double& f, const char* str, char** endptr) noexcept
25096795 {
2510 f = cpt::strtold(str, endptr);
6796 f = std::strtold(str, endptr);
25116797 }
25126798
25136799 /*!
25276813 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
25286814 zero | done | done | exponent | done | done | decimal1 | done
25296815 any1 | any1 | any1 | exponent | done | done | decimal1 | done
2530 decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error]
6816 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
25316817 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
25326818 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
25336819 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
25506836 locale's decimal point is used instead of `.` to work with the
25516837 locale-dependent converters.
25526838 */
2553 token_type scan_number()
6839 token_type scan_number() // lgtm [cpp/use-of-goto]
25546840 {
25556841 // reset token_buffer to store the number's bytes
25566842 reset();
25886874 goto scan_number_any1;
25896875 }
25906876
2591 default:
2592 {
2593 // all other characters are rejected outside scan_number()
2594 assert(false); // LCOV_EXCL_LINE
2595 }
2596 }
2597
2598 scan_number_minus:
6877 // all other characters are rejected outside scan_number()
6878 default: // LCOV_EXCL_LINE
6879 JSON_ASSERT(false); // LCOV_EXCL_LINE
6880 }
6881
6882 scan_number_minus:
25996883 // state: we just parsed a leading minus sign
26006884 number_type = token_type::value_integer;
26016885 switch (get())
26276911 }
26286912 }
26296913
2630 scan_number_zero:
6914 scan_number_zero:
26316915 // state: we just parse a zero (maybe with a leading minus sign)
26326916 switch (get())
26336917 {
26486932 goto scan_number_done;
26496933 }
26506934
2651 scan_number_any1:
6935 scan_number_any1:
26526936 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
26536937 switch (get())
26546938 {
26846968 goto scan_number_done;
26856969 }
26866970
2687 scan_number_decimal1:
6971 scan_number_decimal1:
26886972 // state: we just parsed a decimal point
26896973 number_type = token_type::value_float;
26906974 switch (get())
27116995 }
27126996 }
27136997
2714 scan_number_decimal2:
6998 scan_number_decimal2:
27156999 // we just parsed at least one number after a decimal point
27167000 switch (get())
27177001 {
27417025 goto scan_number_done;
27427026 }
27437027
2744 scan_number_exponent:
7028 scan_number_exponent:
27457029 // we just parsed an exponent
27467030 number_type = token_type::value_float;
27477031 switch (get())
27707054
27717055 default:
27727056 {
2773 error_message = "invalid number; expected '+', '-', or digit after exponent";
7057 error_message =
7058 "invalid number; expected '+', '-', or digit after exponent";
27747059 return token_type::parse_error;
27757060 }
27767061 }
27777062
2778 scan_number_sign:
7063 scan_number_sign:
27797064 // we just parsed an exponent sign
27807065 switch (get())
27817066 {
28017086 }
28027087 }
28037088
2804 scan_number_any2:
7089 scan_number_any2:
28057090 // we just parsed a number after the exponent or exponent sign
28067091 switch (get())
28077092 {
28247109 goto scan_number_done;
28257110 }
28267111
2827 scan_number_done:
7112 scan_number_done:
28287113 // unget the character after the number (we only read it to know that
28297114 // we are done scanning a number)
28307115 unget();
28357120 // try to parse integers first and fall back to floats
28367121 if (number_type == token_type::value_unsigned)
28377122 {
2838 const auto x = strtoull(token_buffer.data(), &endptr, 10);
7123 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
28397124
28407125 // we checked the number format before
2841 assert(endptr == token_buffer.data() + token_buffer.size());
7126 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
28427127
28437128 if (errno == 0)
28447129 {
28517136 }
28527137 else if (number_type == token_type::value_integer)
28537138 {
2854 const auto x = strtoll(token_buffer.data(), &endptr, 10);
7139 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
28557140
28567141 // we checked the number format before
2857 assert(endptr == token_buffer.data() + token_buffer.size());
7142 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
28587143
28597144 if (errno == 0)
28607145 {
28717156 strtof(value_float, token_buffer.data(), &endptr);
28727157
28737158 // we checked the number format before
2874 assert(endptr == token_buffer.data() + token_buffer.size());
7159 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
28757160
28767161 return token_type::value_float;
28777162 }
28817166 @param[in] length the length of the passed literal text
28827167 @param[in] return_type the token type to return on success
28837168 */
2884 token_type scan_literal(const char* literal_text, const std::size_t length, token_type return_type)
2885 {
2886 assert(current == literal_text[0]);
7169 JSON_HEDLEY_NON_NULL(2)
7170 token_type scan_literal(const char_type* literal_text, const std::size_t length,
7171 token_type return_type)
7172 {
7173 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
28877174 for (std::size_t i = 1; i < length; ++i)
28887175 {
2889 if (JSON_UNLIKELY(get() != literal_text[i]))
7176 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
28907177 {
28917178 error_message = "invalid literal";
28927179 return token_type::parse_error;
29047191 {
29057192 token_buffer.clear();
29067193 token_string.clear();
2907 token_string.push_back(std::char_traits<char>::to_char_type(current));
7194 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
29087195 }
29097196
29107197 /*
29177204
29187205 @return character read from the input
29197206 */
2920 std::char_traits<char>::int_type get()
2921 {
2922 ++chars_read;
2923 current = ia->get_character();
2924 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
2925 {
2926 token_string.push_back(std::char_traits<char>::to_char_type(current));
2927 }
7207 char_int_type get()
7208 {
7209 ++position.chars_read_total;
7210 ++position.chars_read_current_line;
7211
7212 if (next_unget)
7213 {
7214 // just reset the next_unget variable and work with current
7215 next_unget = false;
7216 }
7217 else
7218 {
7219 current = ia.get_character();
7220 }
7221
7222 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7223 {
7224 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7225 }
7226
7227 if (current == '\n')
7228 {
7229 ++position.lines_read;
7230 position.chars_read_current_line = 0;
7231 }
7232
29287233 return current;
29297234 }
29307235
2931 /// unget current character (return it again on next get)
7236 /*!
7237 @brief unget current character (read it again on next get)
7238
7239 We implement unget by setting variable next_unget to true. The input is not
7240 changed - we just simulate ungetting by modifying chars_read_total,
7241 chars_read_current_line, and token_string. The next call to get() will
7242 behave as if the unget character is read again.
7243 */
29327244 void unget()
29337245 {
2934 --chars_read;
2935 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
2936 {
2937 ia->unget_character();
2938 assert(token_string.size() != 0);
7246 next_unget = true;
7247
7248 --position.chars_read_total;
7249
7250 // in case we "unget" a newline, we have to also decrement the lines_read
7251 if (position.chars_read_current_line == 0)
7252 {
7253 if (position.lines_read > 0)
7254 {
7255 --position.lines_read;
7256 }
7257 }
7258 else
7259 {
7260 --position.chars_read_current_line;
7261 }
7262
7263 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7264 {
7265 JSON_ASSERT(!token_string.empty());
29397266 token_string.pop_back();
29407267 }
29417268 }
29427269
29437270 /// add a character to token_buffer
2944 void add(int c)
2945 {
2946 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
2947 }
2948
2949 public:
7271 void add(char_int_type c)
7272 {
7273 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7274 }
7275
7276 public:
29507277 /////////////////////
29517278 // value getters
29527279 /////////////////////
29707297 }
29717298
29727299 /// return current string value (implicitly resets the token; useful only once)
2973 string_t&& move_string()
2974 {
2975 return std::move(token_buffer);
7300 string_t& get_string()
7301 {
7302 return token_buffer;
29767303 }
29777304
29787305 /////////////////////
29807307 /////////////////////
29817308
29827309 /// return position of last read token
2983 constexpr std::size_t get_position() const noexcept
2984 {
2985 return chars_read;
7310 constexpr position_t get_position() const noexcept
7311 {
7312 return position;
29867313 }
29877314
29887315 /// return the last read token (for errors only). Will never contain EOF
29947321 std::string result;
29957322 for (const auto c : token_string)
29967323 {
2997 if ('\x00' <= c and c <= '\x1F')
7324 if (static_cast<unsigned char>(c) <= '\x1F')
29987325 {
29997326 // escape control characters
3000 std::stringstream ss;
3001 ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(c) << ">";
3002 result += ss.str();
7327 std::array<char, 9> cs{{}};
7328 (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
7329 result += cs.data();
30037330 }
30047331 else
30057332 {
30067333 // add character as is
3007 result.push_back(c);
7334 result.push_back(static_cast<std::string::value_type>(c));
30087335 }
30097336 }
30107337
30127339 }
30137340
30147341 /// return syntax error message
7342 JSON_HEDLEY_RETURNS_NON_NULL
30157343 constexpr const char* get_error_message() const noexcept
30167344 {
30177345 return error_message;
30217349 // actual scanner
30227350 /////////////////////
30237351
7352 /*!
7353 @brief skip the UTF-8 byte order mark
7354 @return true iff there is no BOM or the correct BOM has been skipped
7355 */
7356 bool skip_bom()
7357 {
7358 if (get() == 0xEF)
7359 {
7360 // check if we completely parse the BOM
7361 return get() == 0xBB && get() == 0xBF;
7362 }
7363
7364 // the first character is not the beginning of the BOM; unget it to
7365 // process is later
7366 unget();
7367 return true;
7368 }
7369
7370 void skip_whitespace()
7371 {
7372 do
7373 {
7374 get();
7375 }
7376 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7377 }
7378
30247379 token_type scan()
30257380 {
7381 // initially, skip the BOM
7382 if (position.chars_read_total == 0 && !skip_bom())
7383 {
7384 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7385 return token_type::parse_error;
7386 }
7387
30267388 // read next character and ignore whitespace
3027 do
3028 {
3029 get();
3030 } while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
7389 skip_whitespace();
7390
7391 // ignore comments
7392 while (ignore_comments && current == '/')
7393 {
7394 if (!scan_comment())
7395 {
7396 return token_type::parse_error;
7397 }
7398
7399 // skip following whitespace
7400 skip_whitespace();
7401 }
30317402
30327403 switch (current)
30337404 {
30477418
30487419 // literals
30497420 case 't':
3050 return scan_literal("true", 4, token_type::literal_true);
7421 {
7422 std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
7423 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7424 }
30517425 case 'f':
3052 return scan_literal("false", 5, token_type::literal_false);
7426 {
7427 std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}};
7428 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7429 }
30537430 case 'n':
3054 return scan_literal("null", 4, token_type::literal_null);
7431 {
7432 std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}};
7433 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7434 }
30557435
30567436 // string
30577437 case '\"':
30747454 // end of input (the null byte is needed when parsing from
30757455 // string literals)
30767456 case '\0':
3077 case std::char_traits<char>::eof():
7457 case std::char_traits<char_type>::eof():
30787458 return token_type::end_of_input;
30797459
30807460 // error
30847464 }
30857465 }
30867466
3087 private:
7467 private:
30887468 /// input adapter
3089 detail::input_adapter_t ia = nullptr;
7469 InputAdapterType ia;
7470
7471 /// whether comments should be ignored (true) or signaled as errors (false)
7472 const bool ignore_comments = false;
30907473
30917474 /// the current character
3092 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
3093
3094 /// the number of characters read
3095 std::size_t chars_read = 0;
7475 char_int_type current = std::char_traits<char_type>::eof();
7476
7477 /// whether the next get() call should just return current
7478 bool next_unget = false;
7479
7480 /// the start position of the current token
7481 position_t position {};
30967482
30977483 /// raw input token string (for error messages)
3098 std::vector<char> token_string{};
7484 std::vector<char_type> token_string {};
30997485
31007486 /// buffer for variable-length tokens (numbers, strings)
3101 string_t token_buffer{};
7487 string_t token_buffer {};
31027488
31037489 /// a description of occurred lexer errors
31047490 const char* error_message = "";
31097495 number_float_t value_float = 0;
31107496
31117497 /// the decimal point
3112 const char decimal_point_char = '.';
7498 const char_int_type decimal_point_char = '.';
31137499 };
3114 }
3115 }
3116
3117 // #include <nlohmann/detail/input/parser.hpp>
3118
3119
3120 #include <cassert> // assert
3121 #include <cmath> // isfinite
3122 #include <cstdint> // uint8_t
3123 #include <functional> // function
3124 #include <string> // string
3125 #include <utility> // move
3126
3127 // #include <nlohmann/detail/exceptions.hpp>
7500 } // namespace detail
7501 } // namespace nlohmann
31287502
31297503 // #include <nlohmann/detail/macro_scope.hpp>
31307504
3131 // #include <nlohmann/detail/input/input_adapters.hpp>
3132
3133 // #include <nlohmann/detail/input/lexer.hpp>
3134
3135 // #include <nlohmann/detail/value_t.hpp>
7505 // #include <nlohmann/detail/meta/is_sax.hpp>
7506
7507
7508 #include <cstdint> // size_t
7509 #include <utility> // declval
7510 #include <string> // string
7511
7512 // #include <nlohmann/detail/meta/detected.hpp>
7513
7514 // #include <nlohmann/detail/meta/type_traits.hpp>
31367515
31377516
31387517 namespace nlohmann
31397518 {
31407519 namespace detail
31417520 {
3142 ////////////
3143 // parser //
3144 ////////////
7521 template<typename T>
7522 using null_function_t = decltype(std::declval<T&>().null());
7523
7524 template<typename T>
7525 using boolean_function_t =
7526 decltype(std::declval<T&>().boolean(std::declval<bool>()));
7527
7528 template<typename T, typename Integer>
7529 using number_integer_function_t =
7530 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
7531
7532 template<typename T, typename Unsigned>
7533 using number_unsigned_function_t =
7534 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
7535
7536 template<typename T, typename Float, typename String>
7537 using number_float_function_t = decltype(std::declval<T&>().number_float(
7538 std::declval<Float>(), std::declval<const String&>()));
7539
7540 template<typename T, typename String>
7541 using string_function_t =
7542 decltype(std::declval<T&>().string(std::declval<String&>()));
7543
7544 template<typename T, typename Binary>
7545 using binary_function_t =
7546 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
7547
7548 template<typename T>
7549 using start_object_function_t =
7550 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
7551
7552 template<typename T, typename String>
7553 using key_function_t =
7554 decltype(std::declval<T&>().key(std::declval<String&>()));
7555
7556 template<typename T>
7557 using end_object_function_t = decltype(std::declval<T&>().end_object());
7558
7559 template<typename T>
7560 using start_array_function_t =
7561 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
7562
7563 template<typename T>
7564 using end_array_function_t = decltype(std::declval<T&>().end_array());
7565
7566 template<typename T, typename Exception>
7567 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
7568 std::declval<std::size_t>(), std::declval<const std::string&>(),
7569 std::declval<const Exception&>()));
7570
7571 template<typename SAX, typename BasicJsonType>
7572 struct is_sax
7573 {
7574 private:
7575 static_assert(is_basic_json<BasicJsonType>::value,
7576 "BasicJsonType must be of type basic_json<...>");
7577
7578 using number_integer_t = typename BasicJsonType::number_integer_t;
7579 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7580 using number_float_t = typename BasicJsonType::number_float_t;
7581 using string_t = typename BasicJsonType::string_t;
7582 using binary_t = typename BasicJsonType::binary_t;
7583 using exception_t = typename BasicJsonType::exception;
7584
7585 public:
7586 static constexpr bool value =
7587 is_detected_exact<bool, null_function_t, SAX>::value &&
7588 is_detected_exact<bool, boolean_function_t, SAX>::value &&
7589 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
7590 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
7591 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
7592 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
7593 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
7594 is_detected_exact<bool, start_object_function_t, SAX>::value &&
7595 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
7596 is_detected_exact<bool, end_object_function_t, SAX>::value &&
7597 is_detected_exact<bool, start_array_function_t, SAX>::value &&
7598 is_detected_exact<bool, end_array_function_t, SAX>::value &&
7599 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
7600 };
7601
7602 template<typename SAX, typename BasicJsonType>
7603 struct is_sax_static_asserts
7604 {
7605 private:
7606 static_assert(is_basic_json<BasicJsonType>::value,
7607 "BasicJsonType must be of type basic_json<...>");
7608
7609 using number_integer_t = typename BasicJsonType::number_integer_t;
7610 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7611 using number_float_t = typename BasicJsonType::number_float_t;
7612 using string_t = typename BasicJsonType::string_t;
7613 using binary_t = typename BasicJsonType::binary_t;
7614 using exception_t = typename BasicJsonType::exception;
7615
7616 public:
7617 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
7618 "Missing/invalid function: bool null()");
7619 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7620 "Missing/invalid function: bool boolean(bool)");
7621 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7622 "Missing/invalid function: bool boolean(bool)");
7623 static_assert(
7624 is_detected_exact<bool, number_integer_function_t, SAX,
7625 number_integer_t>::value,
7626 "Missing/invalid function: bool number_integer(number_integer_t)");
7627 static_assert(
7628 is_detected_exact<bool, number_unsigned_function_t, SAX,
7629 number_unsigned_t>::value,
7630 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
7631 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
7632 number_float_t, string_t>::value,
7633 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
7634 static_assert(
7635 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
7636 "Missing/invalid function: bool string(string_t&)");
7637 static_assert(
7638 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
7639 "Missing/invalid function: bool binary(binary_t&)");
7640 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
7641 "Missing/invalid function: bool start_object(std::size_t)");
7642 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
7643 "Missing/invalid function: bool key(string_t&)");
7644 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
7645 "Missing/invalid function: bool end_object()");
7646 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
7647 "Missing/invalid function: bool start_array(std::size_t)");
7648 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
7649 "Missing/invalid function: bool end_array()");
7650 static_assert(
7651 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
7652 "Missing/invalid function: bool parse_error(std::size_t, const "
7653 "std::string&, const exception&)");
7654 };
7655 } // namespace detail
7656 } // namespace nlohmann
7657
7658 // #include <nlohmann/detail/value_t.hpp>
7659
7660
7661 namespace nlohmann
7662 {
7663 namespace detail
7664 {
7665
7666 /// how to treat CBOR tags
7667 enum class cbor_tag_handler_t
7668 {
7669 error, ///< throw a parse_error exception in case of a tag
7670 ignore ///< ignore tags
7671 };
31457672
31467673 /*!
3147 @brief syntax analysis
3148
3149 This class implements a recursive decent parser.
7674 @brief determine system byte order
7675
7676 @return true if and only if system's byte order is little endian
7677
7678 @note from https://stackoverflow.com/a/1001328/266378
31507679 */
3151 template <typename BasicJsonType>
3152 class parser
7680 static inline bool little_endianess(int num = 1) noexcept
7681 {
7682 return *reinterpret_cast<char*>(&num) == 1;
7683 }
7684
7685
7686 ///////////////////
7687 // binary reader //
7688 ///////////////////
7689
7690 /*!
7691 @brief deserialization of CBOR, MessagePack, and UBJSON values
7692 */
7693 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
7694 class binary_reader
31537695 {
31547696 using number_integer_t = typename BasicJsonType::number_integer_t;
31557697 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
31567698 using number_float_t = typename BasicJsonType::number_float_t;
31577699 using string_t = typename BasicJsonType::string_t;
3158 using lexer_t = lexer<BasicJsonType>;
3159 using token_type = typename lexer_t::token_type;
3160
3161 public:
3162 enum class parse_event_t : uint8_t
3163 {
3164 /// the parser read `{` and started to process a JSON object
3165 object_start,
3166 /// the parser read `}` and finished processing a JSON object
3167 object_end,
3168 /// the parser read `[` and started to process a JSON array
3169 array_start,
3170 /// the parser read `]` and finished processing a JSON array
3171 array_end,
3172 /// the parser read a key of a value in an object
3173 key,
3174 /// the parser finished reading a JSON value
3175 value
3176 };
3177
3178 using parser_callback_t = std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
3179
3180 /// a parser reading from an input adapter
3181 explicit parser(detail::input_adapter_t adapter, const parser_callback_t cb = nullptr, const bool allow_exceptions_ = true)
3182 : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
3183 {
3184 }
3185
3186 /*!
3187 @brief public parser interface
3188
3189 @param[in] strict whether to expect the last token to be EOF
3190 @param[in,out] result parsed JSON value
3191
3192 @throw parse_error.101 in case of an unexpected token
3193 @throw parse_error.102 if to_unicode fails or surrogate error
3194 @throw parse_error.103 if to_unicode fails
3195 */
3196 void parse(const bool strict, BasicJsonType& result)
3197 {
3198 // read first token
3199 get_token();
3200
3201 parse_internal(true, result);
3202 result.assert_invariant();
3203
3204 // in strict mode, input must be completely read
3205 if (strict)
3206 {
3207 get_token();
3208 expect(token_type::end_of_input);
3209 }
3210
3211 // in case of an error, return discarded value
3212 if (errored)
3213 {
3214 result = value_t::discarded;
3215 return;
3216 }
3217
3218 // set top-level value to null if it was discarded by the callback
3219 // function
3220 if (result.is_discarded())
3221 {
3222 result = nullptr;
3223 }
3224 }
3225
3226 /*!
3227 @brief public accept interface
3228
3229 @param[in] strict whether to expect the last token to be EOF
3230 @return whether the input is a proper JSON text
3231 */
3232 bool accept(const bool strict = true)
3233 {
3234 // read first token
3235 get_token();
3236
3237 if (not accept_internal())
7700 using binary_t = typename BasicJsonType::binary_t;
7701 using json_sax_t = SAX;
7702 using char_type = typename InputAdapterType::char_type;
7703 using char_int_type = typename std::char_traits<char_type>::int_type;
7704
7705 public:
7706 /*!
7707 @brief create a binary reader
7708
7709 @param[in] adapter input adapter to read from
7710 */
7711 explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter))
7712 {
7713 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
7714 }
7715
7716 // make class move-only
7717 binary_reader(const binary_reader&) = delete;
7718 binary_reader(binary_reader&&) = default;
7719 binary_reader& operator=(const binary_reader&) = delete;
7720 binary_reader& operator=(binary_reader&&) = default;
7721 ~binary_reader() = default;
7722
7723 /*!
7724 @param[in] format the binary format to parse
7725 @param[in] sax_ a SAX event processor
7726 @param[in] strict whether to expect the input to be consumed completed
7727 @param[in] tag_handler how to treat CBOR tags
7728
7729 @return
7730 */
7731 JSON_HEDLEY_NON_NULL(3)
7732 bool sax_parse(const input_format_t format,
7733 json_sax_t* sax_,
7734 const bool strict = true,
7735 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7736 {
7737 sax = sax_;
7738 bool result = false;
7739
7740 switch (format)
7741 {
7742 case input_format_t::bson:
7743 result = parse_bson_internal();
7744 break;
7745
7746 case input_format_t::cbor:
7747 result = parse_cbor_internal(true, tag_handler);
7748 break;
7749
7750 case input_format_t::msgpack:
7751 result = parse_msgpack_internal();
7752 break;
7753
7754 case input_format_t::ubjson:
7755 result = parse_ubjson_internal();
7756 break;
7757
7758 default: // LCOV_EXCL_LINE
7759 JSON_ASSERT(false); // LCOV_EXCL_LINE
7760 }
7761
7762 // strict mode: next byte must be EOF
7763 if (result && strict)
7764 {
7765 if (format == input_format_t::ubjson)
7766 {
7767 get_ignore_noop();
7768 }
7769 else
7770 {
7771 get();
7772 }
7773
7774 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
7775 {
7776 return sax->parse_error(chars_read, get_token_string(),
7777 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
7778 }
7779 }
7780
7781 return result;
7782 }
7783
7784 private:
7785 //////////
7786 // BSON //
7787 //////////
7788
7789 /*!
7790 @brief Reads in a BSON-object and passes it to the SAX-parser.
7791 @return whether a valid BSON-value was passed to the SAX parser
7792 */
7793 bool parse_bson_internal()
7794 {
7795 std::int32_t document_size{};
7796 get_number<std::int32_t, true>(input_format_t::bson, document_size);
7797
7798 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
32387799 {
32397800 return false;
32407801 }
32417802
3242 // strict => last token must be EOF
3243 return not strict or (get_token() == token_type::end_of_input);
3244 }
3245
3246 private:
3247 /*!
3248 @brief the actual parser
3249 @throw parse_error.101 in case of an unexpected token
3250 @throw parse_error.102 if to_unicode fails or surrogate error
3251 @throw parse_error.103 if to_unicode fails
3252 */
3253 void parse_internal(bool keep, BasicJsonType& result)
3254 {
3255 // never parse after a parse error was detected
3256 assert(not errored);
3257
3258 // start with a discarded value
3259 if (not result.is_discarded())
3260 {
3261 result.m_value.destroy(result.m_type);
3262 result.m_type = value_t::discarded;
3263 }
3264
3265 switch (last_token)
3266 {
3267 case token_type::begin_object:
3268 {
3269 if (keep)
3270 {
3271 if (callback)
3272 {
3273 keep = callback(depth++, parse_event_t::object_start, result);
3274 }
3275
3276 if (not callback or keep)
3277 {
3278 // explicitly set result to object to cope with {}
3279 result.m_type = value_t::object;
3280 result.m_value = value_t::object;
3281 }
3282 }
3283
3284 // read next token
3285 get_token();
3286
3287 // closing } -> we are done
3288 if (last_token == token_type::end_object)
3289 {
3290 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
3291 {
3292 result.m_value.destroy(result.m_type);
3293 result.m_type = value_t::discarded;
3294 }
3295 break;
3296 }
3297
3298 // parse values
3299 string_t key;
3300 BasicJsonType value;
3301 while (true)
3302 {
3303 // store key
3304 if (not expect(token_type::value_string))
3305 {
3306 return;
3307 }
3308 key = m_lexer.move_string();
3309
3310 bool keep_tag = false;
3311 if (keep)
3312 {
3313 if (callback)
3314 {
3315 BasicJsonType k(key);
3316 keep_tag = callback(depth, parse_event_t::key, k);
3317 }
3318 else
3319 {
3320 keep_tag = true;
3321 }
3322 }
3323
3324 // parse separator (:)
3325 get_token();
3326 if (not expect(token_type::name_separator))
3327 {
3328 return;
3329 }
3330
3331 // parse and add value
3332 get_token();
3333 value.m_value.destroy(value.m_type);
3334 value.m_type = value_t::discarded;
3335 parse_internal(keep, value);
3336
3337 if (JSON_UNLIKELY(errored))
3338 {
3339 return;
3340 }
3341
3342 if (keep and keep_tag and not value.is_discarded())
3343 {
3344 result.m_value.object->emplace(std::move(key), std::move(value));
3345 }
3346
3347 // comma -> next value
3348 get_token();
3349 if (last_token == token_type::value_separator)
3350 {
3351 get_token();
3352 continue;
3353 }
3354
3355 // closing }
3356 if (not expect(token_type::end_object))
3357 {
3358 return;
3359 }
3360 break;
3361 }
3362
3363 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
3364 {
3365 result.m_value.destroy(result.m_type);
3366 result.m_type = value_t::discarded;
3367 }
3368 break;
3369 }
3370
3371 case token_type::begin_array:
3372 {
3373 if (keep)
3374 {
3375 if (callback)
3376 {
3377 keep = callback(depth++, parse_event_t::array_start, result);
3378 }
3379
3380 if (not callback or keep)
3381 {
3382 // explicitly set result to array to cope with []
3383 result.m_type = value_t::array;
3384 result.m_value = value_t::array;
3385 }
3386 }
3387
3388 // read next token
3389 get_token();
3390
3391 // closing ] -> we are done
3392 if (last_token == token_type::end_array)
3393 {
3394 if (callback and not callback(--depth, parse_event_t::array_end, result))
3395 {
3396 result.m_value.destroy(result.m_type);
3397 result.m_type = value_t::discarded;
3398 }
3399 break;
3400 }
3401
3402 // parse values
3403 BasicJsonType value;
3404 while (true)
3405 {
3406 // parse value
3407 value.m_value.destroy(value.m_type);
3408 value.m_type = value_t::discarded;
3409 parse_internal(keep, value);
3410
3411 if (JSON_UNLIKELY(errored))
3412 {
3413 return;
3414 }
3415
3416 if (keep and not value.is_discarded())
3417 {
3418 result.m_value.array->push_back(std::move(value));
3419 }
3420
3421 // comma -> next value
3422 get_token();
3423 if (last_token == token_type::value_separator)
3424 {
3425 get_token();
3426 continue;
3427 }
3428
3429 // closing ]
3430 if (not expect(token_type::end_array))
3431 {
3432 return;
3433 }
3434 break;
3435 }
3436
3437 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
3438 {
3439 result.m_value.destroy(result.m_type);
3440 result.m_type = value_t::discarded;
3441 }
3442 break;
3443 }
3444
3445 case token_type::literal_null:
3446 {
3447 result.m_type = value_t::null;
3448 break;
3449 }
3450
3451 case token_type::value_string:
3452 {
3453 result.m_type = value_t::string;
3454 result.m_value = m_lexer.move_string();
3455 break;
3456 }
3457
3458 case token_type::literal_true:
3459 {
3460 result.m_type = value_t::boolean;
3461 result.m_value = true;
3462 break;
3463 }
3464
3465 case token_type::literal_false:
3466 {
3467 result.m_type = value_t::boolean;
3468 result.m_value = false;
3469 break;
3470 }
3471
3472 case token_type::value_unsigned:
3473 {
3474 result.m_type = value_t::number_unsigned;
3475 result.m_value = m_lexer.get_number_unsigned();
3476 break;
3477 }
3478
3479 case token_type::value_integer:
3480 {
3481 result.m_type = value_t::number_integer;
3482 result.m_value = m_lexer.get_number_integer();
3483 break;
3484 }
3485
3486 case token_type::value_float:
3487 {
3488 result.m_type = value_t::number_float;
3489 result.m_value = m_lexer.get_number_float();
3490
3491 // throw in case of infinity or NAN
3492 if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
3493 {
3494 if (allow_exceptions)
3495 {
3496 JSON_THROW(out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
3497 }
3498 expect(token_type::uninitialized);
3499 }
3500 break;
3501 }
3502
3503 case token_type::parse_error:
3504 {
3505 // using "uninitialized" to avoid "expected" message
3506 if (not expect(token_type::uninitialized))
3507 {
3508 return;
3509 }
3510 break; // LCOV_EXCL_LINE
3511 }
3512
3513 default:
3514 {
3515 // the last token was unexpected; we expected a value
3516 if (not expect(token_type::literal_or_value))
3517 {
3518 return;
3519 }
3520 break; // LCOV_EXCL_LINE
3521 }
3522 }
3523
3524 if (keep and callback and not callback(depth, parse_event_t::value, result))
3525 {
3526 result.m_value.destroy(result.m_type);
3527 result.m_type = value_t::discarded;
3528 }
3529 }
3530
3531 /*!
3532 @brief the actual acceptor
3533
3534 @invariant 1. The last token is not yet processed. Therefore, the caller
3535 of this function must make sure a token has been read.
3536 2. When this function returns, the last token is processed.
3537 That is, the last read character was already considered.
3538
3539 This invariant makes sure that no token needs to be "unput".
3540 */
3541 bool accept_internal()
3542 {
3543 switch (last_token)
3544 {
3545 case token_type::begin_object:
3546 {
3547 // read next token
3548 get_token();
3549
3550 // closing } -> we are done
3551 if (last_token == token_type::end_object)
3552 {
3553 return true;
3554 }
3555
3556 // parse values
3557 while (true)
3558 {
3559 // parse key
3560 if (last_token != token_type::value_string)
3561 {
3562 return false;
3563 }
3564
3565 // parse separator (:)
3566 get_token();
3567 if (last_token != token_type::name_separator)
3568 {
3569 return false;
3570 }
3571
3572 // parse value
3573 get_token();
3574 if (not accept_internal())
3575 {
3576 return false;
3577 }
3578
3579 // comma -> next value
3580 get_token();
3581 if (last_token == token_type::value_separator)
3582 {
3583 get_token();
3584 continue;
3585 }
3586
3587 // closing }
3588 return (last_token == token_type::end_object);
3589 }
3590 }
3591
3592 case token_type::begin_array:
3593 {
3594 // read next token
3595 get_token();
3596
3597 // closing ] -> we are done
3598 if (last_token == token_type::end_array)
3599 {
3600 return true;
3601 }
3602
3603 // parse values
3604 while (true)
3605 {
3606 // parse value
3607 if (not accept_internal())
3608 {
3609 return false;
3610 }
3611
3612 // comma -> next value
3613 get_token();
3614 if (last_token == token_type::value_separator)
3615 {
3616 get_token();
3617 continue;
3618 }
3619
3620 // closing ]
3621 return (last_token == token_type::end_array);
3622 }
3623 }
3624
3625 case token_type::value_float:
3626 {
3627 // reject infinity or NAN
3628 return std::isfinite(m_lexer.get_number_float());
3629 }
3630
3631 case token_type::literal_false:
3632 case token_type::literal_null:
3633 case token_type::literal_true:
3634 case token_type::value_integer:
3635 case token_type::value_string:
3636 case token_type::value_unsigned:
7803 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
7804 {
7805 return false;
7806 }
7807
7808 return sax->end_object();
7809 }
7810
7811 /*!
7812 @brief Parses a C-style string from the BSON input.
7813 @param[in, out] result A reference to the string variable where the read
7814 string is to be stored.
7815 @return `true` if the \x00-byte indicating the end of the string was
7816 encountered before the EOF; false` indicates an unexpected EOF.
7817 */
7818 bool get_bson_cstr(string_t& result)
7819 {
7820 auto out = std::back_inserter(result);
7821 while (true)
7822 {
7823 get();
7824 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
7825 {
7826 return false;
7827 }
7828 if (current == 0x00)
7829 {
36377830 return true;
3638
3639 default: // the last token was unexpected
7831 }
7832 *out++ = static_cast<typename string_t::value_type>(current);
7833 }
7834 }
7835
7836 /*!
7837 @brief Parses a zero-terminated string of length @a len from the BSON
7838 input.
7839 @param[in] len The length (including the zero-byte at the end) of the
7840 string to be read.
7841 @param[in, out] result A reference to the string variable where the read
7842 string is to be stored.
7843 @tparam NumberType The type of the length @a len
7844 @pre len >= 1
7845 @return `true` if the string was successfully parsed
7846 */
7847 template<typename NumberType>
7848 bool get_bson_string(const NumberType len, string_t& result)
7849 {
7850 if (JSON_HEDLEY_UNLIKELY(len < 1))
7851 {
7852 auto last_token = get_token_string();
7853 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
7854 }
7855
7856 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
7857 }
7858
7859 /*!
7860 @brief Parses a byte array input of length @a len from the BSON input.
7861 @param[in] len The length of the byte array to be read.
7862 @param[in, out] result A reference to the binary variable where the read
7863 array is to be stored.
7864 @tparam NumberType The type of the length @a len
7865 @pre len >= 0
7866 @return `true` if the byte array was successfully parsed
7867 */
7868 template<typename NumberType>
7869 bool get_bson_binary(const NumberType len, binary_t& result)
7870 {
7871 if (JSON_HEDLEY_UNLIKELY(len < 0))
7872 {
7873 auto last_token = get_token_string();
7874 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary")));
7875 }
7876
7877 // All BSON binary values have a subtype
7878 std::uint8_t subtype{};
7879 get_number<std::uint8_t>(input_format_t::bson, subtype);
7880 result.set_subtype(subtype);
7881
7882 return get_binary(input_format_t::bson, len, result);
7883 }
7884
7885 /*!
7886 @brief Read a BSON document element of the given @a element_type.
7887 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
7888 @param[in] element_type_parse_position The position in the input stream,
7889 where the `element_type` was read.
7890 @warning Not all BSON element types are supported yet. An unsupported
7891 @a element_type will give rise to a parse_error.114:
7892 Unsupported BSON record type 0x...
7893 @return whether a valid BSON-object/array was passed to the SAX parser
7894 */
7895 bool parse_bson_element_internal(const char_int_type element_type,
7896 const std::size_t element_type_parse_position)
7897 {
7898 switch (element_type)
7899 {
7900 case 0x01: // double
7901 {
7902 double number{};
7903 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
7904 }
7905
7906 case 0x02: // string
7907 {
7908 std::int32_t len{};
7909 string_t value;
7910 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
7911 }
7912
7913 case 0x03: // object
7914 {
7915 return parse_bson_internal();
7916 }
7917
7918 case 0x04: // array
7919 {
7920 return parse_bson_array();
7921 }
7922
7923 case 0x05: // binary
7924 {
7925 std::int32_t len{};
7926 binary_t value;
7927 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
7928 }
7929
7930 case 0x08: // boolean
7931 {
7932 return sax->boolean(get() != 0);
7933 }
7934
7935 case 0x0A: // null
7936 {
7937 return sax->null();
7938 }
7939
7940 case 0x10: // int32
7941 {
7942 std::int32_t value{};
7943 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7944 }
7945
7946 case 0x12: // int64
7947 {
7948 std::int64_t value{};
7949 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7950 }
7951
7952 default: // anything else not supported (yet)
7953 {
7954 std::array<char, 3> cr{{}};
7955 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
7956 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
7957 }
7958 }
7959 }
7960
7961 /*!
7962 @brief Read a BSON element list (as specified in the BSON-spec)
7963
7964 The same binary layout is used for objects and arrays, hence it must be
7965 indicated with the argument @a is_array which one is expected
7966 (true --> array, false --> object).
7967
7968 @param[in] is_array Determines if the element list being read is to be
7969 treated as an object (@a is_array == false), or as an
7970 array (@a is_array == true).
7971 @return whether a valid BSON-object/array was passed to the SAX parser
7972 */
7973 bool parse_bson_element_list(const bool is_array)
7974 {
7975 string_t key;
7976
7977 while (auto element_type = get())
7978 {
7979 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
7980 {
36407981 return false;
3641 }
3642 }
3643
3644 /// get next token from lexer
3645 token_type get_token()
3646 {
3647 return (last_token = m_lexer.scan());
3648 }
3649
3650 /*!
3651 @throw parse_error.101 if expected token did not occur
3652 */
3653 bool expect(token_type t)
3654 {
3655 if (JSON_UNLIKELY(t != last_token))
3656 {
3657 errored = true;
3658 expected = t;
3659 if (allow_exceptions)
3660 {
3661 throw_exception();
3662 }
3663 else
7982 }
7983
7984 const std::size_t element_type_parse_position = chars_read;
7985 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
36647986 {
36657987 return false;
36667988 }
7989
7990 if (!is_array && !sax->key(key))
7991 {
7992 return false;
7993 }
7994
7995 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
7996 {
7997 return false;
7998 }
7999
8000 // get_bson_cstr only appends
8001 key.clear();
36678002 }
36688003
36698004 return true;
36708005 }
36718006
3672 [[noreturn]] void throw_exception() const
3673 {
3674 std::string error_msg = "syntax error - ";
3675 if (last_token == token_type::parse_error)
3676 {
3677 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + m_lexer.get_token_string() + "'";
3678 }
3679 else
3680 {
3681 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
3682 }
3683
3684 if (expected != token_type::uninitialized)
3685 {
3686 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
3687 }
3688
3689 JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
3690 }
3691
3692 private:
3693 /// current level of recursion
3694 int depth = 0;
3695 /// callback function
3696 const parser_callback_t callback = nullptr;
3697 /// the type of the last read token
3698 token_type last_token = token_type::uninitialized;
3699 /// the lexer
3700 lexer_t m_lexer;
3701 /// whether a syntax error occurred
3702 bool errored = false;
3703 /// possible reason for the syntax error
3704 token_type expected = token_type::uninitialized;
3705 /// whether to throw exceptions in case of errors
3706 const bool allow_exceptions = true;
3707 };
3708 }
3709 }
3710
3711 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
3712
3713
3714 #include <cstddef> // ptrdiff_t
3715 #include <limits> // numeric_limits
3716
3717 namespace nlohmann
3718 {
3719 namespace detail
3720 {
3721 /*
3722 @brief an iterator for primitive JSON types
3723
3724 This class models an iterator for primitive JSON types (boolean, number,
3725 string). It's only purpose is to allow the iterator/const_iterator classes
3726 to "iterate" over primitive values. Internally, the iterator is modeled by
3727 a `difference_type` variable. Value begin_value (`0`) models the begin,
3728 end_value (`1`) models past the end.
3729 */
3730 class primitive_iterator_t
3731 {
3732 private:
3733 using difference_type = std::ptrdiff_t;
3734 static constexpr difference_type begin_value = 0;
3735 static constexpr difference_type end_value = begin_value + 1;
3736
3737 /// iterator as signed integer type
3738 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
3739
3740 public:
3741 constexpr difference_type get_value() const noexcept
3742 {
3743 return m_it;
3744 }
3745
3746 /// set iterator to a defined beginning
3747 void set_begin() noexcept
3748 {
3749 m_it = begin_value;
3750 }
3751
3752 /// set iterator to a defined past the end
3753 void set_end() noexcept
3754 {
3755 m_it = end_value;
3756 }
3757
3758 /// return whether the iterator can be dereferenced
3759 constexpr bool is_begin() const noexcept
3760 {
3761 return m_it == begin_value;
3762 }
3763
3764 /// return whether the iterator is at end
3765 constexpr bool is_end() const noexcept
3766 {
3767 return m_it == end_value;
3768 }
3769
3770 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
3771 {
3772 return lhs.m_it == rhs.m_it;
3773 }
3774
3775 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
3776 {
3777 return lhs.m_it < rhs.m_it;
3778 }
3779
3780 primitive_iterator_t operator+(difference_type n) noexcept
3781 {
3782 auto result = *this;
3783 result += n;
3784 return result;
3785 }
3786
3787 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
3788 {
3789 return lhs.m_it - rhs.m_it;
3790 }
3791
3792 primitive_iterator_t& operator++() noexcept
3793 {
3794 ++m_it;
3795 return *this;
3796 }
3797
3798 primitive_iterator_t const operator++(int)noexcept
3799 {
3800 auto result = *this;
3801 m_it++;
3802 return result;
3803 }
3804
3805 primitive_iterator_t& operator--() noexcept
3806 {
3807 --m_it;
3808 return *this;
3809 }
3810
3811 primitive_iterator_t const operator--(int)noexcept
3812 {
3813 auto result = *this;
3814 m_it--;
3815 return result;
3816 }
3817
3818 primitive_iterator_t& operator+=(difference_type n) noexcept
3819 {
3820 m_it += n;
3821 return *this;
3822 }
3823
3824 primitive_iterator_t& operator-=(difference_type n) noexcept
3825 {
3826 m_it -= n;
3827 return *this;
3828 }
3829 };
3830 }
3831 }
3832
3833 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
3834
3835
3836 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
3837
3838
3839 namespace nlohmann
3840 {
3841 namespace detail
3842 {
3843 /*!
3844 @brief an iterator value
3845
3846 @note This structure could easily be a union, but MSVC currently does not allow
3847 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
3848 */
3849 template <typename BasicJsonType>
3850 struct internal_iterator
3851 {
3852 /// iterator for JSON objects
3853 typename BasicJsonType::object_t::iterator object_iterator{};
3854 /// iterator for JSON arrays
3855 typename BasicJsonType::array_t::iterator array_iterator{};
3856 /// generic iterator for all other types
3857 primitive_iterator_t primitive_iterator{};
3858 };
3859 }
3860 }
3861
3862 // #include <nlohmann/detail/iterators/iter_impl.hpp>
3863
3864
3865 #include <ciso646> // not
3866 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
3867 #include <type_traits> // conditional, is_const, remove_const
3868
3869 // #include <nlohmann/detail/exceptions.hpp>
3870
3871 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
3872
3873 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
3874
3875 // #include <nlohmann/detail/macro_scope.hpp>
3876
3877 // #include <nlohmann/detail/meta.hpp>
3878
3879 // #include <nlohmann/detail/value_t.hpp>
3880
3881
3882 namespace nlohmann
3883 {
3884 namespace detail
3885 {
3886 // forward declare, to be able to friend it later on
3887 template <typename IteratorType>
3888 class iteration_proxy;
3889
3890 /*!
3891 @brief a template for a bidirectional iterator for the @ref basic_json class
3892
3893 This class implements a both iterators (iterator and const_iterator) for the
3894 @ref basic_json class.
3895
3896 @note An iterator is called *initialized* when a pointer to a JSON value has
3897 been set (e.g., by a constructor or a copy assignment). If the iterator is
3898 default-constructed, it is *uninitialized* and most methods are undefined.
3899 **The library uses assertions to detect calls on uninitialized iterators.**
3900
3901 @requirement The class satisfies the following concept requirements:
3902 -
3903 [BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
3904 The iterator that can be moved can be moved in both directions (i.e.
3905 incremented and decremented).
3906
3907 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
3908 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
3909 */
3910 template <typename BasicJsonType>
3911 class iter_impl
3912 {
3913 /// allow basic_json to access private members
3914 friend iter_impl<
3915 typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
3916 friend BasicJsonType;
3917 friend iteration_proxy<iter_impl>;
3918
3919 using object_t = typename BasicJsonType::object_t;
3920 using array_t = typename BasicJsonType::array_t;
3921 // make sure BasicJsonType is basic_json or const basic_json
3922 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, "iter_impl only accepts (const) basic_json");
3923
3924 public:
3925 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
3926 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
3927 /// A user-defined iterator should provide publicly accessible typedefs named
3928 /// iterator_category, value_type, difference_type, pointer, and reference.
3929 /// Note that value_type is required to be non-const, even for constant iterators.
3930 using iterator_category = std::bidirectional_iterator_tag;
3931
3932 /// the type of the values when the iterator is dereferenced
3933 using value_type = typename BasicJsonType::value_type;
3934 /// a type to represent differences between iterators
3935 using difference_type = typename BasicJsonType::difference_type;
3936 /// defines a pointer to the type iterated over (value_type)
3937 using pointer =
3938 typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer>::type;
3939 /// defines a reference to the type iterated over (value_type)
3940 using reference =
3941 typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type;
3942
3943 /// default constructor
3944 iter_impl() = default;
3945
3946 /*!
3947 @brief constructor for a given JSON instance
3948 @param[in] object pointer to a JSON object for this iterator
3949 @pre object != nullptr
3950 @post The iterator is initialized; i.e. `m_object != nullptr`.
3951 */
3952 explicit iter_impl(pointer object) noexcept : m_object(object)
3953 {
3954 assert(m_object != nullptr);
3955
3956 switch (m_object->m_type)
3957 {
3958 case value_t::object:
3959 {
3960 m_it.object_iterator = typename object_t::iterator();
3961 break;
3962 }
3963
3964 case value_t::array:
3965 {
3966 m_it.array_iterator = typename array_t::iterator();
3967 break;
3968 }
3969
3970 default:
3971 {
3972 m_it.primitive_iterator = primitive_iterator_t();
3973 break;
3974 }
3975 }
3976 }
3977
3978 /*!
3979 @note The conventional copy constructor and copy assignment are implicitly
3980 defined. Combined with the following converting constructor and
3981 assignment, they support: (1) copy from iterator to iterator, (2)
3982 copy from const iterator to const iterator, and (3) conversion from
3983 iterator to const iterator. However conversion from const iterator
3984 to iterator is not defined.
3985 */
3986
3987 /*!
3988 @brief converting constructor
3989 @param[in] other non-const iterator to copy from
3990 @note It is not checked whether @a other is initialized.
3991 */
3992 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept : m_object(other.m_object), m_it(other.m_it)
3993 {
3994 }
3995
3996 /*!
3997 @brief converting assignment
3998 @param[in,out] other non-const iterator to copy from
3999 @return const/non-const iterator
4000 @note It is not checked whether @a other is initialized.
4001 */
4002 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
4003 {
4004 m_object = other.m_object;
4005 m_it = other.m_it;
4006 return *this;
4007 }
4008
4009 private:
4010 /*!
4011 @brief set the iterator to the first value
4012 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4013 */
4014 void set_begin() noexcept
4015 {
4016 assert(m_object != nullptr);
4017
4018 switch (m_object->m_type)
4019 {
4020 case value_t::object:
4021 {
4022 m_it.object_iterator = m_object->m_value.object->begin();
4023 break;
4024 }
4025
4026 case value_t::array:
4027 {
4028 m_it.array_iterator = m_object->m_value.array->begin();
4029 break;
4030 }
4031
4032 case value_t::null:
4033 {
4034 // set to end so begin()==end() is true: null is empty
4035 m_it.primitive_iterator.set_end();
4036 break;
4037 }
4038
4039 default:
4040 {
4041 m_it.primitive_iterator.set_begin();
4042 break;
4043 }
4044 }
4045 }
4046
4047 /*!
4048 @brief set the iterator past the last value
4049 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4050 */
4051 void set_end() noexcept
4052 {
4053 assert(m_object != nullptr);
4054
4055 switch (m_object->m_type)
4056 {
4057 case value_t::object:
4058 {
4059 m_it.object_iterator = m_object->m_value.object->end();
4060 break;
4061 }
4062
4063 case value_t::array:
4064 {
4065 m_it.array_iterator = m_object->m_value.array->end();
4066 break;
4067 }
4068
4069 default:
4070 {
4071 m_it.primitive_iterator.set_end();
4072 break;
4073 }
4074 }
4075 }
4076
4077 public:
4078 /*!
4079 @brief return a reference to the value pointed to by the iterator
4080 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4081 */
4082 reference operator*() const
4083 {
4084 assert(m_object != nullptr);
4085
4086 switch (m_object->m_type)
4087 {
4088 case value_t::object:
4089 {
4090 assert(m_it.object_iterator != m_object->m_value.object->end());
4091 return m_it.object_iterator->second;
4092 }
4093
4094 case value_t::array:
4095 {
4096 assert(m_it.array_iterator != m_object->m_value.array->end());
4097 return *m_it.array_iterator;
4098 }
4099
4100 case value_t::null:
4101 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
4102
4103 default:
4104 {
4105 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
4106 {
4107 return *m_object;
4108 }
4109
4110 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
4111 }
4112 }
4113 }
4114
4115 /*!
4116 @brief dereference the iterator
4117 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4118 */
4119 pointer operator->() const
4120 {
4121 assert(m_object != nullptr);
4122
4123 switch (m_object->m_type)
4124 {
4125 case value_t::object:
4126 {
4127 assert(m_it.object_iterator != m_object->m_value.object->end());
4128 return &(m_it.object_iterator->second);
4129 }
4130
4131 case value_t::array:
4132 {
4133 assert(m_it.array_iterator != m_object->m_value.array->end());
4134 return &*m_it.array_iterator;
4135 }
4136
4137 default:
4138 {
4139 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
4140 {
4141 return m_object;
4142 }
4143
4144 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
4145 }
4146 }
4147 }
4148
4149 /*!
4150 @brief post-increment (it++)
4151 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4152 */
4153 iter_impl const operator++(int)
4154 {
4155 auto result = *this;
4156 ++(*this);
4157 return result;
4158 }
4159
4160 /*!
4161 @brief pre-increment (++it)
4162 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4163 */
4164 iter_impl& operator++()
4165 {
4166 assert(m_object != nullptr);
4167
4168 switch (m_object->m_type)
4169 {
4170 case value_t::object:
4171 {
4172 std::advance(m_it.object_iterator, 1);
4173 break;
4174 }
4175
4176 case value_t::array:
4177 {
4178 std::advance(m_it.array_iterator, 1);
4179 break;
4180 }
4181
4182 default:
4183 {
4184 ++m_it.primitive_iterator;
4185 break;
4186 }
4187 }
4188
4189 return *this;
4190 }
4191
4192 /*!
4193 @brief post-decrement (it--)
4194 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4195 */
4196 iter_impl const operator--(int)
4197 {
4198 auto result = *this;
4199 --(*this);
4200 return result;
4201 }
4202
4203 /*!
4204 @brief pre-decrement (--it)
4205 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4206 */
4207 iter_impl& operator--()
4208 {
4209 assert(m_object != nullptr);
4210
4211 switch (m_object->m_type)
4212 {
4213 case value_t::object:
4214 {
4215 std::advance(m_it.object_iterator, -1);
4216 break;
4217 }
4218
4219 case value_t::array:
4220 {
4221 std::advance(m_it.array_iterator, -1);
4222 break;
4223 }
4224
4225 default:
4226 {
4227 --m_it.primitive_iterator;
4228 break;
4229 }
4230 }
4231
4232 return *this;
4233 }
4234
4235 /*!
4236 @brief comparison: equal
4237 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4238 */
4239 bool operator==(const iter_impl& other) const
4240 {
4241 // if objects are not the same, the comparison is undefined
4242 if (JSON_UNLIKELY(m_object != other.m_object))
4243 {
4244 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
4245 }
4246
4247 assert(m_object != nullptr);
4248
4249 switch (m_object->m_type)
4250 {
4251 case value_t::object:
4252 return (m_it.object_iterator == other.m_it.object_iterator);
4253
4254 case value_t::array:
4255 return (m_it.array_iterator == other.m_it.array_iterator);
4256
4257 default:
4258 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
4259 }
4260 }
4261
4262 /*!
4263 @brief comparison: not equal
4264 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4265 */
4266 bool operator!=(const iter_impl& other) const
4267 {
4268 return not operator==(other);
4269 }
4270
4271 /*!
4272 @brief comparison: smaller
4273 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4274 */
4275 bool operator<(const iter_impl& other) const
4276 {
4277 // if objects are not the same, the comparison is undefined
4278 if (JSON_UNLIKELY(m_object != other.m_object))
4279 {
4280 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
4281 }
4282
4283 assert(m_object != nullptr);
4284
4285 switch (m_object->m_type)
4286 {
4287 case value_t::object:
4288 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
4289
4290 case value_t::array:
4291 return (m_it.array_iterator < other.m_it.array_iterator);
4292
4293 default:
4294 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
4295 }
4296 }
4297
4298 /*!
4299 @brief comparison: less than or equal
4300 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4301 */
4302 bool operator<=(const iter_impl& other) const
4303 {
4304 return not other.operator<(*this);
4305 }
4306
4307 /*!
4308 @brief comparison: greater than
4309 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4310 */
4311 bool operator>(const iter_impl& other) const
4312 {
4313 return not operator<=(other);
4314 }
4315
4316 /*!
4317 @brief comparison: greater than or equal
4318 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4319 */
4320 bool operator>=(const iter_impl& other) const
4321 {
4322 return not operator<(other);
4323 }
4324
4325 /*!
4326 @brief add to iterator
4327 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4328 */
4329 iter_impl& operator+=(difference_type i)
4330 {
4331 assert(m_object != nullptr);
4332
4333 switch (m_object->m_type)
4334 {
4335 case value_t::object:
4336 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
4337
4338 case value_t::array:
4339 {
4340 std::advance(m_it.array_iterator, i);
4341 break;
4342 }
4343
4344 default:
4345 {
4346 m_it.primitive_iterator += i;
4347 break;
4348 }
4349 }
4350
4351 return *this;
4352 }
4353
4354 /*!
4355 @brief subtract from iterator
4356 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4357 */
4358 iter_impl& operator-=(difference_type i)
4359 {
4360 return operator+=(-i);
4361 }
4362
4363 /*!
4364 @brief add to iterator
4365 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4366 */
4367 iter_impl operator+(difference_type i) const
4368 {
4369 auto result = *this;
4370 result += i;
4371 return result;
4372 }
4373
4374 /*!
4375 @brief addition of distance and iterator
4376 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4377 */
4378 friend iter_impl operator+(difference_type i, const iter_impl& it)
4379 {
4380 auto result = it;
4381 result += i;
4382 return result;
4383 }
4384
4385 /*!
4386 @brief subtract from iterator
4387 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4388 */
4389 iter_impl operator-(difference_type i) const
4390 {
4391 auto result = *this;
4392 result -= i;
4393 return result;
4394 }
4395
4396 /*!
4397 @brief return difference
4398 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4399 */
4400 difference_type operator-(const iter_impl& other) const
4401 {
4402 assert(m_object != nullptr);
4403
4404 switch (m_object->m_type)
4405 {
4406 case value_t::object:
4407 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
4408
4409 case value_t::array:
4410 return m_it.array_iterator - other.m_it.array_iterator;
4411
4412 default:
4413 return m_it.primitive_iterator - other.m_it.primitive_iterator;
4414 }
4415 }
4416
4417 /*!
4418 @brief access to successor
4419 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4420 */
4421 reference operator[](difference_type n) const
4422 {
4423 assert(m_object != nullptr);
4424
4425 switch (m_object->m_type)
4426 {
4427 case value_t::object:
4428 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
4429
4430 case value_t::array:
4431 return *std::next(m_it.array_iterator, n);
4432
4433 case value_t::null:
4434 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
4435
4436 default:
4437 {
4438 if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
4439 {
4440 return *m_object;
4441 }
4442
4443 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
4444 }
4445 }
4446 }
4447
4448 /*!
4449 @brief return the key of an object iterator
4450 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4451 */
4452 typename object_t::key_type key() const
4453 {
4454 assert(m_object != nullptr);
4455
4456 if (JSON_LIKELY(m_object->is_object()))
4457 {
4458 return m_it.object_iterator->first;
4459 }
4460
4461 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
4462 }
4463
4464 /*!
4465 @brief return the value of an iterator
4466 @pre The iterator is initialized; i.e. `m_object != nullptr`.
4467 */
4468 reference value() const
4469 {
4470 return operator*();
4471 }
4472
4473 private:
4474 /// associated JSON instance
4475 pointer m_object = nullptr;
4476 /// the actual iterator of the associated instance
4477 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
4478 };
4479 }
4480 }
4481
4482 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4483
4484
4485 #include <cstddef> // size_t
4486 #include <string> // string, to_string
4487
4488 // #include <nlohmann/detail/value_t.hpp>
4489
4490
4491 namespace nlohmann
4492 {
4493 namespace detail
4494 {
4495 /// proxy class for the items() function
4496 template <typename IteratorType>
4497 class iteration_proxy
4498 {
4499 private:
4500 /// helper class for iteration
4501 class iteration_proxy_internal
4502 {
4503 private:
4504 /// the iterator
4505 IteratorType anchor;
4506 /// an index for arrays (used to create key names)
4507 std::size_t array_index = 0;
4508
4509 public:
4510 explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it)
4511 {
4512 }
4513
4514 /// dereference operator (needed for range-based for)
4515 iteration_proxy_internal& operator*()
4516 {
4517 return *this;
4518 }
4519
4520 /// increment operator (needed for range-based for)
4521 iteration_proxy_internal& operator++()
4522 {
4523 ++anchor;
4524 ++array_index;
4525
4526 return *this;
4527 }
4528
4529 /// inequality operator (needed for range-based for)
4530 bool operator!=(const iteration_proxy_internal& o) const noexcept
4531 {
4532 return anchor != o.anchor;
4533 }
4534
4535 /// return key of the iterator
4536 std::string key() const
4537 {
4538 assert(anchor.m_object != nullptr);
4539
4540 switch (anchor.m_object->type())
4541 {
4542 // use integer array index as key
4543 case value_t::array:
4544 return cpt::to_string(array_index);
4545
4546 // use key from the object
4547 case value_t::object:
4548 return anchor.key();
4549
4550 // use an empty key for all primitive types
4551 default:
4552 return "";
4553 }
4554 }
4555
4556 /// return value of the iterator
4557 typename IteratorType::reference value() const
4558 {
4559 return anchor.value();
4560 }
4561 };
4562
4563 /// the container to iterate
4564 typename IteratorType::reference container;
4565
4566 public:
4567 /// construct iteration proxy from a container
4568 explicit iteration_proxy(typename IteratorType::reference cont) noexcept : container(cont)
4569 {
4570 }
4571
4572 /// return iterator begin (needed for range-based for)
4573 iteration_proxy_internal begin() noexcept
4574 {
4575 return iteration_proxy_internal(container.begin());
4576 }
4577
4578 /// return iterator end (needed for range-based for)
4579 iteration_proxy_internal end() noexcept
4580 {
4581 return iteration_proxy_internal(container.end());
4582 }
4583 };
4584 }
4585 }
4586
4587 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
4588
4589
4590 #include <cstddef> // ptrdiff_t
4591 #include <iterator> // reverse_iterator
4592 #include <utility> // declval
4593
4594 namespace nlohmann
4595 {
4596 namespace detail
4597 {
4598 //////////////////////
4599 // reverse_iterator //
4600 //////////////////////
4601
4602 /*!
4603 @brief a template for a reverse iterator class
4604
4605 @tparam Base the base iterator type to reverse. Valid types are @ref
4606 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
4607 create @ref const_reverse_iterator).
4608
4609 @requirement The class satisfies the following concept requirements:
4610 -
4611 [BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
4612 The iterator that can be moved can be moved in both directions (i.e.
4613 incremented and decremented).
4614 - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
4615 It is possible to write to the pointed-to element (only if @a Base is
4616 @ref iterator).
4617
4618 @since version 1.0.0
4619 */
4620 template <typename Base>
4621 class json_reverse_iterator : public std::reverse_iterator<Base>
4622 {
4623 public:
4624 using difference_type = std::ptrdiff_t;
4625 /// shortcut to the reverse iterator adapter
4626 using base_iterator = std::reverse_iterator<Base>;
4627 /// the reference type for the pointed-to element
4628 using reference = typename Base::reference;
4629
4630 /// create reverse iterator from iterator
4631 json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept : base_iterator(it)
4632 {
4633 }
4634
4635 /// create reverse iterator from base class
4636 json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it)
4637 {
4638 }
4639
4640 /// post-increment (it++)
4641 json_reverse_iterator const operator++(int)
4642 {
4643 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
4644 }
4645
4646 /// pre-increment (++it)
4647 json_reverse_iterator& operator++()
4648 {
4649 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
4650 }
4651
4652 /// post-decrement (it--)
4653 json_reverse_iterator const operator--(int)
4654 {
4655 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
4656 }
4657
4658 /// pre-decrement (--it)
4659 json_reverse_iterator& operator--()
4660 {
4661 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
4662 }
4663
4664 /// add to iterator
4665 json_reverse_iterator& operator+=(difference_type i)
4666 {
4667 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
4668 }
4669
4670 /// add to iterator
4671 json_reverse_iterator operator+(difference_type i) const
4672 {
4673 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
4674 }
4675
4676 /// subtract from iterator
4677 json_reverse_iterator operator-(difference_type i) const
4678 {
4679 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
4680 }
4681
4682 /// return difference
4683 difference_type operator-(const json_reverse_iterator& other) const
4684 {
4685 return base_iterator(*this) - base_iterator(other);
4686 }
4687
4688 /// access to successor
4689 reference operator[](difference_type n) const
4690 {
4691 return *(this->operator+(n));
4692 }
4693
4694 /// return the key of an object iterator
4695 auto key() const -> decltype(std::declval<Base>().key())
4696 {
4697 auto it = --this->base();
4698 return it.key();
4699 }
4700
4701 /// return the value of an iterator
4702 reference value() const
4703 {
4704 auto it = --this->base();
4705 return it.operator*();
4706 }
4707 };
4708 }
4709 }
4710
4711 // #include <nlohmann/detail/output/output_adapters.hpp>
4712
4713
4714 #include <algorithm> // copy
4715 #include <cstddef> // size_t
4716 #include <ios> // streamsize
4717 #include <iterator> // back_inserter
4718 #include <memory> // shared_ptr, make_shared
4719 #include <ostream> // basic_ostream
4720 #include <string> // basic_string
4721 #include <vector> // vector
4722
4723 namespace nlohmann
4724 {
4725 namespace detail
4726 {
4727 /// abstract output adapter interface
4728 template <typename CharType>
4729 struct output_adapter_protocol
4730 {
4731 virtual void write_character(CharType c) = 0;
4732 virtual void write_characters(const CharType* s, std::size_t length) = 0;
4733 virtual ~output_adapter_protocol() = default;
4734 };
4735
4736 /// a type to simplify interfaces
4737 template <typename CharType>
4738 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
4739
4740 /// output adapter for byte vectors
4741 template <typename CharType>
4742 class output_vector_adapter : public output_adapter_protocol<CharType>
4743 {
4744 public:
4745 explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec)
4746 {
4747 }
4748
4749 void write_character(CharType c) override
4750 {
4751 v.push_back(c);
4752 }
4753
4754 void write_characters(const CharType* s, std::size_t length) override
4755 {
4756 std::copy(s, s + length, std::back_inserter(v));
4757 }
4758
4759 private:
4760 std::vector<CharType>& v;
4761 };
4762
4763 /// output adapter for output streams
4764 template <typename CharType>
4765 class output_stream_adapter : public output_adapter_protocol<CharType>
4766 {
4767 public:
4768 explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s)
4769 {
4770 }
4771
4772 void write_character(CharType c) override
4773 {
4774 stream.put(c);
4775 }
4776
4777 void write_characters(const CharType* s, std::size_t length) override
4778 {
4779 stream.write(s, static_cast<std::streamsize>(length));
4780 }
4781
4782 private:
4783 std::basic_ostream<CharType>& stream;
4784 };
4785
4786 /// output adapter for basic_string
4787 template <typename CharType, typename StringType = std::basic_string<CharType>>
4788 class output_string_adapter : public output_adapter_protocol<CharType>
4789 {
4790 public:
4791 explicit output_string_adapter(StringType& s) : str(s)
4792 {
4793 }
4794
4795 void write_character(CharType c) override
4796 {
4797 str.push_back(c);
4798 }
4799
4800 void write_characters(const CharType* s, std::size_t length) override
4801 {
4802 str.append(s, length);
4803 }
4804
4805 private:
4806 StringType& str;
4807 };
4808
4809 template <typename CharType, typename StringType = std::basic_string<CharType>>
4810 class output_adapter
4811 {
4812 public:
4813 output_adapter(std::vector<CharType>& vec) : oa(std::make_shared<output_vector_adapter<CharType>>(vec))
4814 {
4815 }
4816
4817 output_adapter(std::basic_ostream<CharType>& s) : oa(std::make_shared<output_stream_adapter<CharType>>(s))
4818 {
4819 }
4820
4821 output_adapter(StringType& s) : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s))
4822 {
4823 }
4824
4825 operator output_adapter_t<CharType>()
4826 {
4827 return oa;
4828 }
4829
4830 private:
4831 output_adapter_t<CharType> oa = nullptr;
4832 };
4833 }
4834 }
4835
4836 // #include <nlohmann/detail/input/binary_reader.hpp>
4837
4838
4839 #include <algorithm> // generate_n
4840 #include <array> // array
4841 #include <cassert> // assert
4842 #include <cmath> // ldexp
4843 #include <cstddef> // size_t
4844 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
4845 #include <cstring> // memcpy
4846 #include <iomanip> // setw, setfill
4847 #include <ios> // hex
4848 #include <iterator> // back_inserter
4849 #include <limits> // numeric_limits
4850 #include <sstream> // stringstream
4851 #include <string> // char_traits, string
4852 #include <utility> // make_pair, move
4853
4854 // #include <nlohmann/detail/input/input_adapters.hpp>
4855
4856 // #include <nlohmann/detail/exceptions.hpp>
4857
4858 // #include <nlohmann/detail/macro_scope.hpp>
4859
4860 // #include <nlohmann/detail/value_t.hpp>
4861
4862
4863 namespace nlohmann
4864 {
4865 namespace detail
4866 {
4867 ///////////////////
4868 // binary reader //
4869 ///////////////////
4870
4871 /*!
4872 @brief deserialization of CBOR and MessagePack values
4873 */
4874 template <typename BasicJsonType>
4875 class binary_reader
4876 {
4877 using number_integer_t = typename BasicJsonType::number_integer_t;
4878 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4879 using string_t = typename BasicJsonType::string_t;
4880
4881 public:
4882 /*!
4883 @brief create a binary reader
4884
4885 @param[in] adapter input adapter to read from
4886 */
4887 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
4888 {
4889 assert(ia);
4890 }
4891
4892 /*!
4893 @brief create a JSON value from CBOR input
4894
4895 @param[in] strict whether to expect the input to be consumed completed
4896 @return JSON value created from CBOR input
4897
4898 @throw parse_error.110 if input ended unexpectedly or the end of file was
4899 not reached when @a strict was set to true
4900 @throw parse_error.112 if unsupported byte was read
4901 */
4902 BasicJsonType parse_cbor(const bool strict)
4903 {
4904 const auto res = parse_cbor_internal();
4905 if (strict)
4906 {
4907 get();
4908 expect_eof();
4909 }
4910 return res;
4911 }
4912
4913 /*!
4914 @brief create a JSON value from MessagePack input
4915
4916 @param[in] strict whether to expect the input to be consumed completed
4917 @return JSON value created from MessagePack input
4918
4919 @throw parse_error.110 if input ended unexpectedly or the end of file was
4920 not reached when @a strict was set to true
4921 @throw parse_error.112 if unsupported byte was read
4922 */
4923 BasicJsonType parse_msgpack(const bool strict)
4924 {
4925 const auto res = parse_msgpack_internal();
4926 if (strict)
4927 {
4928 get();
4929 expect_eof();
4930 }
4931 return res;
4932 }
4933
4934 /*!
4935 @brief create a JSON value from UBJSON input
4936
4937 @param[in] strict whether to expect the input to be consumed completed
4938 @return JSON value created from UBJSON input
4939
4940 @throw parse_error.110 if input ended unexpectedly or the end of file was
4941 not reached when @a strict was set to true
4942 @throw parse_error.112 if unsupported byte was read
4943 */
4944 BasicJsonType parse_ubjson(const bool strict)
4945 {
4946 const auto res = parse_ubjson_internal();
4947 if (strict)
4948 {
4949 get_ignore_noop();
4950 expect_eof();
4951 }
4952 return res;
4953 }
4954
4955 /*!
4956 @brief determine system byte order
4957
4958 @return true if and only if system's byte order is little endian
4959
4960 @note from http://stackoverflow.com/a/1001328/266378
4961 */
4962 static constexpr bool little_endianess(int num = 1) noexcept
4963 {
4964 return (*reinterpret_cast<char*>(&num) == 1);
4965 }
4966
4967 private:
8007 /*!
8008 @brief Reads an array from the BSON input and passes it to the SAX-parser.
8009 @return whether a valid BSON-array was passed to the SAX parser
8010 */
8011 bool parse_bson_array()
8012 {
8013 std::int32_t document_size{};
8014 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8015
8016 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
8017 {
8018 return false;
8019 }
8020
8021 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8022 {
8023 return false;
8024 }
8025
8026 return sax->end_array();
8027 }
8028
8029 //////////
8030 // CBOR //
8031 //////////
8032
49688033 /*!
49698034 @param[in] get_char whether a new character should be retrieved from the
4970 input (true, default) or whether the last read
4971 character should be considered instead
4972 */
4973 BasicJsonType parse_cbor_internal(const bool get_char = true)
8035 input (true) or whether the last read character should
8036 be considered instead (false)
8037 @param[in] tag_handler how CBOR tags should be treated
8038
8039 @return whether a valid CBOR value was passed to the SAX parser
8040 */
8041 bool parse_cbor_internal(const bool get_char,
8042 const cbor_tag_handler_t tag_handler)
49748043 {
49758044 switch (get_char ? get() : current)
49768045 {
49778046 // EOF
4978 case std::char_traits<char>::eof():
4979 JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
8047 case std::char_traits<char_type>::eof():
8048 return unexpect_eof(input_format_t::cbor, "value");
49808049
49818050 // Integer 0x00..0x17 (0..23)
49828051 case 0x00:
50038072 case 0x15:
50048073 case 0x16:
50058074 case 0x17:
5006 return static_cast<number_unsigned_t>(current);
8075 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
50078076
50088077 case 0x18: // Unsigned integer (one-byte uint8_t follows)
5009 return get_number<uint8_t>();
8078 {
8079 std::uint8_t number{};
8080 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8081 }
50108082
50118083 case 0x19: // Unsigned integer (two-byte uint16_t follows)
5012 return get_number<uint16_t>();
8084 {
8085 std::uint16_t number{};
8086 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8087 }
50138088
50148089 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
5015 return get_number<uint32_t>();
8090 {
8091 std::uint32_t number{};
8092 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8093 }
50168094
50178095 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
5018 return get_number<uint64_t>();
8096 {
8097 std::uint64_t number{};
8098 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8099 }
50198100
50208101 // Negative integer -1-0x00..-1-0x17 (-1..-24)
50218102 case 0x20:
50428123 case 0x35:
50438124 case 0x36:
50448125 case 0x37:
5045 return static_cast<int8_t>(0x20 - 1 - current);
8126 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
50468127
50478128 case 0x38: // Negative integer (one-byte uint8_t follows)
50488129 {
5049 return static_cast<number_integer_t>(-1) - get_number<uint8_t>();
8130 std::uint8_t number{};
8131 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
50508132 }
50518133
50528134 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
50538135 {
5054 return static_cast<number_integer_t>(-1) - get_number<uint16_t>();
8136 std::uint16_t number{};
8137 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
50558138 }
50568139
50578140 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
50588141 {
5059 return static_cast<number_integer_t>(-1) - get_number<uint32_t>();
8142 std::uint32_t number{};
8143 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
50608144 }
50618145
50628146 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
50638147 {
5064 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_number<uint64_t>());
8148 std::uint64_t number{};
8149 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8150 - static_cast<number_integer_t>(number));
8151 }
8152
8153 // Binary data (0x00..0x17 bytes follow)
8154 case 0x40:
8155 case 0x41:
8156 case 0x42:
8157 case 0x43:
8158 case 0x44:
8159 case 0x45:
8160 case 0x46:
8161 case 0x47:
8162 case 0x48:
8163 case 0x49:
8164 case 0x4A:
8165 case 0x4B:
8166 case 0x4C:
8167 case 0x4D:
8168 case 0x4E:
8169 case 0x4F:
8170 case 0x50:
8171 case 0x51:
8172 case 0x52:
8173 case 0x53:
8174 case 0x54:
8175 case 0x55:
8176 case 0x56:
8177 case 0x57:
8178 case 0x58: // Binary data (one-byte uint8_t for n follows)
8179 case 0x59: // Binary data (two-byte uint16_t for n follow)
8180 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8181 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8182 case 0x5F: // Binary data (indefinite length)
8183 {
8184 binary_t b;
8185 return get_cbor_binary(b) && sax->binary(b);
50658186 }
50668187
50678188 // UTF-8 string (0x00..0x17 bytes follow)
50958216 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
50968217 case 0x7F: // UTF-8 string (indefinite length)
50978218 {
5098 return get_cbor_string();
8219 string_t s;
8220 return get_cbor_string(s) && sax->string(s);
50998221 }
51008222
51018223 // array (0x00..0x17 data items follow)
51238245 case 0x95:
51248246 case 0x96:
51258247 case 0x97:
5126 {
5127 return get_cbor_array(current & 0x1F);
5128 }
8248 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
51298249
51308250 case 0x98: // array (one-byte uint8_t for n follows)
51318251 {
5132 return get_cbor_array(get_number<uint8_t>());
8252 std::uint8_t len{};
8253 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
51338254 }
51348255
51358256 case 0x99: // array (two-byte uint16_t for n follow)
51368257 {
5137 return get_cbor_array(get_number<uint16_t>());
8258 std::uint16_t len{};
8259 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
51388260 }
51398261
51408262 case 0x9A: // array (four-byte uint32_t for n follow)
51418263 {
5142 return get_cbor_array(get_number<uint32_t>());
8264 std::uint32_t len{};
8265 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
51438266 }
51448267
51458268 case 0x9B: // array (eight-byte uint64_t for n follow)
51468269 {
5147 return get_cbor_array(get_number<uint64_t>());
8270 std::uint64_t len{};
8271 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
51488272 }
51498273
51508274 case 0x9F: // array (indefinite length)
5151 {
5152 BasicJsonType result = value_t::array;
5153 while (get() != 0xFF)
5154 {
5155 result.push_back(parse_cbor_internal(false));
5156 }
5157 return result;
5158 }
8275 return get_cbor_array(std::size_t(-1), tag_handler);
51598276
51608277 // map (0x00..0x17 pairs of data items follow)
51618278 case 0xA0:
51828299 case 0xB5:
51838300 case 0xB6:
51848301 case 0xB7:
5185 {
5186 return get_cbor_object(current & 0x1F);
5187 }
8302 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
51888303
51898304 case 0xB8: // map (one-byte uint8_t for n follows)
51908305 {
5191 return get_cbor_object(get_number<uint8_t>());
8306 std::uint8_t len{};
8307 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
51928308 }
51938309
51948310 case 0xB9: // map (two-byte uint16_t for n follow)
51958311 {
5196 return get_cbor_object(get_number<uint16_t>());
8312 std::uint16_t len{};
8313 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
51978314 }
51988315
51998316 case 0xBA: // map (four-byte uint32_t for n follow)
52008317 {
5201 return get_cbor_object(get_number<uint32_t>());
8318 std::uint32_t len{};
8319 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
52028320 }
52038321
52048322 case 0xBB: // map (eight-byte uint64_t for n follow)
52058323 {
5206 return get_cbor_object(get_number<uint64_t>());
8324 std::uint64_t len{};
8325 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
52078326 }
52088327
52098328 case 0xBF: // map (indefinite length)
5210 {
5211 BasicJsonType result = value_t::object;
5212 while (get() != 0xFF)
8329 return get_cbor_object(std::size_t(-1), tag_handler);
8330
8331 case 0xC6: // tagged item
8332 case 0xC7:
8333 case 0xC8:
8334 case 0xC9:
8335 case 0xCA:
8336 case 0xCB:
8337 case 0xCC:
8338 case 0xCD:
8339 case 0xCE:
8340 case 0xCF:
8341 case 0xD0:
8342 case 0xD1:
8343 case 0xD2:
8344 case 0xD3:
8345 case 0xD4:
8346 case 0xD8: // tagged item (1 bytes follow)
8347 case 0xD9: // tagged item (2 bytes follow)
8348 case 0xDA: // tagged item (4 bytes follow)
8349 case 0xDB: // tagged item (8 bytes follow)
8350 {
8351 switch (tag_handler)
52138352 {
5214 auto key = get_cbor_string();
5215 result[key] = parse_cbor_internal();
8353 case cbor_tag_handler_t::error:
8354 {
8355 auto last_token = get_token_string();
8356 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
8357 }
8358
8359 case cbor_tag_handler_t::ignore:
8360 {
8361 switch (current)
8362 {
8363 case 0xD8:
8364 {
8365 std::uint8_t len{};
8366 get_number(input_format_t::cbor, len);
8367 break;
8368 }
8369 case 0xD9:
8370 {
8371 std::uint16_t len{};
8372 get_number(input_format_t::cbor, len);
8373 break;
8374 }
8375 case 0xDA:
8376 {
8377 std::uint32_t len{};
8378 get_number(input_format_t::cbor, len);
8379 break;
8380 }
8381 case 0xDB:
8382 {
8383 std::uint64_t len{};
8384 get_number(input_format_t::cbor, len);
8385 break;
8386 }
8387 default:
8388 break;
8389 }
8390 return parse_cbor_internal(true, tag_handler);
8391 }
8392
8393 default: // LCOV_EXCL_LINE
8394 JSON_ASSERT(false); // LCOV_EXCL_LINE
52168395 }
5217 return result;
52188396 }
52198397
52208398 case 0xF4: // false
5221 {
5222 return false;
5223 }
8399 return sax->boolean(false);
52248400
52258401 case 0xF5: // true
5226 {
5227 return true;
5228 }
8402 return sax->boolean(true);
52298403
52308404 case 0xF6: // null
5231 {
5232 return value_t::null;
5233 }
8405 return sax->null();
52348406
52358407 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
52368408 {
5237 const int byte1 = get();
5238 unexpect_eof();
5239 const int byte2 = get();
5240 unexpect_eof();
8409 const auto byte1_raw = get();
8410 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8411 {
8412 return false;
8413 }
8414 const auto byte2_raw = get();
8415 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8416 {
8417 return false;
8418 }
8419
8420 const auto byte1 = static_cast<unsigned char>(byte1_raw);
8421 const auto byte2 = static_cast<unsigned char>(byte2_raw);
52418422
52428423 // code from RFC 7049, Appendix D, Figure 3:
52438424 // As half-precision floating-point numbers were only added
52478428 // without such support. An example of a small decoder for
52488429 // half-precision floating-point numbers in the C language
52498430 // is shown in Fig. 3.
5250 const int half = (byte1 << 8) + byte2;
5251 const int exp = (half >> 10) & 0x1F;
5252 const int mant = half & 0x3FF;
5253 double val;
5254 if (exp == 0)
8431 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
8432 const double val = [&half]
52558433 {
5256 val = std::ldexp(mant, -24);
8434 const int exp = (half >> 10u) & 0x1Fu;
8435 const unsigned int mant = half & 0x3FFu;
8436 JSON_ASSERT(0 <= exp&& exp <= 32);
8437 JSON_ASSERT(mant <= 1024);
8438 switch (exp)
8439 {
8440 case 0:
8441 return std::ldexp(mant, -24);
8442 case 31:
8443 return (mant == 0)
8444 ? std::numeric_limits<double>::infinity()
8445 : std::numeric_limits<double>::quiet_NaN();
8446 default:
8447 return std::ldexp(mant + 1024, exp - 25);
8448 }
8449 }();
8450 return sax->number_float((half & 0x8000u) != 0
8451 ? static_cast<number_float_t>(-val)
8452 : static_cast<number_float_t>(val), "");
8453 }
8454
8455 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
8456 {
8457 float number{};
8458 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8459 }
8460
8461 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
8462 {
8463 double number{};
8464 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8465 }
8466
8467 default: // anything else (0xFF is handled inside the other types)
8468 {
8469 auto last_token = get_token_string();
8470 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
8471 }
8472 }
8473 }
8474
8475 /*!
8476 @brief reads a CBOR string
8477
8478 This function first reads starting bytes to determine the expected
8479 string length and then copies this number of bytes into a string.
8480 Additionally, CBOR's strings with indefinite lengths are supported.
8481
8482 @param[out] result created string
8483
8484 @return whether string creation completed
8485 */
8486 bool get_cbor_string(string_t& result)
8487 {
8488 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
8489 {
8490 return false;
8491 }
8492
8493 switch (current)
8494 {
8495 // UTF-8 string (0x00..0x17 bytes follow)
8496 case 0x60:
8497 case 0x61:
8498 case 0x62:
8499 case 0x63:
8500 case 0x64:
8501 case 0x65:
8502 case 0x66:
8503 case 0x67:
8504 case 0x68:
8505 case 0x69:
8506 case 0x6A:
8507 case 0x6B:
8508 case 0x6C:
8509 case 0x6D:
8510 case 0x6E:
8511 case 0x6F:
8512 case 0x70:
8513 case 0x71:
8514 case 0x72:
8515 case 0x73:
8516 case 0x74:
8517 case 0x75:
8518 case 0x76:
8519 case 0x77:
8520 {
8521 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8522 }
8523
8524 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8525 {
8526 std::uint8_t len{};
8527 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8528 }
8529
8530 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8531 {
8532 std::uint16_t len{};
8533 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8534 }
8535
8536 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8537 {
8538 std::uint32_t len{};
8539 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8540 }
8541
8542 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8543 {
8544 std::uint64_t len{};
8545 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8546 }
8547
8548 case 0x7F: // UTF-8 string (indefinite length)
8549 {
8550 while (get() != 0xFF)
8551 {
8552 string_t chunk;
8553 if (!get_cbor_string(chunk))
8554 {
8555 return false;
8556 }
8557 result.append(chunk);
52578558 }
5258 else if (exp != 31)
8559 return true;
8560 }
8561
8562 default:
8563 {
8564 auto last_token = get_token_string();
8565 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
8566 }
8567 }
8568 }
8569
8570 /*!
8571 @brief reads a CBOR byte array
8572
8573 This function first reads starting bytes to determine the expected
8574 byte array length and then copies this number of bytes into the byte array.
8575 Additionally, CBOR's byte arrays with indefinite lengths are supported.
8576
8577 @param[out] result created byte array
8578
8579 @return whether byte array creation completed
8580 */
8581 bool get_cbor_binary(binary_t& result)
8582 {
8583 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
8584 {
8585 return false;
8586 }
8587
8588 switch (current)
8589 {
8590 // Binary data (0x00..0x17 bytes follow)
8591 case 0x40:
8592 case 0x41:
8593 case 0x42:
8594 case 0x43:
8595 case 0x44:
8596 case 0x45:
8597 case 0x46:
8598 case 0x47:
8599 case 0x48:
8600 case 0x49:
8601 case 0x4A:
8602 case 0x4B:
8603 case 0x4C:
8604 case 0x4D:
8605 case 0x4E:
8606 case 0x4F:
8607 case 0x50:
8608 case 0x51:
8609 case 0x52:
8610 case 0x53:
8611 case 0x54:
8612 case 0x55:
8613 case 0x56:
8614 case 0x57:
8615 {
8616 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8617 }
8618
8619 case 0x58: // Binary data (one-byte uint8_t for n follows)
8620 {
8621 std::uint8_t len{};
8622 return get_number(input_format_t::cbor, len) &&
8623 get_binary(input_format_t::cbor, len, result);
8624 }
8625
8626 case 0x59: // Binary data (two-byte uint16_t for n follow)
8627 {
8628 std::uint16_t len{};
8629 return get_number(input_format_t::cbor, len) &&
8630 get_binary(input_format_t::cbor, len, result);
8631 }
8632
8633 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8634 {
8635 std::uint32_t len{};
8636 return get_number(input_format_t::cbor, len) &&
8637 get_binary(input_format_t::cbor, len, result);
8638 }
8639
8640 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8641 {
8642 std::uint64_t len{};
8643 return get_number(input_format_t::cbor, len) &&
8644 get_binary(input_format_t::cbor, len, result);
8645 }
8646
8647 case 0x5F: // Binary data (indefinite length)
8648 {
8649 while (get() != 0xFF)
52598650 {
5260 val = std::ldexp(mant + 1024, exp - 25);
8651 binary_t chunk;
8652 if (!get_cbor_binary(chunk))
8653 {
8654 return false;
8655 }
8656 result.insert(result.end(), chunk.begin(), chunk.end());
52618657 }
5262 else
8658 return true;
8659 }
8660
8661 default:
8662 {
8663 auto last_token = get_token_string();
8664 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary")));
8665 }
8666 }
8667 }
8668
8669 /*!
8670 @param[in] len the length of the array or std::size_t(-1) for an
8671 array of indefinite size
8672 @param[in] tag_handler how CBOR tags should be treated
8673 @return whether array creation completed
8674 */
8675 bool get_cbor_array(const std::size_t len,
8676 const cbor_tag_handler_t tag_handler)
8677 {
8678 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
8679 {
8680 return false;
8681 }
8682
8683 if (len != std::size_t(-1))
8684 {
8685 for (std::size_t i = 0; i < len; ++i)
8686 {
8687 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
52638688 {
5264 val = (mant == 0) ? std::numeric_limits<double>::infinity() : std::numeric_limits<double>::quiet_NaN();
8689 return false;
52658690 }
5266 return (half & 0x8000) != 0 ? -val : val;
5267 }
5268
5269 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
5270 {
5271 return get_number<float>();
5272 }
5273
5274 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
5275 {
5276 return get_number<double>();
5277 }
5278
5279 default: // anything else (0xFF is handled inside the other types)
5280 {
5281 std::stringstream ss;
5282 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5283 JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
5284 }
5285 }
5286 }
5287
5288 BasicJsonType parse_msgpack_internal()
8691 }
8692 }
8693 else
8694 {
8695 while (get() != 0xFF)
8696 {
8697 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
8698 {
8699 return false;
8700 }
8701 }
8702 }
8703
8704 return sax->end_array();
8705 }
8706
8707 /*!
8708 @param[in] len the length of the object or std::size_t(-1) for an
8709 object of indefinite size
8710 @param[in] tag_handler how CBOR tags should be treated
8711 @return whether object creation completed
8712 */
8713 bool get_cbor_object(const std::size_t len,
8714 const cbor_tag_handler_t tag_handler)
8715 {
8716 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
8717 {
8718 return false;
8719 }
8720
8721 string_t key;
8722 if (len != std::size_t(-1))
8723 {
8724 for (std::size_t i = 0; i < len; ++i)
8725 {
8726 get();
8727 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8728 {
8729 return false;
8730 }
8731
8732 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8733 {
8734 return false;
8735 }
8736 key.clear();
8737 }
8738 }
8739 else
8740 {
8741 while (get() != 0xFF)
8742 {
8743 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8744 {
8745 return false;
8746 }
8747
8748 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8749 {
8750 return false;
8751 }
8752 key.clear();
8753 }
8754 }
8755
8756 return sax->end_object();
8757 }
8758
8759 /////////////
8760 // MsgPack //
8761 /////////////
8762
8763 /*!
8764 @return whether a valid MessagePack value was passed to the SAX parser
8765 */
8766 bool parse_msgpack_internal()
52898767 {
52908768 switch (get())
52918769 {
52928770 // EOF
5293 case std::char_traits<char>::eof():
5294 JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
8771 case std::char_traits<char_type>::eof():
8772 return unexpect_eof(input_format_t::msgpack, "value");
52958773
52968774 // positive fixint
52978775 case 0x00:
54228900 case 0x7D:
54238901 case 0x7E:
54248902 case 0x7F:
5425 return static_cast<number_unsigned_t>(current);
8903 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
54268904
54278905 // fixmap
54288906 case 0x80:
54418919 case 0x8D:
54428920 case 0x8E:
54438921 case 0x8F:
5444 {
5445 return get_msgpack_object(current & 0x0F);
5446 }
8922 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
54478923
54488924 // fixarray
54498925 case 0x90:
54628938 case 0x9D:
54638939 case 0x9E:
54648940 case 0x9F:
5465 {
5466 return get_msgpack_array(current & 0x0F);
5467 }
8941 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
54688942
54698943 // fixstr
54708944 case 0xA0:
54998973 case 0xBD:
55008974 case 0xBE:
55018975 case 0xBF:
5502 return get_msgpack_string();
5503
5504 case 0xC0: // nil
5505 return value_t::null;
5506
5507 case 0xC2: // false
5508 return false;
5509
5510 case 0xC3: // true
5511 return true;
5512
5513 case 0xCA: // float 32
5514 return get_number<float>();
5515
5516 case 0xCB: // float 64
5517 return get_number<double>();
5518
5519 case 0xCC: // uint 8
5520 return get_number<uint8_t>();
5521
5522 case 0xCD: // uint 16
5523 return get_number<uint16_t>();
5524
5525 case 0xCE: // uint 32
5526 return get_number<uint32_t>();
5527
5528 case 0xCF: // uint 64
5529 return get_number<uint64_t>();
5530
5531 case 0xD0: // int 8
5532 return get_number<int8_t>();
5533
5534 case 0xD1: // int 16
5535 return get_number<int16_t>();
5536
5537 case 0xD2: // int 32
5538 return get_number<int32_t>();
5539
5540 case 0xD3: // int 64
5541 return get_number<int64_t>();
5542
55438976 case 0xD9: // str 8
55448977 case 0xDA: // str 16
55458978 case 0xDB: // str 32
5546 return get_msgpack_string();
8979 {
8980 string_t s;
8981 return get_msgpack_string(s) && sax->string(s);
8982 }
8983
8984 case 0xC0: // nil
8985 return sax->null();
8986
8987 case 0xC2: // false
8988 return sax->boolean(false);
8989
8990 case 0xC3: // true
8991 return sax->boolean(true);
8992
8993 case 0xC4: // bin 8
8994 case 0xC5: // bin 16
8995 case 0xC6: // bin 32
8996 case 0xC7: // ext 8
8997 case 0xC8: // ext 16
8998 case 0xC9: // ext 32
8999 case 0xD4: // fixext 1
9000 case 0xD5: // fixext 2
9001 case 0xD6: // fixext 4
9002 case 0xD7: // fixext 8
9003 case 0xD8: // fixext 16
9004 {
9005 binary_t b;
9006 return get_msgpack_binary(b) && sax->binary(b);
9007 }
9008
9009 case 0xCA: // float 32
9010 {
9011 float number{};
9012 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9013 }
9014
9015 case 0xCB: // float 64
9016 {
9017 double number{};
9018 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9019 }
9020
9021 case 0xCC: // uint 8
9022 {
9023 std::uint8_t number{};
9024 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9025 }
9026
9027 case 0xCD: // uint 16
9028 {
9029 std::uint16_t number{};
9030 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9031 }
9032
9033 case 0xCE: // uint 32
9034 {
9035 std::uint32_t number{};
9036 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9037 }
9038
9039 case 0xCF: // uint 64
9040 {
9041 std::uint64_t number{};
9042 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9043 }
9044
9045 case 0xD0: // int 8
9046 {
9047 std::int8_t number{};
9048 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9049 }
9050
9051 case 0xD1: // int 16
9052 {
9053 std::int16_t number{};
9054 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9055 }
9056
9057 case 0xD2: // int 32
9058 {
9059 std::int32_t number{};
9060 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9061 }
9062
9063 case 0xD3: // int 64
9064 {
9065 std::int64_t number{};
9066 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9067 }
55479068
55489069 case 0xDC: // array 16
55499070 {
5550 return get_msgpack_array(get_number<uint16_t>());
9071 std::uint16_t len{};
9072 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
55519073 }
55529074
55539075 case 0xDD: // array 32
55549076 {
5555 return get_msgpack_array(get_number<uint32_t>());
9077 std::uint32_t len{};
9078 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
55569079 }
55579080
55589081 case 0xDE: // map 16
55599082 {
5560 return get_msgpack_object(get_number<uint16_t>());
9083 std::uint16_t len{};
9084 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
55619085 }
55629086
55639087 case 0xDF: // map 32
55649088 {
5565 return get_msgpack_object(get_number<uint32_t>());
5566 }
5567
5568 // positive fixint
9089 std::uint32_t len{};
9090 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9091 }
9092
9093 // negative fixint
55699094 case 0xE0:
55709095 case 0xE1:
55719096 case 0xE2:
55989123 case 0xFD:
55999124 case 0xFE:
56009125 case 0xFF:
5601 return static_cast<int8_t>(current);
9126 return sax->number_integer(static_cast<std::int8_t>(current));
56029127
56039128 default: // anything else
56049129 {
5605 std::stringstream ss;
5606 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5607 JSON_THROW(parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + ss.str()));
5608 }
5609 }
5610 }
5611
5612 /*!
5613 @param[in] get_char whether a new character should be retrieved from the
5614 input (true, default) or whether the last read
5615 character should be considered instead
5616 */
5617 BasicJsonType parse_ubjson_internal(const bool get_char = true)
5618 {
5619 return get_ubjson_value(get_char ? get_ignore_noop() : current);
5620 }
5621
5622 /*!
5623 @brief get next character from the input
5624
5625 This function provides the interface to the used input adapter. It does
5626 not throw in case the input reached EOF, but returns a -'ve valued
5627 `std::char_traits<char>::eof()` in that case.
5628
5629 @return character read from the input
5630 */
5631 int get()
5632 {
5633 ++chars_read;
5634 return (current = ia->get_character());
5635 }
5636
5637 /*!
5638 @return character read from the input after ignoring all 'N' entries
5639 */
5640 int get_ignore_noop()
5641 {
5642 do
5643 {
5644 get();
5645 } while (current == 'N');
5646
5647 return current;
5648 }
5649
5650 /*
5651 @brief read a number from the input
5652
5653 @tparam NumberType the type of the number
5654
5655 @return number of type @a NumberType
5656
5657 @note This function needs to respect the system's endianess, because
5658 bytes in CBOR and MessagePack are stored in network order (big
5659 endian) and therefore need reordering on little endian systems.
5660
5661 @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
5662 */
5663 template <typename NumberType>
5664 NumberType get_number()
5665 {
5666 // step 1: read input into array with system's byte order
5667 std::array<uint8_t, sizeof(NumberType)> vec;
5668 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
5669 {
5670 get();
5671 unexpect_eof();
5672
5673 // reverse byte order prior to conversion if necessary
5674 if (is_little_endian)
5675 {
5676 vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
5677 }
5678 else
5679 {
5680 vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
5681 }
5682 }
5683
5684 // step 2: convert array into number of type T and return
5685 NumberType result;
5686 std::memcpy(&result, vec.data(), sizeof(NumberType));
5687 return result;
5688 }
5689
5690 /*!
5691 @brief create a string by reading characters from the input
5692
5693 @param[in] len number of bytes to read
5694
5695 @note We can not reserve @a len bytes for the result, because @a len
5696 may be too large. Usually, @ref unexpect_eof() detects the end of
5697 the input before we run out of string memory.
5698
5699 @return string created by reading @a len bytes
5700
5701 @throw parse_error.110 if input has less than @a len bytes
5702 */
5703 template <typename NumberType>
5704 string_t get_string(const NumberType len)
5705 {
5706 string_t result;
5707 std::generate_n(std::back_inserter(result), len, [this]() {
5708 get();
5709 unexpect_eof();
5710 return static_cast<char>(current);
5711 });
5712 return result;
5713 }
5714
5715 /*!
5716 @brief reads a CBOR string
9130 auto last_token = get_token_string();
9131 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
9132 }
9133 }
9134 }
9135
9136 /*!
9137 @brief reads a MessagePack string
57179138
57189139 This function first reads starting bytes to determine the expected
57199140 string length and then copies this number of bytes into a string.
5720 Additionally, CBOR's strings with indefinite lengths are supported.
5721
5722 @return string
5723
5724 @throw parse_error.110 if input ended
5725 @throw parse_error.113 if an unexpected byte is read
5726 */
5727 string_t get_cbor_string()
5728 {
5729 unexpect_eof();
5730
5731 switch (current)
5732 {
5733 // UTF-8 string (0x00..0x17 bytes follow)
5734 case 0x60:
5735 case 0x61:
5736 case 0x62:
5737 case 0x63:
5738 case 0x64:
5739 case 0x65:
5740 case 0x66:
5741 case 0x67:
5742 case 0x68:
5743 case 0x69:
5744 case 0x6A:
5745 case 0x6B:
5746 case 0x6C:
5747 case 0x6D:
5748 case 0x6E:
5749 case 0x6F:
5750 case 0x70:
5751 case 0x71:
5752 case 0x72:
5753 case 0x73:
5754 case 0x74:
5755 case 0x75:
5756 case 0x76:
5757 case 0x77:
5758 {
5759 return get_string(current & 0x1F);
5760 }
5761
5762 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
5763 {
5764 return get_string(get_number<uint8_t>());
5765 }
5766
5767 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
5768 {
5769 return get_string(get_number<uint16_t>());
5770 }
5771
5772 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
5773 {
5774 return get_string(get_number<uint32_t>());
5775 }
5776
5777 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
5778 {
5779 return get_string(get_number<uint64_t>());
5780 }
5781
5782 case 0x7F: // UTF-8 string (indefinite length)
5783 {
5784 string_t result;
5785 while (get() != 0xFF)
5786 {
5787 result.append(get_cbor_string());
5788 }
5789 return result;
5790 }
5791
5792 default:
5793 {
5794 std::stringstream ss;
5795 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5796 JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
5797 }
5798 }
5799 }
5800
5801 template <typename NumberType>
5802 BasicJsonType get_cbor_array(const NumberType len)
5803 {
5804 BasicJsonType result = value_t::array;
5805 std::generate_n(std::back_inserter(*result.m_value.array), len, [this]() { return parse_cbor_internal(); });
5806 return result;
5807 }
5808
5809 template <typename NumberType>
5810 BasicJsonType get_cbor_object(const NumberType len)
5811 {
5812 BasicJsonType result = value_t::object;
5813 std::generate_n(std::inserter(*result.m_value.object, result.m_value.object->end()), len, [this]() {
5814 get();
5815 auto key = get_cbor_string();
5816 auto val = parse_cbor_internal();
5817 return std::make_pair(std::move(key), std::move(val));
5818 });
5819 return result;
5820 }
5821
5822 /*!
5823 @brief reads a MessagePack string
5824
5825 This function first reads starting bytes to determine the expected
5826 string length and then copies this number of bytes into a string.
5827
5828 @return string
5829
5830 @throw parse_error.110 if input ended
5831 @throw parse_error.113 if an unexpected byte is read
5832 */
5833 string_t get_msgpack_string()
5834 {
5835 unexpect_eof();
9141
9142 @param[out] result created string
9143
9144 @return whether string creation completed
9145 */
9146 bool get_msgpack_string(string_t& result)
9147 {
9148 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9149 {
9150 return false;
9151 }
58369152
58379153 switch (current)
58389154 {
58709186 case 0xBE:
58719187 case 0xBF:
58729188 {
5873 return get_string(current & 0x1F);
9189 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
58749190 }
58759191
58769192 case 0xD9: // str 8
58779193 {
5878 return get_string(get_number<uint8_t>());
9194 std::uint8_t len{};
9195 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
58799196 }
58809197
58819198 case 0xDA: // str 16
58829199 {
5883 return get_string(get_number<uint16_t>());
9200 std::uint16_t len{};
9201 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
58849202 }
58859203
58869204 case 0xDB: // str 32
58879205 {
5888 return get_string(get_number<uint32_t>());
9206 std::uint32_t len{};
9207 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
58899208 }
58909209
58919210 default:
58929211 {
5893 std::stringstream ss;
5894 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5895 JSON_THROW(parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + ss.str()));
5896 }
5897 }
5898 }
5899
5900 template <typename NumberType>
5901 BasicJsonType get_msgpack_array(const NumberType len)
5902 {
5903 BasicJsonType result = value_t::array;
5904 std::generate_n(std::back_inserter(*result.m_value.array), len, [this]() { return parse_msgpack_internal(); });
5905 return result;
5906 }
5907
5908 template <typename NumberType>
5909 BasicJsonType get_msgpack_object(const NumberType len)
5910 {
5911 BasicJsonType result = value_t::object;
5912 std::generate_n(std::inserter(*result.m_value.object, result.m_value.object->end()), len, [this]() {
9212 auto last_token = get_token_string();
9213 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
9214 }
9215 }
9216 }
9217
9218 /*!
9219 @brief reads a MessagePack byte array
9220
9221 This function first reads starting bytes to determine the expected
9222 byte array length and then copies this number of bytes into a byte array.
9223
9224 @param[out] result created byte array
9225
9226 @return whether byte array creation completed
9227 */
9228 bool get_msgpack_binary(binary_t& result)
9229 {
9230 // helper function to set the subtype
9231 auto assign_and_return_true = [&result](std::int8_t subtype)
9232 {
9233 result.set_subtype(static_cast<std::uint8_t>(subtype));
9234 return true;
9235 };
9236
9237 switch (current)
9238 {
9239 case 0xC4: // bin 8
9240 {
9241 std::uint8_t len{};
9242 return get_number(input_format_t::msgpack, len) &&
9243 get_binary(input_format_t::msgpack, len, result);
9244 }
9245
9246 case 0xC5: // bin 16
9247 {
9248 std::uint16_t len{};
9249 return get_number(input_format_t::msgpack, len) &&
9250 get_binary(input_format_t::msgpack, len, result);
9251 }
9252
9253 case 0xC6: // bin 32
9254 {
9255 std::uint32_t len{};
9256 return get_number(input_format_t::msgpack, len) &&
9257 get_binary(input_format_t::msgpack, len, result);
9258 }
9259
9260 case 0xC7: // ext 8
9261 {
9262 std::uint8_t len{};
9263 std::int8_t subtype{};
9264 return get_number(input_format_t::msgpack, len) &&
9265 get_number(input_format_t::msgpack, subtype) &&
9266 get_binary(input_format_t::msgpack, len, result) &&
9267 assign_and_return_true(subtype);
9268 }
9269
9270 case 0xC8: // ext 16
9271 {
9272 std::uint16_t len{};
9273 std::int8_t subtype{};
9274 return get_number(input_format_t::msgpack, len) &&
9275 get_number(input_format_t::msgpack, subtype) &&
9276 get_binary(input_format_t::msgpack, len, result) &&
9277 assign_and_return_true(subtype);
9278 }
9279
9280 case 0xC9: // ext 32
9281 {
9282 std::uint32_t len{};
9283 std::int8_t subtype{};
9284 return get_number(input_format_t::msgpack, len) &&
9285 get_number(input_format_t::msgpack, subtype) &&
9286 get_binary(input_format_t::msgpack, len, result) &&
9287 assign_and_return_true(subtype);
9288 }
9289
9290 case 0xD4: // fixext 1
9291 {
9292 std::int8_t subtype{};
9293 return get_number(input_format_t::msgpack, subtype) &&
9294 get_binary(input_format_t::msgpack, 1, result) &&
9295 assign_and_return_true(subtype);
9296 }
9297
9298 case 0xD5: // fixext 2
9299 {
9300 std::int8_t subtype{};
9301 return get_number(input_format_t::msgpack, subtype) &&
9302 get_binary(input_format_t::msgpack, 2, result) &&
9303 assign_and_return_true(subtype);
9304 }
9305
9306 case 0xD6: // fixext 4
9307 {
9308 std::int8_t subtype{};
9309 return get_number(input_format_t::msgpack, subtype) &&
9310 get_binary(input_format_t::msgpack, 4, result) &&
9311 assign_and_return_true(subtype);
9312 }
9313
9314 case 0xD7: // fixext 8
9315 {
9316 std::int8_t subtype{};
9317 return get_number(input_format_t::msgpack, subtype) &&
9318 get_binary(input_format_t::msgpack, 8, result) &&
9319 assign_and_return_true(subtype);
9320 }
9321
9322 case 0xD8: // fixext 16
9323 {
9324 std::int8_t subtype{};
9325 return get_number(input_format_t::msgpack, subtype) &&
9326 get_binary(input_format_t::msgpack, 16, result) &&
9327 assign_and_return_true(subtype);
9328 }
9329
9330 default: // LCOV_EXCL_LINE
9331 return false; // LCOV_EXCL_LINE
9332 }
9333 }
9334
9335 /*!
9336 @param[in] len the length of the array
9337 @return whether array creation completed
9338 */
9339 bool get_msgpack_array(const std::size_t len)
9340 {
9341 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9342 {
9343 return false;
9344 }
9345
9346 for (std::size_t i = 0; i < len; ++i)
9347 {
9348 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9349 {
9350 return false;
9351 }
9352 }
9353
9354 return sax->end_array();
9355 }
9356
9357 /*!
9358 @param[in] len the length of the object
9359 @return whether object creation completed
9360 */
9361 bool get_msgpack_object(const std::size_t len)
9362 {
9363 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9364 {
9365 return false;
9366 }
9367
9368 string_t key;
9369 for (std::size_t i = 0; i < len; ++i)
9370 {
59139371 get();
5914 auto key = get_msgpack_string();
5915 auto val = parse_msgpack_internal();
5916 return std::make_pair(std::move(key), std::move(val));
5917 });
5918 return result;
9372 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9373 {
9374 return false;
9375 }
9376
9377 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9378 {
9379 return false;
9380 }
9381 key.clear();
9382 }
9383
9384 return sax->end_object();
9385 }
9386
9387 ////////////
9388 // UBJSON //
9389 ////////////
9390
9391 /*!
9392 @param[in] get_char whether a new character should be retrieved from the
9393 input (true, default) or whether the last read
9394 character should be considered instead
9395
9396 @return whether a valid UBJSON value was passed to the SAX parser
9397 */
9398 bool parse_ubjson_internal(const bool get_char = true)
9399 {
9400 return get_ubjson_value(get_char ? get_ignore_noop() : current);
59199401 }
59209402
59219403 /*!
59259407 indicating a string, or in case of an object key where the 'S' byte can be
59269408 left out.
59279409
9410 @param[out] result created string
59289411 @param[in] get_char whether a new character should be retrieved from the
59299412 input (true, default) or whether the last read
59309413 character should be considered instead
59319414
5932 @return string
5933
5934 @throw parse_error.110 if input ended
5935 @throw parse_error.113 if an unexpected byte is read
5936 */
5937 string_t get_ubjson_string(const bool get_char = true)
9415 @return whether string creation completed
9416 */
9417 bool get_ubjson_string(string_t& result, const bool get_char = true)
59389418 {
59399419 if (get_char)
59409420 {
5941 get(); // TODO: may we ignore N here?
5942 }
5943
5944 unexpect_eof();
9421 get(); // TODO(niels): may we ignore N here?
9422 }
9423
9424 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9425 {
9426 return false;
9427 }
59459428
59469429 switch (current)
59479430 {
59489431 case 'U':
5949 return get_string(get_number<uint8_t>());
9432 {
9433 std::uint8_t len{};
9434 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9435 }
9436
59509437 case 'i':
5951 return get_string(get_number<int8_t>());
9438 {
9439 std::int8_t len{};
9440 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9441 }
9442
59529443 case 'I':
5953 return get_string(get_number<int16_t>());
9444 {
9445 std::int16_t len{};
9446 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9447 }
9448
59549449 case 'l':
5955 return get_string(get_number<int32_t>());
9450 {
9451 std::int32_t len{};
9452 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9453 }
9454
59569455 case 'L':
5957 return get_string(get_number<int64_t>());
9456 {
9457 std::int64_t len{};
9458 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9459 }
9460
59589461 default:
5959 std::stringstream ss;
5960 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5961 JSON_THROW(parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + ss.str()));
9462 auto last_token = get_token_string();
9463 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
9464 }
9465 }
9466
9467 /*!
9468 @param[out] result determined size
9469 @return whether size determination completed
9470 */
9471 bool get_ubjson_size_value(std::size_t& result)
9472 {
9473 switch (get_ignore_noop())
9474 {
9475 case 'U':
9476 {
9477 std::uint8_t number{};
9478 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9479 {
9480 return false;
9481 }
9482 result = static_cast<std::size_t>(number);
9483 return true;
9484 }
9485
9486 case 'i':
9487 {
9488 std::int8_t number{};
9489 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9490 {
9491 return false;
9492 }
9493 result = static_cast<std::size_t>(number);
9494 return true;
9495 }
9496
9497 case 'I':
9498 {
9499 std::int16_t number{};
9500 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9501 {
9502 return false;
9503 }
9504 result = static_cast<std::size_t>(number);
9505 return true;
9506 }
9507
9508 case 'l':
9509 {
9510 std::int32_t number{};
9511 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9512 {
9513 return false;
9514 }
9515 result = static_cast<std::size_t>(number);
9516 return true;
9517 }
9518
9519 case 'L':
9520 {
9521 std::int64_t number{};
9522 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9523 {
9524 return false;
9525 }
9526 result = static_cast<std::size_t>(number);
9527 return true;
9528 }
9529
9530 default:
9531 {
9532 auto last_token = get_token_string();
9533 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
9534 }
59629535 }
59639536 }
59649537
59689541 In the optimized UBJSON format, a type and a size can be provided to allow
59699542 for a more compact representation.
59709543
5971 @return pair of the size and the type
5972 */
5973 std::pair<std::size_t, int> get_ubjson_size_type()
5974 {
5975 std::size_t sz = string_t::npos;
5976 int tc = 0;
9544 @param[out] result pair of the size and the type
9545
9546 @return whether pair creation completed
9547 */
9548 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
9549 {
9550 result.first = string_t::npos; // size
9551 result.second = 0; // type
59779552
59789553 get_ignore_noop();
59799554
59809555 if (current == '$')
59819556 {
5982 tc = get(); // must not ignore 'N', because 'N' maybe the type
5983 unexpect_eof();
9557 result.second = get(); // must not ignore 'N', because 'N' maybe the type
9558 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
9559 {
9560 return false;
9561 }
59849562
59859563 get_ignore_noop();
5986 if (current != '#')
5987 {
5988 std::stringstream ss;
5989 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
5990 JSON_THROW(parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + ss.str()));
5991 }
5992 sz = parse_ubjson_internal();
5993 }
5994 else if (current == '#')
5995 {
5996 sz = parse_ubjson_internal();
5997 }
5998
5999 return std::make_pair(sz, tc);
6000 }
6001
6002 BasicJsonType get_ubjson_value(const int prefix)
9564 if (JSON_HEDLEY_UNLIKELY(current != '#'))
9565 {
9566 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9567 {
9568 return false;
9569 }
9570 auto last_token = get_token_string();
9571 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
9572 }
9573
9574 return get_ubjson_size_value(result.first);
9575 }
9576
9577 if (current == '#')
9578 {
9579 return get_ubjson_size_value(result.first);
9580 }
9581
9582 return true;
9583 }
9584
9585 /*!
9586 @param prefix the previously read or set type prefix
9587 @return whether value creation completed
9588 */
9589 bool get_ubjson_value(const char_int_type prefix)
60039590 {
60049591 switch (prefix)
60059592 {
6006 case std::char_traits<char>::eof(): // EOF
6007 JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
6008
6009 case 'T': // true
6010 return true;
6011 case 'F': // false
9593 case std::char_traits<char_type>::eof(): // EOF
9594 return unexpect_eof(input_format_t::ubjson, "value");
9595
9596 case 'T': // true
9597 return sax->boolean(true);
9598 case 'F': // false
9599 return sax->boolean(false);
9600
9601 case 'Z': // null
9602 return sax->null();
9603
9604 case 'U':
9605 {
9606 std::uint8_t number{};
9607 return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
9608 }
9609
9610 case 'i':
9611 {
9612 std::int8_t number{};
9613 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9614 }
9615
9616 case 'I':
9617 {
9618 std::int16_t number{};
9619 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9620 }
9621
9622 case 'l':
9623 {
9624 std::int32_t number{};
9625 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9626 }
9627
9628 case 'L':
9629 {
9630 std::int64_t number{};
9631 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9632 }
9633
9634 case 'd':
9635 {
9636 float number{};
9637 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9638 }
9639
9640 case 'D':
9641 {
9642 double number{};
9643 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9644 }
9645
9646 case 'H':
9647 {
9648 return get_ubjson_high_precision_number();
9649 }
9650
9651 case 'C': // char
9652 {
9653 get();
9654 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
9655 {
9656 return false;
9657 }
9658 if (JSON_HEDLEY_UNLIKELY(current > 127))
9659 {
9660 auto last_token = get_token_string();
9661 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
9662 }
9663 string_t s(1, static_cast<typename string_t::value_type>(current));
9664 return sax->string(s);
9665 }
9666
9667 case 'S': // string
9668 {
9669 string_t s;
9670 return get_ubjson_string(s) && sax->string(s);
9671 }
9672
9673 case '[': // array
9674 return get_ubjson_array();
9675
9676 case '{': // object
9677 return get_ubjson_object();
9678
9679 default: // anything else
9680 {
9681 auto last_token = get_token_string();
9682 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
9683 }
9684 }
9685 }
9686
9687 /*!
9688 @return whether array creation completed
9689 */
9690 bool get_ubjson_array()
9691 {
9692 std::pair<std::size_t, char_int_type> size_and_type;
9693 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9694 {
9695 return false;
9696 }
9697
9698 if (size_and_type.first != string_t::npos)
9699 {
9700 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
9701 {
60129702 return false;
6013
6014 case 'Z': // null
6015 return nullptr;
6016
6017 case 'U':
6018 return get_number<uint8_t>();
6019 case 'i':
6020 return get_number<int8_t>();
6021 case 'I':
6022 return get_number<int16_t>();
6023 case 'l':
6024 return get_number<int32_t>();
6025 case 'L':
6026 return get_number<int64_t>();
6027 case 'd':
6028 return get_number<float>();
6029 case 'D':
6030 return get_number<double>();
6031
6032 case 'C': // char
6033 {
6034 get();
6035 unexpect_eof();
6036 if (JSON_UNLIKELY(current > 127))
6037 {
6038 std::stringstream ss;
6039 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
6040 JSON_THROW(parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
6041 }
6042 return string_t(1, static_cast<char>(current));
6043 }
6044
6045 case 'S': // string
6046 return get_ubjson_string();
6047
6048 case '[': // array
6049 return get_ubjson_array();
6050
6051 case '{': // object
6052 return get_ubjson_object();
6053
6054 default: // anything else
6055 std::stringstream ss;
6056 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
6057 JSON_THROW(parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + ss.str()));
6058 }
6059 }
6060
6061 BasicJsonType get_ubjson_array()
6062 {
6063 BasicJsonType result = value_t::array;
6064 const auto size_and_type = get_ubjson_size_type();
6065
6066 if (size_and_type.first != string_t::npos)
6067 {
6068 if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
6069 {
6070 JSON_THROW(out_of_range::create(408, "excessive array size: " + cpt::to_string(size_and_type.first)));
60719703 }
60729704
60739705 if (size_and_type.second != 0)
60749706 {
60759707 if (size_and_type.second != 'N')
60769708 {
6077 std::generate_n(std::back_inserter(*result.m_value.array), size_and_type.first,
6078 [this, size_and_type]() { return get_ubjson_value(size_and_type.second); });
9709 for (std::size_t i = 0; i < size_and_type.first; ++i)
9710 {
9711 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9712 {
9713 return false;
9714 }
9715 }
60799716 }
60809717 }
60819718 else
60829719 {
6083 std::generate_n(std::back_inserter(*result.m_value.array), size_and_type.first, [this]() { return parse_ubjson_internal(); });
9720 for (std::size_t i = 0; i < size_and_type.first; ++i)
9721 {
9722 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9723 {
9724 return false;
9725 }
9726 }
60849727 }
60859728 }
60869729 else
60879730 {
9731 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
9732 {
9733 return false;
9734 }
9735
60889736 while (current != ']')
60899737 {
6090 result.push_back(parse_ubjson_internal(false));
9738 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
9739 {
9740 return false;
9741 }
60919742 get_ignore_noop();
60929743 }
60939744 }
60949745
6095 return result;
6096 }
6097
6098 BasicJsonType get_ubjson_object()
6099 {
6100 BasicJsonType result = value_t::object;
6101 const auto size_and_type = get_ubjson_size_type();
6102
9746 return sax->end_array();
9747 }
9748
9749 /*!
9750 @return whether object creation completed
9751 */
9752 bool get_ubjson_object()
9753 {
9754 std::pair<std::size_t, char_int_type> size_and_type;
9755 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9756 {
9757 return false;
9758 }
9759
9760 string_t key;
61039761 if (size_and_type.first != string_t::npos)
61049762 {
6105 if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
6106 {
6107 JSON_THROW(out_of_range::create(408, "excessive object size: " + cpt::to_string(size_and_type.first)));
9763 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
9764 {
9765 return false;
61089766 }
61099767
61109768 if (size_and_type.second != 0)
61119769 {
6112 std::generate_n(std::inserter(*result.m_value.object, result.m_value.object->end()), size_and_type.first, [this, size_and_type]() {
6113 auto key = get_ubjson_string();
6114 auto val = get_ubjson_value(size_and_type.second);
6115 return std::make_pair(std::move(key), std::move(val));
6116 });
9770 for (std::size_t i = 0; i < size_and_type.first; ++i)
9771 {
9772 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9773 {
9774 return false;
9775 }
9776 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9777 {
9778 return false;
9779 }
9780 key.clear();
9781 }
61179782 }
61189783 else
61199784 {
6120 std::generate_n(std::inserter(*result.m_value.object, result.m_value.object->end()), size_and_type.first, [this]() {
6121 auto key = get_ubjson_string();
6122 auto val = parse_ubjson_internal();
6123 return std::make_pair(std::move(key), std::move(val));
6124 });
9785 for (std::size_t i = 0; i < size_and_type.first; ++i)
9786 {
9787 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9788 {
9789 return false;
9790 }
9791 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9792 {
9793 return false;
9794 }
9795 key.clear();
9796 }
61259797 }
61269798 }
61279799 else
61289800 {
9801 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
9802 {
9803 return false;
9804 }
9805
61299806 while (current != '}')
61309807 {
6131 auto key = get_ubjson_string(false);
6132 result[std::move(key)] = parse_ubjson_internal();
9808 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
9809 {
9810 return false;
9811 }
9812 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9813 {
9814 return false;
9815 }
61339816 get_ignore_noop();
6134 }
6135 }
6136
6137 return result;
6138 }
6139
6140 /*!
6141 @brief throw if end of input is not reached
6142 @throw parse_error.110 if input not ended
6143 */
6144 void expect_eof() const
6145 {
6146 if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6147 {
6148 JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
6149 }
6150 }
6151
6152 /*!
6153 @briefthrow if end of input is reached
6154 @throw parse_error.110 if input ended
6155 */
6156 void unexpect_eof() const
6157 {
6158 if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
6159 {
6160 JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
6161 }
6162 }
6163
6164 private:
9817 key.clear();
9818 }
9819 }
9820
9821 return sax->end_object();
9822 }
9823
9824 // Note, no reader for UBJSON binary types is implemented because they do
9825 // not exist
9826
9827 bool get_ubjson_high_precision_number()
9828 {
9829 // get size of following number string
9830 std::size_t size{};
9831 auto res = get_ubjson_size_value(size);
9832 if (JSON_HEDLEY_UNLIKELY(!res))
9833 {
9834 return res;
9835 }
9836
9837 // get number string
9838 std::vector<char> number_vector;
9839 for (std::size_t i = 0; i < size; ++i)
9840 {
9841 get();
9842 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
9843 {
9844 return false;
9845 }
9846 number_vector.push_back(static_cast<char>(current));
9847 }
9848
9849 // parse number string
9850 auto number_ia = detail::input_adapter(std::forward<decltype(number_vector)>(number_vector));
9851 auto number_lexer = detail::lexer<BasicJsonType, decltype(number_ia)>(std::move(number_ia), false);
9852 const auto result_number = number_lexer.scan();
9853 const auto number_string = number_lexer.get_token_string();
9854 const auto result_remainder = number_lexer.scan();
9855
9856 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
9857
9858 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
9859 {
9860 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
9861 }
9862
9863 switch (result_number)
9864 {
9865 case token_type::value_integer:
9866 return sax->number_integer(number_lexer.get_number_integer());
9867 case token_type::value_unsigned:
9868 return sax->number_unsigned(number_lexer.get_number_unsigned());
9869 case token_type::value_float:
9870 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
9871 default:
9872 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
9873 }
9874 }
9875
9876 ///////////////////////
9877 // Utility functions //
9878 ///////////////////////
9879
9880 /*!
9881 @brief get next character from the input
9882
9883 This function provides the interface to the used input adapter. It does
9884 not throw in case the input reached EOF, but returns a -'ve valued
9885 `std::char_traits<char_type>::eof()` in that case.
9886
9887 @return character read from the input
9888 */
9889 char_int_type get()
9890 {
9891 ++chars_read;
9892 return current = ia.get_character();
9893 }
9894
9895 /*!
9896 @return character read from the input after ignoring all 'N' entries
9897 */
9898 char_int_type get_ignore_noop()
9899 {
9900 do
9901 {
9902 get();
9903 }
9904 while (current == 'N');
9905
9906 return current;
9907 }
9908
9909 /*
9910 @brief read a number from the input
9911
9912 @tparam NumberType the type of the number
9913 @param[in] format the current format (for diagnostics)
9914 @param[out] result number of type @a NumberType
9915
9916 @return whether conversion completed
9917
9918 @note This function needs to respect the system's endianess, because
9919 bytes in CBOR, MessagePack, and UBJSON are stored in network order
9920 (big endian) and therefore need reordering on little endian systems.
9921 */
9922 template<typename NumberType, bool InputIsLittleEndian = false>
9923 bool get_number(const input_format_t format, NumberType& result)
9924 {
9925 // step 1: read input into array with system's byte order
9926 std::array<std::uint8_t, sizeof(NumberType)> vec;
9927 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
9928 {
9929 get();
9930 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
9931 {
9932 return false;
9933 }
9934
9935 // reverse byte order prior to conversion if necessary
9936 if (is_little_endian != InputIsLittleEndian)
9937 {
9938 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
9939 }
9940 else
9941 {
9942 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
9943 }
9944 }
9945
9946 // step 2: convert array into number of type T and return
9947 std::memcpy(&result, vec.data(), sizeof(NumberType));
9948 return true;
9949 }
9950
9951 /*!
9952 @brief create a string by reading characters from the input
9953
9954 @tparam NumberType the type of the number
9955 @param[in] format the current format (for diagnostics)
9956 @param[in] len number of characters to read
9957 @param[out] result string created by reading @a len bytes
9958
9959 @return whether string creation completed
9960
9961 @note We can not reserve @a len bytes for the result, because @a len
9962 may be too large. Usually, @ref unexpect_eof() detects the end of
9963 the input before we run out of string memory.
9964 */
9965 template<typename NumberType>
9966 bool get_string(const input_format_t format,
9967 const NumberType len,
9968 string_t& result)
9969 {
9970 bool success = true;
9971 for (NumberType i = 0; i < len; i++)
9972 {
9973 get();
9974 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
9975 {
9976 success = false;
9977 break;
9978 }
9979 result.push_back(static_cast<typename string_t::value_type>(current));
9980 };
9981 return success;
9982 }
9983
9984 /*!
9985 @brief create a byte array by reading bytes from the input
9986
9987 @tparam NumberType the type of the number
9988 @param[in] format the current format (for diagnostics)
9989 @param[in] len number of bytes to read
9990 @param[out] result byte array created by reading @a len bytes
9991
9992 @return whether byte array creation completed
9993
9994 @note We can not reserve @a len bytes for the result, because @a len
9995 may be too large. Usually, @ref unexpect_eof() detects the end of
9996 the input before we run out of memory.
9997 */
9998 template<typename NumberType>
9999 bool get_binary(const input_format_t format,
10000 const NumberType len,
10001 binary_t& result)
10002 {
10003 bool success = true;
10004 for (NumberType i = 0; i < len; i++)
10005 {
10006 get();
10007 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10008 {
10009 success = false;
10010 break;
10011 }
10012 result.push_back(static_cast<std::uint8_t>(current));
10013 }
10014 return success;
10015 }
10016
10017 /*!
10018 @param[in] format the current format (for diagnostics)
10019 @param[in] context further context information (for diagnostics)
10020 @return whether the last read character is not EOF
10021 */
10022 JSON_HEDLEY_NON_NULL(3)
10023 bool unexpect_eof(const input_format_t format, const char* context) const
10024 {
10025 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10026 {
10027 return sax->parse_error(chars_read, "<end of file>",
10028 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
10029 }
10030 return true;
10031 }
10032
10033 /*!
10034 @return a string representation of the last read byte
10035 */
10036 std::string get_token_string() const
10037 {
10038 std::array<char, 3> cr{{}};
10039 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
10040 return std::string{cr.data()};
10041 }
10042
10043 /*!
10044 @param[in] format the current format
10045 @param[in] detail a detailed error message
10046 @param[in] context further context information
10047 @return a message string to use in the parse_error exceptions
10048 */
10049 std::string exception_message(const input_format_t format,
10050 const std::string& detail,
10051 const std::string& context) const
10052 {
10053 std::string error_msg = "syntax error while parsing ";
10054
10055 switch (format)
10056 {
10057 case input_format_t::cbor:
10058 error_msg += "CBOR";
10059 break;
10060
10061 case input_format_t::msgpack:
10062 error_msg += "MessagePack";
10063 break;
10064
10065 case input_format_t::ubjson:
10066 error_msg += "UBJSON";
10067 break;
10068
10069 case input_format_t::bson:
10070 error_msg += "BSON";
10071 break;
10072
10073 default: // LCOV_EXCL_LINE
10074 JSON_ASSERT(false); // LCOV_EXCL_LINE
10075 }
10076
10077 return error_msg + " " + context + ": " + detail;
10078 }
10079
10080 private:
616510081 /// input adapter
6166 input_adapter_t ia = nullptr;
10082 InputAdapterType ia;
616710083
616810084 /// the current character
6169 int current = std::char_traits<char>::eof();
10085 char_int_type current = std::char_traits<char_type>::eof();
617010086
617110087 /// the number of characters read
617210088 std::size_t chars_read = 0;
617310089
617410090 /// whether we can assume little endianess
617510091 const bool is_little_endian = little_endianess();
10092
10093 /// the SAX parser
10094 json_sax_t* sax = nullptr;
617610095 };
6177 }
6178 }
10096 } // namespace detail
10097 } // namespace nlohmann
10098
10099 // #include <nlohmann/detail/input/input_adapters.hpp>
10100
10101 // #include <nlohmann/detail/input/lexer.hpp>
10102
10103 // #include <nlohmann/detail/input/parser.hpp>
10104
10105
10106 #include <cmath> // isfinite
10107 #include <cstdint> // uint8_t
10108 #include <functional> // function
10109 #include <string> // string
10110 #include <utility> // move
10111 #include <vector> // vector
10112
10113 // #include <nlohmann/detail/exceptions.hpp>
10114
10115 // #include <nlohmann/detail/input/input_adapters.hpp>
10116
10117 // #include <nlohmann/detail/input/json_sax.hpp>
10118
10119 // #include <nlohmann/detail/input/lexer.hpp>
10120
10121 // #include <nlohmann/detail/macro_scope.hpp>
10122
10123 // #include <nlohmann/detail/meta/is_sax.hpp>
10124
10125 // #include <nlohmann/detail/value_t.hpp>
10126
10127
10128 namespace nlohmann
10129 {
10130 namespace detail
10131 {
10132 ////////////
10133 // parser //
10134 ////////////
10135
10136 enum class parse_event_t : uint8_t
10137 {
10138 /// the parser read `{` and started to process a JSON object
10139 object_start,
10140 /// the parser read `}` and finished processing a JSON object
10141 object_end,
10142 /// the parser read `[` and started to process a JSON array
10143 array_start,
10144 /// the parser read `]` and finished processing a JSON array
10145 array_end,
10146 /// the parser read a key of a value in an object
10147 key,
10148 /// the parser finished reading a JSON value
10149 value
10150 };
10151
10152 template<typename BasicJsonType>
10153 using parser_callback_t =
10154 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
10155
10156 /*!
10157 @brief syntax analysis
10158
10159 This class implements a recursive descent parser.
10160 */
10161 template<typename BasicJsonType, typename InputAdapterType>
10162 class parser
10163 {
10164 using number_integer_t = typename BasicJsonType::number_integer_t;
10165 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10166 using number_float_t = typename BasicJsonType::number_float_t;
10167 using string_t = typename BasicJsonType::string_t;
10168 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10169 using token_type = typename lexer_t::token_type;
10170
10171 public:
10172 /// a parser reading from an input adapter
10173 explicit parser(InputAdapterType&& adapter,
10174 const parser_callback_t<BasicJsonType> cb = nullptr,
10175 const bool allow_exceptions_ = true,
10176 const bool skip_comments = false)
10177 : callback(cb)
10178 , m_lexer(std::move(adapter), skip_comments)
10179 , allow_exceptions(allow_exceptions_)
10180 {
10181 // read first token
10182 get_token();
10183 }
10184
10185 /*!
10186 @brief public parser interface
10187
10188 @param[in] strict whether to expect the last token to be EOF
10189 @param[in,out] result parsed JSON value
10190
10191 @throw parse_error.101 in case of an unexpected token
10192 @throw parse_error.102 if to_unicode fails or surrogate error
10193 @throw parse_error.103 if to_unicode fails
10194 */
10195 void parse(const bool strict, BasicJsonType& result)
10196 {
10197 if (callback)
10198 {
10199 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10200 sax_parse_internal(&sdp);
10201 result.assert_invariant();
10202
10203 // in strict mode, input must be completely read
10204 if (strict && (get_token() != token_type::end_of_input))
10205 {
10206 sdp.parse_error(m_lexer.get_position(),
10207 m_lexer.get_token_string(),
10208 parse_error::create(101, m_lexer.get_position(),
10209 exception_message(token_type::end_of_input, "value")));
10210 }
10211
10212 // in case of an error, return discarded value
10213 if (sdp.is_errored())
10214 {
10215 result = value_t::discarded;
10216 return;
10217 }
10218
10219 // set top-level value to null if it was discarded by the callback
10220 // function
10221 if (result.is_discarded())
10222 {
10223 result = nullptr;
10224 }
10225 }
10226 else
10227 {
10228 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10229 sax_parse_internal(&sdp);
10230 result.assert_invariant();
10231
10232 // in strict mode, input must be completely read
10233 if (strict && (get_token() != token_type::end_of_input))
10234 {
10235 sdp.parse_error(m_lexer.get_position(),
10236 m_lexer.get_token_string(),
10237 parse_error::create(101, m_lexer.get_position(),
10238 exception_message(token_type::end_of_input, "value")));
10239 }
10240
10241 // in case of an error, return discarded value
10242 if (sdp.is_errored())
10243 {
10244 result = value_t::discarded;
10245 return;
10246 }
10247 }
10248 }
10249
10250 /*!
10251 @brief public accept interface
10252
10253 @param[in] strict whether to expect the last token to be EOF
10254 @return whether the input is a proper JSON text
10255 */
10256 bool accept(const bool strict = true)
10257 {
10258 json_sax_acceptor<BasicJsonType> sax_acceptor;
10259 return sax_parse(&sax_acceptor, strict);
10260 }
10261
10262 template<typename SAX>
10263 JSON_HEDLEY_NON_NULL(2)
10264 bool sax_parse(SAX* sax, const bool strict = true)
10265 {
10266 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10267 const bool result = sax_parse_internal(sax);
10268
10269 // strict mode: next byte must be EOF
10270 if (result && strict && (get_token() != token_type::end_of_input))
10271 {
10272 return sax->parse_error(m_lexer.get_position(),
10273 m_lexer.get_token_string(),
10274 parse_error::create(101, m_lexer.get_position(),
10275 exception_message(token_type::end_of_input, "value")));
10276 }
10277
10278 return result;
10279 }
10280
10281 private:
10282 template<typename SAX>
10283 JSON_HEDLEY_NON_NULL(2)
10284 bool sax_parse_internal(SAX* sax)
10285 {
10286 // stack to remember the hierarchy of structured values we are parsing
10287 // true = array; false = object
10288 std::vector<bool> states;
10289 // value to avoid a goto (see comment where set to true)
10290 bool skip_to_state_evaluation = false;
10291
10292 while (true)
10293 {
10294 if (!skip_to_state_evaluation)
10295 {
10296 // invariant: get_token() was called before each iteration
10297 switch (last_token)
10298 {
10299 case token_type::begin_object:
10300 {
10301 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
10302 {
10303 return false;
10304 }
10305
10306 // closing } -> we are done
10307 if (get_token() == token_type::end_object)
10308 {
10309 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10310 {
10311 return false;
10312 }
10313 break;
10314 }
10315
10316 // parse key
10317 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10318 {
10319 return sax->parse_error(m_lexer.get_position(),
10320 m_lexer.get_token_string(),
10321 parse_error::create(101, m_lexer.get_position(),
10322 exception_message(token_type::value_string, "object key")));
10323 }
10324 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10325 {
10326 return false;
10327 }
10328
10329 // parse separator (:)
10330 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10331 {
10332 return sax->parse_error(m_lexer.get_position(),
10333 m_lexer.get_token_string(),
10334 parse_error::create(101, m_lexer.get_position(),
10335 exception_message(token_type::name_separator, "object separator")));
10336 }
10337
10338 // remember we are now inside an object
10339 states.push_back(false);
10340
10341 // parse values
10342 get_token();
10343 continue;
10344 }
10345
10346 case token_type::begin_array:
10347 {
10348 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
10349 {
10350 return false;
10351 }
10352
10353 // closing ] -> we are done
10354 if (get_token() == token_type::end_array)
10355 {
10356 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10357 {
10358 return false;
10359 }
10360 break;
10361 }
10362
10363 // remember we are now inside an array
10364 states.push_back(true);
10365
10366 // parse values (no need to call get_token)
10367 continue;
10368 }
10369
10370 case token_type::value_float:
10371 {
10372 const auto res = m_lexer.get_number_float();
10373
10374 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10375 {
10376 return sax->parse_error(m_lexer.get_position(),
10377 m_lexer.get_token_string(),
10378 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
10379 }
10380
10381 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10382 {
10383 return false;
10384 }
10385
10386 break;
10387 }
10388
10389 case token_type::literal_false:
10390 {
10391 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10392 {
10393 return false;
10394 }
10395 break;
10396 }
10397
10398 case token_type::literal_null:
10399 {
10400 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10401 {
10402 return false;
10403 }
10404 break;
10405 }
10406
10407 case token_type::literal_true:
10408 {
10409 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
10410 {
10411 return false;
10412 }
10413 break;
10414 }
10415
10416 case token_type::value_integer:
10417 {
10418 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
10419 {
10420 return false;
10421 }
10422 break;
10423 }
10424
10425 case token_type::value_string:
10426 {
10427 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
10428 {
10429 return false;
10430 }
10431 break;
10432 }
10433
10434 case token_type::value_unsigned:
10435 {
10436 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
10437 {
10438 return false;
10439 }
10440 break;
10441 }
10442
10443 case token_type::parse_error:
10444 {
10445 // using "uninitialized" to avoid "expected" message
10446 return sax->parse_error(m_lexer.get_position(),
10447 m_lexer.get_token_string(),
10448 parse_error::create(101, m_lexer.get_position(),
10449 exception_message(token_type::uninitialized, "value")));
10450 }
10451
10452 default: // the last token was unexpected
10453 {
10454 return sax->parse_error(m_lexer.get_position(),
10455 m_lexer.get_token_string(),
10456 parse_error::create(101, m_lexer.get_position(),
10457 exception_message(token_type::literal_or_value, "value")));
10458 }
10459 }
10460 }
10461 else
10462 {
10463 skip_to_state_evaluation = false;
10464 }
10465
10466 // we reached this line after we successfully parsed a value
10467 if (states.empty())
10468 {
10469 // empty stack: we reached the end of the hierarchy: done
10470 return true;
10471 }
10472
10473 if (states.back()) // array
10474 {
10475 // comma -> next value
10476 if (get_token() == token_type::value_separator)
10477 {
10478 // parse a new value
10479 get_token();
10480 continue;
10481 }
10482
10483 // closing ]
10484 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
10485 {
10486 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10487 {
10488 return false;
10489 }
10490
10491 // We are done with this array. Before we can parse a
10492 // new value, we need to evaluate the new state first.
10493 // By setting skip_to_state_evaluation to false, we
10494 // are effectively jumping to the beginning of this if.
10495 JSON_ASSERT(!states.empty());
10496 states.pop_back();
10497 skip_to_state_evaluation = true;
10498 continue;
10499 }
10500
10501 return sax->parse_error(m_lexer.get_position(),
10502 m_lexer.get_token_string(),
10503 parse_error::create(101, m_lexer.get_position(),
10504 exception_message(token_type::end_array, "array")));
10505 }
10506 else // object
10507 {
10508 // comma -> next value
10509 if (get_token() == token_type::value_separator)
10510 {
10511 // parse key
10512 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
10513 {
10514 return sax->parse_error(m_lexer.get_position(),
10515 m_lexer.get_token_string(),
10516 parse_error::create(101, m_lexer.get_position(),
10517 exception_message(token_type::value_string, "object key")));
10518 }
10519
10520 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10521 {
10522 return false;
10523 }
10524
10525 // parse separator (:)
10526 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10527 {
10528 return sax->parse_error(m_lexer.get_position(),
10529 m_lexer.get_token_string(),
10530 parse_error::create(101, m_lexer.get_position(),
10531 exception_message(token_type::name_separator, "object separator")));
10532 }
10533
10534 // parse values
10535 get_token();
10536 continue;
10537 }
10538
10539 // closing }
10540 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
10541 {
10542 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10543 {
10544 return false;
10545 }
10546
10547 // We are done with this object. Before we can parse a
10548 // new value, we need to evaluate the new state first.
10549 // By setting skip_to_state_evaluation to false, we
10550 // are effectively jumping to the beginning of this if.
10551 JSON_ASSERT(!states.empty());
10552 states.pop_back();
10553 skip_to_state_evaluation = true;
10554 continue;
10555 }
10556
10557 return sax->parse_error(m_lexer.get_position(),
10558 m_lexer.get_token_string(),
10559 parse_error::create(101, m_lexer.get_position(),
10560 exception_message(token_type::end_object, "object")));
10561 }
10562 }
10563 }
10564
10565 /// get next token from lexer
10566 token_type get_token()
10567 {
10568 return last_token = m_lexer.scan();
10569 }
10570
10571 std::string exception_message(const token_type expected, const std::string& context)
10572 {
10573 std::string error_msg = "syntax error ";
10574
10575 if (!context.empty())
10576 {
10577 error_msg += "while parsing " + context + " ";
10578 }
10579
10580 error_msg += "- ";
10581
10582 if (last_token == token_type::parse_error)
10583 {
10584 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
10585 m_lexer.get_token_string() + "'";
10586 }
10587 else
10588 {
10589 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
10590 }
10591
10592 if (expected != token_type::uninitialized)
10593 {
10594 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
10595 }
10596
10597 return error_msg;
10598 }
10599
10600 private:
10601 /// callback function
10602 const parser_callback_t<BasicJsonType> callback = nullptr;
10603 /// the type of the last read token
10604 token_type last_token = token_type::uninitialized;
10605 /// the lexer
10606 lexer_t m_lexer;
10607 /// whether to throw exceptions in case of errors
10608 const bool allow_exceptions = true;
10609 };
10610 } // namespace detail
10611 } // namespace nlohmann
10612
10613 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
10614
10615
10616 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10617
10618
10619 #include <cstddef> // ptrdiff_t
10620 #include <limits> // numeric_limits
10621
10622 namespace nlohmann
10623 {
10624 namespace detail
10625 {
10626 /*
10627 @brief an iterator for primitive JSON types
10628
10629 This class models an iterator for primitive JSON types (boolean, number,
10630 string). It's only purpose is to allow the iterator/const_iterator classes
10631 to "iterate" over primitive values. Internally, the iterator is modeled by
10632 a `difference_type` variable. Value begin_value (`0`) models the begin,
10633 end_value (`1`) models past the end.
10634 */
10635 class primitive_iterator_t
10636 {
10637 private:
10638 using difference_type = std::ptrdiff_t;
10639 static constexpr difference_type begin_value = 0;
10640 static constexpr difference_type end_value = begin_value + 1;
10641
10642 /// iterator as signed integer type
10643 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
10644
10645 public:
10646 constexpr difference_type get_value() const noexcept
10647 {
10648 return m_it;
10649 }
10650
10651 /// set iterator to a defined beginning
10652 void set_begin() noexcept
10653 {
10654 m_it = begin_value;
10655 }
10656
10657 /// set iterator to a defined past the end
10658 void set_end() noexcept
10659 {
10660 m_it = end_value;
10661 }
10662
10663 /// return whether the iterator can be dereferenced
10664 constexpr bool is_begin() const noexcept
10665 {
10666 return m_it == begin_value;
10667 }
10668
10669 /// return whether the iterator is at end
10670 constexpr bool is_end() const noexcept
10671 {
10672 return m_it == end_value;
10673 }
10674
10675 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10676 {
10677 return lhs.m_it == rhs.m_it;
10678 }
10679
10680 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10681 {
10682 return lhs.m_it < rhs.m_it;
10683 }
10684
10685 primitive_iterator_t operator+(difference_type n) noexcept
10686 {
10687 auto result = *this;
10688 result += n;
10689 return result;
10690 }
10691
10692 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10693 {
10694 return lhs.m_it - rhs.m_it;
10695 }
10696
10697 primitive_iterator_t& operator++() noexcept
10698 {
10699 ++m_it;
10700 return *this;
10701 }
10702
10703 primitive_iterator_t const operator++(int) noexcept
10704 {
10705 auto result = *this;
10706 ++m_it;
10707 return result;
10708 }
10709
10710 primitive_iterator_t& operator--() noexcept
10711 {
10712 --m_it;
10713 return *this;
10714 }
10715
10716 primitive_iterator_t const operator--(int) noexcept
10717 {
10718 auto result = *this;
10719 --m_it;
10720 return result;
10721 }
10722
10723 primitive_iterator_t& operator+=(difference_type n) noexcept
10724 {
10725 m_it += n;
10726 return *this;
10727 }
10728
10729 primitive_iterator_t& operator-=(difference_type n) noexcept
10730 {
10731 m_it -= n;
10732 return *this;
10733 }
10734 };
10735 } // namespace detail
10736 } // namespace nlohmann
10737
10738
10739 namespace nlohmann
10740 {
10741 namespace detail
10742 {
10743 /*!
10744 @brief an iterator value
10745
10746 @note This structure could easily be a union, but MSVC currently does not allow
10747 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
10748 */
10749 template<typename BasicJsonType> struct internal_iterator
10750 {
10751 /// iterator for JSON objects
10752 typename BasicJsonType::object_t::iterator object_iterator {};
10753 /// iterator for JSON arrays
10754 typename BasicJsonType::array_t::iterator array_iterator {};
10755 /// generic iterator for all other types
10756 primitive_iterator_t primitive_iterator {};
10757 };
10758 } // namespace detail
10759 } // namespace nlohmann
10760
10761 // #include <nlohmann/detail/iterators/iter_impl.hpp>
10762
10763
10764 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
10765 #include <type_traits> // conditional, is_const, remove_const
10766
10767 // #include <nlohmann/detail/exceptions.hpp>
10768
10769 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
10770
10771 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10772
10773 // #include <nlohmann/detail/macro_scope.hpp>
10774
10775 // #include <nlohmann/detail/meta/cpp_future.hpp>
10776
10777 // #include <nlohmann/detail/meta/type_traits.hpp>
10778
10779 // #include <nlohmann/detail/value_t.hpp>
10780
10781
10782 namespace nlohmann
10783 {
10784 namespace detail
10785 {
10786 // forward declare, to be able to friend it later on
10787 template<typename IteratorType> class iteration_proxy;
10788 template<typename IteratorType> class iteration_proxy_value;
10789
10790 /*!
10791 @brief a template for a bidirectional iterator for the @ref basic_json class
10792 This class implements a both iterators (iterator and const_iterator) for the
10793 @ref basic_json class.
10794 @note An iterator is called *initialized* when a pointer to a JSON value has
10795 been set (e.g., by a constructor or a copy assignment). If the iterator is
10796 default-constructed, it is *uninitialized* and most methods are undefined.
10797 **The library uses assertions to detect calls on uninitialized iterators.**
10798 @requirement The class satisfies the following concept requirements:
10799 -
10800 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
10801 The iterator that can be moved can be moved in both directions (i.e.
10802 incremented and decremented).
10803 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
10804 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
10805 */
10806 template<typename BasicJsonType>
10807 class iter_impl
10808 {
10809 /// allow basic_json to access private members
10810 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
10811 friend BasicJsonType;
10812 friend iteration_proxy<iter_impl>;
10813 friend iteration_proxy_value<iter_impl>;
10814
10815 using object_t = typename BasicJsonType::object_t;
10816 using array_t = typename BasicJsonType::array_t;
10817 // make sure BasicJsonType is basic_json or const basic_json
10818 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
10819 "iter_impl only accepts (const) basic_json");
10820
10821 public:
10822
10823 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
10824 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
10825 /// A user-defined iterator should provide publicly accessible typedefs named
10826 /// iterator_category, value_type, difference_type, pointer, and reference.
10827 /// Note that value_type is required to be non-const, even for constant iterators.
10828 using iterator_category = std::bidirectional_iterator_tag;
10829
10830 /// the type of the values when the iterator is dereferenced
10831 using value_type = typename BasicJsonType::value_type;
10832 /// a type to represent differences between iterators
10833 using difference_type = typename BasicJsonType::difference_type;
10834 /// defines a pointer to the type iterated over (value_type)
10835 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
10836 typename BasicJsonType::const_pointer,
10837 typename BasicJsonType::pointer>::type;
10838 /// defines a reference to the type iterated over (value_type)
10839 using reference =
10840 typename std::conditional<std::is_const<BasicJsonType>::value,
10841 typename BasicJsonType::const_reference,
10842 typename BasicJsonType::reference>::type;
10843
10844 /// default constructor
10845 iter_impl() = default;
10846
10847 /*!
10848 @brief constructor for a given JSON instance
10849 @param[in] object pointer to a JSON object for this iterator
10850 @pre object != nullptr
10851 @post The iterator is initialized; i.e. `m_object != nullptr`.
10852 */
10853 explicit iter_impl(pointer object) noexcept : m_object(object)
10854 {
10855 JSON_ASSERT(m_object != nullptr);
10856
10857 switch (m_object->m_type)
10858 {
10859 case value_t::object:
10860 {
10861 m_it.object_iterator = typename object_t::iterator();
10862 break;
10863 }
10864
10865 case value_t::array:
10866 {
10867 m_it.array_iterator = typename array_t::iterator();
10868 break;
10869 }
10870
10871 default:
10872 {
10873 m_it.primitive_iterator = primitive_iterator_t();
10874 break;
10875 }
10876 }
10877 }
10878
10879 /*!
10880 @note The conventional copy constructor and copy assignment are implicitly
10881 defined. Combined with the following converting constructor and
10882 assignment, they support: (1) copy from iterator to iterator, (2)
10883 copy from const iterator to const iterator, and (3) conversion from
10884 iterator to const iterator. However conversion from const iterator
10885 to iterator is not defined.
10886 */
10887
10888 /*!
10889 @brief const copy constructor
10890 @param[in] other const iterator to copy from
10891 @note This copy constructor had to be defined explicitly to circumvent a bug
10892 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
10893 information refer to: https://github.com/nlohmann/json/issues/1608
10894 */
10895 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
10896 : m_object(other.m_object), m_it(other.m_it)
10897 {}
10898
10899 /*!
10900 @brief converting assignment
10901 @param[in] other const iterator to copy from
10902 @return const/non-const iterator
10903 @note It is not checked whether @a other is initialized.
10904 */
10905 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
10906 {
10907 m_object = other.m_object;
10908 m_it = other.m_it;
10909 return *this;
10910 }
10911
10912 /*!
10913 @brief converting constructor
10914 @param[in] other non-const iterator to copy from
10915 @note It is not checked whether @a other is initialized.
10916 */
10917 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10918 : m_object(other.m_object), m_it(other.m_it)
10919 {}
10920
10921 /*!
10922 @brief converting assignment
10923 @param[in] other non-const iterator to copy from
10924 @return const/non-const iterator
10925 @note It is not checked whether @a other is initialized.
10926 */
10927 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10928 {
10929 m_object = other.m_object;
10930 m_it = other.m_it;
10931 return *this;
10932 }
10933
10934 private:
10935 /*!
10936 @brief set the iterator to the first value
10937 @pre The iterator is initialized; i.e. `m_object != nullptr`.
10938 */
10939 void set_begin() noexcept
10940 {
10941 JSON_ASSERT(m_object != nullptr);
10942
10943 switch (m_object->m_type)
10944 {
10945 case value_t::object:
10946 {
10947 m_it.object_iterator = m_object->m_value.object->begin();
10948 break;
10949 }
10950
10951 case value_t::array:
10952 {
10953 m_it.array_iterator = m_object->m_value.array->begin();
10954 break;
10955 }
10956
10957 case value_t::null:
10958 {
10959 // set to end so begin()==end() is true: null is empty
10960 m_it.primitive_iterator.set_end();
10961 break;
10962 }
10963
10964 default:
10965 {
10966 m_it.primitive_iterator.set_begin();
10967 break;
10968 }
10969 }
10970 }
10971
10972 /*!
10973 @brief set the iterator past the last value
10974 @pre The iterator is initialized; i.e. `m_object != nullptr`.
10975 */
10976 void set_end() noexcept
10977 {
10978 JSON_ASSERT(m_object != nullptr);
10979
10980 switch (m_object->m_type)
10981 {
10982 case value_t::object:
10983 {
10984 m_it.object_iterator = m_object->m_value.object->end();
10985 break;
10986 }
10987
10988 case value_t::array:
10989 {
10990 m_it.array_iterator = m_object->m_value.array->end();
10991 break;
10992 }
10993
10994 default:
10995 {
10996 m_it.primitive_iterator.set_end();
10997 break;
10998 }
10999 }
11000 }
11001
11002 public:
11003 /*!
11004 @brief return a reference to the value pointed to by the iterator
11005 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11006 */
11007 reference operator*() const
11008 {
11009 JSON_ASSERT(m_object != nullptr);
11010
11011 switch (m_object->m_type)
11012 {
11013 case value_t::object:
11014 {
11015 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11016 return m_it.object_iterator->second;
11017 }
11018
11019 case value_t::array:
11020 {
11021 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11022 return *m_it.array_iterator;
11023 }
11024
11025 case value_t::null:
11026 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11027
11028 default:
11029 {
11030 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11031 {
11032 return *m_object;
11033 }
11034
11035 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11036 }
11037 }
11038 }
11039
11040 /*!
11041 @brief dereference the iterator
11042 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11043 */
11044 pointer operator->() const
11045 {
11046 JSON_ASSERT(m_object != nullptr);
11047
11048 switch (m_object->m_type)
11049 {
11050 case value_t::object:
11051 {
11052 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11053 return &(m_it.object_iterator->second);
11054 }
11055
11056 case value_t::array:
11057 {
11058 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11059 return &*m_it.array_iterator;
11060 }
11061
11062 default:
11063 {
11064 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11065 {
11066 return m_object;
11067 }
11068
11069 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11070 }
11071 }
11072 }
11073
11074 /*!
11075 @brief post-increment (it++)
11076 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11077 */
11078 iter_impl const operator++(int)
11079 {
11080 auto result = *this;
11081 ++(*this);
11082 return result;
11083 }
11084
11085 /*!
11086 @brief pre-increment (++it)
11087 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11088 */
11089 iter_impl& operator++()
11090 {
11091 JSON_ASSERT(m_object != nullptr);
11092
11093 switch (m_object->m_type)
11094 {
11095 case value_t::object:
11096 {
11097 std::advance(m_it.object_iterator, 1);
11098 break;
11099 }
11100
11101 case value_t::array:
11102 {
11103 std::advance(m_it.array_iterator, 1);
11104 break;
11105 }
11106
11107 default:
11108 {
11109 ++m_it.primitive_iterator;
11110 break;
11111 }
11112 }
11113
11114 return *this;
11115 }
11116
11117 /*!
11118 @brief post-decrement (it--)
11119 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11120 */
11121 iter_impl const operator--(int)
11122 {
11123 auto result = *this;
11124 --(*this);
11125 return result;
11126 }
11127
11128 /*!
11129 @brief pre-decrement (--it)
11130 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11131 */
11132 iter_impl& operator--()
11133 {
11134 JSON_ASSERT(m_object != nullptr);
11135
11136 switch (m_object->m_type)
11137 {
11138 case value_t::object:
11139 {
11140 std::advance(m_it.object_iterator, -1);
11141 break;
11142 }
11143
11144 case value_t::array:
11145 {
11146 std::advance(m_it.array_iterator, -1);
11147 break;
11148 }
11149
11150 default:
11151 {
11152 --m_it.primitive_iterator;
11153 break;
11154 }
11155 }
11156
11157 return *this;
11158 }
11159
11160 /*!
11161 @brief comparison: equal
11162 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11163 */
11164 bool operator==(const iter_impl& other) const
11165 {
11166 // if objects are not the same, the comparison is undefined
11167 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11168 {
11169 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11170 }
11171
11172 JSON_ASSERT(m_object != nullptr);
11173
11174 switch (m_object->m_type)
11175 {
11176 case value_t::object:
11177 return (m_it.object_iterator == other.m_it.object_iterator);
11178
11179 case value_t::array:
11180 return (m_it.array_iterator == other.m_it.array_iterator);
11181
11182 default:
11183 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11184 }
11185 }
11186
11187 /*!
11188 @brief comparison: not equal
11189 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11190 */
11191 bool operator!=(const iter_impl& other) const
11192 {
11193 return !operator==(other);
11194 }
11195
11196 /*!
11197 @brief comparison: smaller
11198 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11199 */
11200 bool operator<(const iter_impl& other) const
11201 {
11202 // if objects are not the same, the comparison is undefined
11203 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11204 {
11205 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11206 }
11207
11208 JSON_ASSERT(m_object != nullptr);
11209
11210 switch (m_object->m_type)
11211 {
11212 case value_t::object:
11213 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
11214
11215 case value_t::array:
11216 return (m_it.array_iterator < other.m_it.array_iterator);
11217
11218 default:
11219 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11220 }
11221 }
11222
11223 /*!
11224 @brief comparison: less than or equal
11225 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11226 */
11227 bool operator<=(const iter_impl& other) const
11228 {
11229 return !other.operator < (*this);
11230 }
11231
11232 /*!
11233 @brief comparison: greater than
11234 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11235 */
11236 bool operator>(const iter_impl& other) const
11237 {
11238 return !operator<=(other);
11239 }
11240
11241 /*!
11242 @brief comparison: greater than or equal
11243 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11244 */
11245 bool operator>=(const iter_impl& other) const
11246 {
11247 return !operator<(other);
11248 }
11249
11250 /*!
11251 @brief add to iterator
11252 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11253 */
11254 iter_impl& operator+=(difference_type i)
11255 {
11256 JSON_ASSERT(m_object != nullptr);
11257
11258 switch (m_object->m_type)
11259 {
11260 case value_t::object:
11261 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11262
11263 case value_t::array:
11264 {
11265 std::advance(m_it.array_iterator, i);
11266 break;
11267 }
11268
11269 default:
11270 {
11271 m_it.primitive_iterator += i;
11272 break;
11273 }
11274 }
11275
11276 return *this;
11277 }
11278
11279 /*!
11280 @brief subtract from iterator
11281 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11282 */
11283 iter_impl& operator-=(difference_type i)
11284 {
11285 return operator+=(-i);
11286 }
11287
11288 /*!
11289 @brief add to iterator
11290 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11291 */
11292 iter_impl operator+(difference_type i) const
11293 {
11294 auto result = *this;
11295 result += i;
11296 return result;
11297 }
11298
11299 /*!
11300 @brief addition of distance and iterator
11301 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11302 */
11303 friend iter_impl operator+(difference_type i, const iter_impl& it)
11304 {
11305 auto result = it;
11306 result += i;
11307 return result;
11308 }
11309
11310 /*!
11311 @brief subtract from iterator
11312 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11313 */
11314 iter_impl operator-(difference_type i) const
11315 {
11316 auto result = *this;
11317 result -= i;
11318 return result;
11319 }
11320
11321 /*!
11322 @brief return difference
11323 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11324 */
11325 difference_type operator-(const iter_impl& other) const
11326 {
11327 JSON_ASSERT(m_object != nullptr);
11328
11329 switch (m_object->m_type)
11330 {
11331 case value_t::object:
11332 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11333
11334 case value_t::array:
11335 return m_it.array_iterator - other.m_it.array_iterator;
11336
11337 default:
11338 return m_it.primitive_iterator - other.m_it.primitive_iterator;
11339 }
11340 }
11341
11342 /*!
11343 @brief access to successor
11344 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11345 */
11346 reference operator[](difference_type n) const
11347 {
11348 JSON_ASSERT(m_object != nullptr);
11349
11350 switch (m_object->m_type)
11351 {
11352 case value_t::object:
11353 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
11354
11355 case value_t::array:
11356 return *std::next(m_it.array_iterator, n);
11357
11358 case value_t::null:
11359 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11360
11361 default:
11362 {
11363 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
11364 {
11365 return *m_object;
11366 }
11367
11368 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11369 }
11370 }
11371 }
11372
11373 /*!
11374 @brief return the key of an object iterator
11375 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11376 */
11377 const typename object_t::key_type& key() const
11378 {
11379 JSON_ASSERT(m_object != nullptr);
11380
11381 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
11382 {
11383 return m_it.object_iterator->first;
11384 }
11385
11386 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
11387 }
11388
11389 /*!
11390 @brief return the value of an iterator
11391 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11392 */
11393 reference value() const
11394 {
11395 return operator*();
11396 }
11397
11398 private:
11399 /// associated JSON instance
11400 pointer m_object = nullptr;
11401 /// the actual iterator of the associated instance
11402 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
11403 };
11404 } // namespace detail
11405 } // namespace nlohmann
11406
11407 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
11408
11409 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
11410
11411
11412 #include <cstddef> // ptrdiff_t
11413 #include <iterator> // reverse_iterator
11414 #include <utility> // declval
11415
11416 namespace nlohmann
11417 {
11418 namespace detail
11419 {
11420 //////////////////////
11421 // reverse_iterator //
11422 //////////////////////
11423
11424 /*!
11425 @brief a template for a reverse iterator class
11426
11427 @tparam Base the base iterator type to reverse. Valid types are @ref
11428 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
11429 create @ref const_reverse_iterator).
11430
11431 @requirement The class satisfies the following concept requirements:
11432 -
11433 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11434 The iterator that can be moved can be moved in both directions (i.e.
11435 incremented and decremented).
11436 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
11437 It is possible to write to the pointed-to element (only if @a Base is
11438 @ref iterator).
11439
11440 @since version 1.0.0
11441 */
11442 template<typename Base>
11443 class json_reverse_iterator : public std::reverse_iterator<Base>
11444 {
11445 public:
11446 using difference_type = std::ptrdiff_t;
11447 /// shortcut to the reverse iterator adapter
11448 using base_iterator = std::reverse_iterator<Base>;
11449 /// the reference type for the pointed-to element
11450 using reference = typename Base::reference;
11451
11452 /// create reverse iterator from iterator
11453 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
11454 : base_iterator(it) {}
11455
11456 /// create reverse iterator from base class
11457 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
11458
11459 /// post-increment (it++)
11460 json_reverse_iterator const operator++(int)
11461 {
11462 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
11463 }
11464
11465 /// pre-increment (++it)
11466 json_reverse_iterator& operator++()
11467 {
11468 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
11469 }
11470
11471 /// post-decrement (it--)
11472 json_reverse_iterator const operator--(int)
11473 {
11474 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
11475 }
11476
11477 /// pre-decrement (--it)
11478 json_reverse_iterator& operator--()
11479 {
11480 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
11481 }
11482
11483 /// add to iterator
11484 json_reverse_iterator& operator+=(difference_type i)
11485 {
11486 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
11487 }
11488
11489 /// add to iterator
11490 json_reverse_iterator operator+(difference_type i) const
11491 {
11492 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
11493 }
11494
11495 /// subtract from iterator
11496 json_reverse_iterator operator-(difference_type i) const
11497 {
11498 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
11499 }
11500
11501 /// return difference
11502 difference_type operator-(const json_reverse_iterator& other) const
11503 {
11504 return base_iterator(*this) - base_iterator(other);
11505 }
11506
11507 /// access to successor
11508 reference operator[](difference_type n) const
11509 {
11510 return *(this->operator+(n));
11511 }
11512
11513 /// return the key of an object iterator
11514 auto key() const -> decltype(std::declval<Base>().key())
11515 {
11516 auto it = --this->base();
11517 return it.key();
11518 }
11519
11520 /// return the value of an iterator
11521 reference value() const
11522 {
11523 auto it = --this->base();
11524 return it.operator * ();
11525 }
11526 };
11527 } // namespace detail
11528 } // namespace nlohmann
11529
11530 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11531
11532 // #include <nlohmann/detail/json_pointer.hpp>
11533
11534
11535 #include <algorithm> // all_of
11536 #include <cctype> // isdigit
11537 #include <limits> // max
11538 #include <numeric> // accumulate
11539 #include <string> // string
11540 #include <utility> // move
11541 #include <vector> // vector
11542
11543 // #include <nlohmann/detail/exceptions.hpp>
11544
11545 // #include <nlohmann/detail/macro_scope.hpp>
11546
11547 // #include <nlohmann/detail/value_t.hpp>
11548
11549
11550 namespace nlohmann
11551 {
11552 template<typename BasicJsonType>
11553 class json_pointer
11554 {
11555 // allow basic_json to access private members
11556 NLOHMANN_BASIC_JSON_TPL_DECLARATION
11557 friend class basic_json;
11558
11559 public:
11560 /*!
11561 @brief create JSON pointer
11562
11563 Create a JSON pointer according to the syntax described in
11564 [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
11565
11566 @param[in] s string representing the JSON pointer; if omitted, the empty
11567 string is assumed which references the whole JSON value
11568
11569 @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
11570 not begin with a slash (`/`); see example below
11571
11572 @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
11573 not followed by `0` (representing `~`) or `1` (representing `/`); see
11574 example below
11575
11576 @liveexample{The example shows the construction several valid JSON pointers
11577 as well as the exceptional behavior.,json_pointer}
11578
11579 @since version 2.0.0
11580 */
11581 explicit json_pointer(const std::string& s = "")
11582 : reference_tokens(split(s))
11583 {}
11584
11585 /*!
11586 @brief return a string representation of the JSON pointer
11587
11588 @invariant For each JSON pointer `ptr`, it holds:
11589 @code {.cpp}
11590 ptr == json_pointer(ptr.to_string());
11591 @endcode
11592
11593 @return a string representation of the JSON pointer
11594
11595 @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
11596
11597 @since version 2.0.0
11598 */
11599 std::string to_string() const
11600 {
11601 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11602 std::string{},
11603 [](const std::string & a, const std::string & b)
11604 {
11605 return a + "/" + escape(b);
11606 });
11607 }
11608
11609 /// @copydoc to_string()
11610 operator std::string() const
11611 {
11612 return to_string();
11613 }
11614
11615 /*!
11616 @brief append another JSON pointer at the end of this JSON pointer
11617
11618 @param[in] ptr JSON pointer to append
11619 @return JSON pointer with @a ptr appended
11620
11621 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11622
11623 @complexity Linear in the length of @a ptr.
11624
11625 @sa @ref operator/=(std::string) to append a reference token
11626 @sa @ref operator/=(std::size_t) to append an array index
11627 @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
11628
11629 @since version 3.6.0
11630 */
11631 json_pointer& operator/=(const json_pointer& ptr)
11632 {
11633 reference_tokens.insert(reference_tokens.end(),
11634 ptr.reference_tokens.begin(),
11635 ptr.reference_tokens.end());
11636 return *this;
11637 }
11638
11639 /*!
11640 @brief append an unescaped reference token at the end of this JSON pointer
11641
11642 @param[in] token reference token to append
11643 @return JSON pointer with @a token appended without escaping @a token
11644
11645 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11646
11647 @complexity Amortized constant.
11648
11649 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11650 @sa @ref operator/=(std::size_t) to append an array index
11651 @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
11652
11653 @since version 3.6.0
11654 */
11655 json_pointer& operator/=(std::string token)
11656 {
11657 push_back(std::move(token));
11658 return *this;
11659 }
11660
11661 /*!
11662 @brief append an array index at the end of this JSON pointer
11663
11664 @param[in] array_idx array index to append
11665 @return JSON pointer with @a array_idx appended
11666
11667 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11668
11669 @complexity Amortized constant.
11670
11671 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11672 @sa @ref operator/=(std::string) to append a reference token
11673 @sa @ref operator/(const json_pointer&, std::string) for a binary operator
11674
11675 @since version 3.6.0
11676 */
11677 json_pointer& operator/=(std::size_t array_idx)
11678 {
11679 return *this /= std::to_string(array_idx);
11680 }
11681
11682 /*!
11683 @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
11684
11685 @param[in] lhs JSON pointer
11686 @param[in] rhs JSON pointer
11687 @return a new JSON pointer with @a rhs appended to @a lhs
11688
11689 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11690
11691 @complexity Linear in the length of @a lhs and @a rhs.
11692
11693 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11694
11695 @since version 3.6.0
11696 */
11697 friend json_pointer operator/(const json_pointer& lhs,
11698 const json_pointer& rhs)
11699 {
11700 return json_pointer(lhs) /= rhs;
11701 }
11702
11703 /*!
11704 @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
11705
11706 @param[in] ptr JSON pointer
11707 @param[in] token reference token
11708 @return a new JSON pointer with unescaped @a token appended to @a ptr
11709
11710 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11711
11712 @complexity Linear in the length of @a ptr.
11713
11714 @sa @ref operator/=(std::string) to append a reference token
11715
11716 @since version 3.6.0
11717 */
11718 friend json_pointer operator/(const json_pointer& ptr, std::string token)
11719 {
11720 return json_pointer(ptr) /= std::move(token);
11721 }
11722
11723 /*!
11724 @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
11725
11726 @param[in] ptr JSON pointer
11727 @param[in] array_idx array index
11728 @return a new JSON pointer with @a array_idx appended to @a ptr
11729
11730 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11731
11732 @complexity Linear in the length of @a ptr.
11733
11734 @sa @ref operator/=(std::size_t) to append an array index
11735
11736 @since version 3.6.0
11737 */
11738 friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx)
11739 {
11740 return json_pointer(ptr) /= array_idx;
11741 }
11742
11743 /*!
11744 @brief returns the parent of this JSON pointer
11745
11746 @return parent of this JSON pointer; in case this JSON pointer is the root,
11747 the root itself is returned
11748
11749 @complexity Linear in the length of the JSON pointer.
11750
11751 @liveexample{The example shows the result of `parent_pointer` for different
11752 JSON Pointers.,json_pointer__parent_pointer}
11753
11754 @since version 3.6.0
11755 */
11756 json_pointer parent_pointer() const
11757 {
11758 if (empty())
11759 {
11760 return *this;
11761 }
11762
11763 json_pointer res = *this;
11764 res.pop_back();
11765 return res;
11766 }
11767
11768 /*!
11769 @brief remove last reference token
11770
11771 @pre not `empty()`
11772
11773 @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
11774
11775 @complexity Constant.
11776
11777 @throw out_of_range.405 if JSON pointer has no parent
11778
11779 @since version 3.6.0
11780 */
11781 void pop_back()
11782 {
11783 if (JSON_HEDLEY_UNLIKELY(empty()))
11784 {
11785 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11786 }
11787
11788 reference_tokens.pop_back();
11789 }
11790
11791 /*!
11792 @brief return last reference token
11793
11794 @pre not `empty()`
11795 @return last reference token
11796
11797 @liveexample{The example shows the usage of `back`.,json_pointer__back}
11798
11799 @complexity Constant.
11800
11801 @throw out_of_range.405 if JSON pointer has no parent
11802
11803 @since version 3.6.0
11804 */
11805 const std::string& back() const
11806 {
11807 if (JSON_HEDLEY_UNLIKELY(empty()))
11808 {
11809 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11810 }
11811
11812 return reference_tokens.back();
11813 }
11814
11815 /*!
11816 @brief append an unescaped token at the end of the reference pointer
11817
11818 @param[in] token token to add
11819
11820 @complexity Amortized constant.
11821
11822 @liveexample{The example shows the result of `push_back` for different
11823 JSON Pointers.,json_pointer__push_back}
11824
11825 @since version 3.6.0
11826 */
11827 void push_back(const std::string& token)
11828 {
11829 reference_tokens.push_back(token);
11830 }
11831
11832 /// @copydoc push_back(const std::string&)
11833 void push_back(std::string&& token)
11834 {
11835 reference_tokens.push_back(std::move(token));
11836 }
11837
11838 /*!
11839 @brief return whether pointer points to the root document
11840
11841 @return true iff the JSON pointer points to the root document
11842
11843 @complexity Constant.
11844
11845 @exceptionsafety No-throw guarantee: this function never throws exceptions.
11846
11847 @liveexample{The example shows the result of `empty` for different JSON
11848 Pointers.,json_pointer__empty}
11849
11850 @since version 3.6.0
11851 */
11852 bool empty() const noexcept
11853 {
11854 return reference_tokens.empty();
11855 }
11856
11857 private:
11858 /*!
11859 @param[in] s reference token to be converted into an array index
11860
11861 @return integer representation of @a s
11862
11863 @throw parse_error.106 if an array index begins with '0'
11864 @throw parse_error.109 if an array index begins not with a digit
11865 @throw out_of_range.404 if string @a s could not be converted to an integer
11866 @throw out_of_range.410 if an array index exceeds size_type
11867 */
11868 static typename BasicJsonType::size_type array_index(const std::string& s)
11869 {
11870 using size_type = typename BasicJsonType::size_type;
11871
11872 // error condition (cf. RFC 6901, Sect. 4)
11873 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
11874 {
11875 JSON_THROW(detail::parse_error::create(106, 0,
11876 "array index '" + s +
11877 "' must not begin with '0'"));
11878 }
11879
11880 // error condition (cf. RFC 6901, Sect. 4)
11881 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
11882 {
11883 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
11884 }
11885
11886 std::size_t processed_chars = 0;
11887 unsigned long long res = 0;
11888 JSON_TRY
11889 {
11890 res = std::stoull(s, &processed_chars);
11891 }
11892 JSON_CATCH(std::out_of_range&)
11893 {
11894 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11895 }
11896
11897 // check if the string was completely read
11898 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
11899 {
11900 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11901 }
11902
11903 // only triggered on special platforms (like 32bit), see also
11904 // https://github.com/nlohmann/json/pull/2203
11905 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
11906 {
11907 JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
11908 }
11909
11910 return static_cast<size_type>(res);
11911 }
11912
11913 json_pointer top() const
11914 {
11915 if (JSON_HEDLEY_UNLIKELY(empty()))
11916 {
11917 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11918 }
11919
11920 json_pointer result = *this;
11921 result.reference_tokens = {reference_tokens[0]};
11922 return result;
11923 }
11924
11925 /*!
11926 @brief create and return a reference to the pointed to value
11927
11928 @complexity Linear in the number of reference tokens.
11929
11930 @throw parse_error.109 if array index is not a number
11931 @throw type_error.313 if value cannot be unflattened
11932 */
11933 BasicJsonType& get_and_create(BasicJsonType& j) const
11934 {
11935 auto result = &j;
11936
11937 // in case no reference tokens exist, return a reference to the JSON value
11938 // j which will be overwritten by a primitive value
11939 for (const auto& reference_token : reference_tokens)
11940 {
11941 switch (result->type())
11942 {
11943 case detail::value_t::null:
11944 {
11945 if (reference_token == "0")
11946 {
11947 // start a new array if reference token is 0
11948 result = &result->operator[](0);
11949 }
11950 else
11951 {
11952 // start a new object otherwise
11953 result = &result->operator[](reference_token);
11954 }
11955 break;
11956 }
11957
11958 case detail::value_t::object:
11959 {
11960 // create an entry in the object
11961 result = &result->operator[](reference_token);
11962 break;
11963 }
11964
11965 case detail::value_t::array:
11966 {
11967 // create an entry in the array
11968 result = &result->operator[](array_index(reference_token));
11969 break;
11970 }
11971
11972 /*
11973 The following code is only reached if there exists a reference
11974 token _and_ the current value is primitive. In this case, we have
11975 an error situation, because primitive values may only occur as
11976 single value; that is, with an empty list of reference tokens.
11977 */
11978 default:
11979 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11980 }
11981 }
11982
11983 return *result;
11984 }
11985
11986 /*!
11987 @brief return a reference to the pointed to value
11988
11989 @note This version does not throw if a value is not present, but tries to
11990 create nested values instead. For instance, calling this function
11991 with pointer `"/this/that"` on a null value is equivalent to calling
11992 `operator[]("this").operator[]("that")` on that value, effectively
11993 changing the null value to an object.
11994
11995 @param[in] ptr a JSON value
11996
11997 @return reference to the JSON value pointed to by the JSON pointer
11998
11999 @complexity Linear in the length of the JSON pointer.
12000
12001 @throw parse_error.106 if an array index begins with '0'
12002 @throw parse_error.109 if an array index was not a number
12003 @throw out_of_range.404 if the JSON pointer can not be resolved
12004 */
12005 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12006 {
12007 for (const auto& reference_token : reference_tokens)
12008 {
12009 // convert null values to arrays or objects before continuing
12010 if (ptr->is_null())
12011 {
12012 // check if reference token is a number
12013 const bool nums =
12014 std::all_of(reference_token.begin(), reference_token.end(),
12015 [](const unsigned char x)
12016 {
12017 return std::isdigit(x);
12018 });
12019
12020 // change value to array for numbers or "-" or to object otherwise
12021 *ptr = (nums || reference_token == "-")
12022 ? detail::value_t::array
12023 : detail::value_t::object;
12024 }
12025
12026 switch (ptr->type())
12027 {
12028 case detail::value_t::object:
12029 {
12030 // use unchecked object access
12031 ptr = &ptr->operator[](reference_token);
12032 break;
12033 }
12034
12035 case detail::value_t::array:
12036 {
12037 if (reference_token == "-")
12038 {
12039 // explicitly treat "-" as index beyond the end
12040 ptr = &ptr->operator[](ptr->m_value.array->size());
12041 }
12042 else
12043 {
12044 // convert array index to number; unchecked access
12045 ptr = &ptr->operator[](array_index(reference_token));
12046 }
12047 break;
12048 }
12049
12050 default:
12051 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12052 }
12053 }
12054
12055 return *ptr;
12056 }
12057
12058 /*!
12059 @throw parse_error.106 if an array index begins with '0'
12060 @throw parse_error.109 if an array index was not a number
12061 @throw out_of_range.402 if the array index '-' is used
12062 @throw out_of_range.404 if the JSON pointer can not be resolved
12063 */
12064 BasicJsonType& get_checked(BasicJsonType* ptr) const
12065 {
12066 for (const auto& reference_token : reference_tokens)
12067 {
12068 switch (ptr->type())
12069 {
12070 case detail::value_t::object:
12071 {
12072 // note: at performs range check
12073 ptr = &ptr->at(reference_token);
12074 break;
12075 }
12076
12077 case detail::value_t::array:
12078 {
12079 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12080 {
12081 // "-" always fails the range check
12082 JSON_THROW(detail::out_of_range::create(402,
12083 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12084 ") is out of range"));
12085 }
12086
12087 // note: at performs range check
12088 ptr = &ptr->at(array_index(reference_token));
12089 break;
12090 }
12091
12092 default:
12093 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12094 }
12095 }
12096
12097 return *ptr;
12098 }
12099
12100 /*!
12101 @brief return a const reference to the pointed to value
12102
12103 @param[in] ptr a JSON value
12104
12105 @return const reference to the JSON value pointed to by the JSON
12106 pointer
12107
12108 @throw parse_error.106 if an array index begins with '0'
12109 @throw parse_error.109 if an array index was not a number
12110 @throw out_of_range.402 if the array index '-' is used
12111 @throw out_of_range.404 if the JSON pointer can not be resolved
12112 */
12113 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12114 {
12115 for (const auto& reference_token : reference_tokens)
12116 {
12117 switch (ptr->type())
12118 {
12119 case detail::value_t::object:
12120 {
12121 // use unchecked object access
12122 ptr = &ptr->operator[](reference_token);
12123 break;
12124 }
12125
12126 case detail::value_t::array:
12127 {
12128 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12129 {
12130 // "-" cannot be used for const access
12131 JSON_THROW(detail::out_of_range::create(402,
12132 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12133 ") is out of range"));
12134 }
12135
12136 // use unchecked array access
12137 ptr = &ptr->operator[](array_index(reference_token));
12138 break;
12139 }
12140
12141 default:
12142 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12143 }
12144 }
12145
12146 return *ptr;
12147 }
12148
12149 /*!
12150 @throw parse_error.106 if an array index begins with '0'
12151 @throw parse_error.109 if an array index was not a number
12152 @throw out_of_range.402 if the array index '-' is used
12153 @throw out_of_range.404 if the JSON pointer can not be resolved
12154 */
12155 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12156 {
12157 for (const auto& reference_token : reference_tokens)
12158 {
12159 switch (ptr->type())
12160 {
12161 case detail::value_t::object:
12162 {
12163 // note: at performs range check
12164 ptr = &ptr->at(reference_token);
12165 break;
12166 }
12167
12168 case detail::value_t::array:
12169 {
12170 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12171 {
12172 // "-" always fails the range check
12173 JSON_THROW(detail::out_of_range::create(402,
12174 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12175 ") is out of range"));
12176 }
12177
12178 // note: at performs range check
12179 ptr = &ptr->at(array_index(reference_token));
12180 break;
12181 }
12182
12183 default:
12184 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12185 }
12186 }
12187
12188 return *ptr;
12189 }
12190
12191 /*!
12192 @throw parse_error.106 if an array index begins with '0'
12193 @throw parse_error.109 if an array index was not a number
12194 */
12195 bool contains(const BasicJsonType* ptr) const
12196 {
12197 for (const auto& reference_token : reference_tokens)
12198 {
12199 switch (ptr->type())
12200 {
12201 case detail::value_t::object:
12202 {
12203 if (!ptr->contains(reference_token))
12204 {
12205 // we did not find the key in the object
12206 return false;
12207 }
12208
12209 ptr = &ptr->operator[](reference_token);
12210 break;
12211 }
12212
12213 case detail::value_t::array:
12214 {
12215 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12216 {
12217 // "-" always fails the range check
12218 return false;
12219 }
12220 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12221 {
12222 // invalid char
12223 return false;
12224 }
12225 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12226 {
12227 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12228 {
12229 // first char should be between '1' and '9'
12230 return false;
12231 }
12232 for (std::size_t i = 1; i < reference_token.size(); i++)
12233 {
12234 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12235 {
12236 // other char should be between '0' and '9'
12237 return false;
12238 }
12239 }
12240 }
12241
12242 const auto idx = array_index(reference_token);
12243 if (idx >= ptr->size())
12244 {
12245 // index out of range
12246 return false;
12247 }
12248
12249 ptr = &ptr->operator[](idx);
12250 break;
12251 }
12252
12253 default:
12254 {
12255 // we do not expect primitive values if there is still a
12256 // reference token to process
12257 return false;
12258 }
12259 }
12260 }
12261
12262 // no reference token left means we found a primitive value
12263 return true;
12264 }
12265
12266 /*!
12267 @brief split the string input to reference tokens
12268
12269 @note This function is only called by the json_pointer constructor.
12270 All exceptions below are documented there.
12271
12272 @throw parse_error.107 if the pointer is not empty or begins with '/'
12273 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12274 */
12275 static std::vector<std::string> split(const std::string& reference_string)
12276 {
12277 std::vector<std::string> result;
12278
12279 // special case: empty reference string -> no reference tokens
12280 if (reference_string.empty())
12281 {
12282 return result;
12283 }
12284
12285 // check if nonempty reference string begins with slash
12286 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12287 {
12288 JSON_THROW(detail::parse_error::create(107, 1,
12289 "JSON pointer must be empty or begin with '/' - was: '" +
12290 reference_string + "'"));
12291 }
12292
12293 // extract the reference tokens:
12294 // - slash: position of the last read slash (or end of string)
12295 // - start: position after the previous slash
12296 for (
12297 // search for the first slash after the first character
12298 std::size_t slash = reference_string.find_first_of('/', 1),
12299 // set the beginning of the first reference token
12300 start = 1;
12301 // we can stop if start == 0 (if slash == std::string::npos)
12302 start != 0;
12303 // set the beginning of the next reference token
12304 // (will eventually be 0 if slash == std::string::npos)
12305 start = (slash == std::string::npos) ? 0 : slash + 1,
12306 // find next slash
12307 slash = reference_string.find_first_of('/', start))
12308 {
12309 // use the text between the beginning of the reference token
12310 // (start) and the last slash (slash).
12311 auto reference_token = reference_string.substr(start, slash - start);
12312
12313 // check reference tokens are properly escaped
12314 for (std::size_t pos = reference_token.find_first_of('~');
12315 pos != std::string::npos;
12316 pos = reference_token.find_first_of('~', pos + 1))
12317 {
12318 JSON_ASSERT(reference_token[pos] == '~');
12319
12320 // ~ must be followed by 0 or 1
12321 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12322 (reference_token[pos + 1] != '0' &&
12323 reference_token[pos + 1] != '1')))
12324 {
12325 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12326 }
12327 }
12328
12329 // finally, store the reference token
12330 unescape(reference_token);
12331 result.push_back(reference_token);
12332 }
12333
12334 return result;
12335 }
12336
12337 /*!
12338 @brief replace all occurrences of a substring by another string
12339
12340 @param[in,out] s the string to manipulate; changed so that all
12341 occurrences of @a f are replaced with @a t
12342 @param[in] f the substring to replace with @a t
12343 @param[in] t the string to replace @a f
12344
12345 @pre The search string @a f must not be empty. **This precondition is
12346 enforced with an assertion.**
12347
12348 @since version 2.0.0
12349 */
12350 static void replace_substring(std::string& s, const std::string& f,
12351 const std::string& t)
12352 {
12353 JSON_ASSERT(!f.empty());
12354 for (auto pos = s.find(f); // find first occurrence of f
12355 pos != std::string::npos; // make sure f was found
12356 s.replace(pos, f.size(), t), // replace with t, and
12357 pos = s.find(f, pos + t.size())) // find next occurrence of f
12358 {}
12359 }
12360
12361 /// escape "~" to "~0" and "/" to "~1"
12362 static std::string escape(std::string s)
12363 {
12364 replace_substring(s, "~", "~0");
12365 replace_substring(s, "/", "~1");
12366 return s;
12367 }
12368
12369 /// unescape "~1" to tilde and "~0" to slash (order is important!)
12370 static void unescape(std::string& s)
12371 {
12372 replace_substring(s, "~1", "/");
12373 replace_substring(s, "~0", "~");
12374 }
12375
12376 /*!
12377 @param[in] reference_string the reference string to the current value
12378 @param[in] value the value to consider
12379 @param[in,out] result the result object to insert values to
12380
12381 @note Empty objects or arrays are flattened to `null`.
12382 */
12383 static void flatten(const std::string& reference_string,
12384 const BasicJsonType& value,
12385 BasicJsonType& result)
12386 {
12387 switch (value.type())
12388 {
12389 case detail::value_t::array:
12390 {
12391 if (value.m_value.array->empty())
12392 {
12393 // flatten empty array as null
12394 result[reference_string] = nullptr;
12395 }
12396 else
12397 {
12398 // iterate array and use index as reference string
12399 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12400 {
12401 flatten(reference_string + "/" + std::to_string(i),
12402 value.m_value.array->operator[](i), result);
12403 }
12404 }
12405 break;
12406 }
12407
12408 case detail::value_t::object:
12409 {
12410 if (value.m_value.object->empty())
12411 {
12412 // flatten empty object as null
12413 result[reference_string] = nullptr;
12414 }
12415 else
12416 {
12417 // iterate object and use keys as reference string
12418 for (const auto& element : *value.m_value.object)
12419 {
12420 flatten(reference_string + "/" + escape(element.first), element.second, result);
12421 }
12422 }
12423 break;
12424 }
12425
12426 default:
12427 {
12428 // add primitive value with its reference string
12429 result[reference_string] = value;
12430 break;
12431 }
12432 }
12433 }
12434
12435 /*!
12436 @param[in] value flattened JSON
12437
12438 @return unflattened JSON
12439
12440 @throw parse_error.109 if array index is not a number
12441 @throw type_error.314 if value is not an object
12442 @throw type_error.315 if object values are not primitive
12443 @throw type_error.313 if value cannot be unflattened
12444 */
12445 static BasicJsonType
12446 unflatten(const BasicJsonType& value)
12447 {
12448 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
12449 {
12450 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12451 }
12452
12453 BasicJsonType result;
12454
12455 // iterate the JSON object values
12456 for (const auto& element : *value.m_value.object)
12457 {
12458 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
12459 {
12460 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12461 }
12462
12463 // assign value to reference pointed to by JSON pointer; Note that if
12464 // the JSON pointer is "" (i.e., points to the whole value), function
12465 // get_and_create returns a reference to result itself. An assignment
12466 // will then create a primitive value.
12467 json_pointer(element.first).get_and_create(result) = element.second;
12468 }
12469
12470 return result;
12471 }
12472
12473 /*!
12474 @brief compares two JSON pointers for equality
12475
12476 @param[in] lhs JSON pointer to compare
12477 @param[in] rhs JSON pointer to compare
12478 @return whether @a lhs is equal to @a rhs
12479
12480 @complexity Linear in the length of the JSON pointer
12481
12482 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12483 */
12484 friend bool operator==(json_pointer const& lhs,
12485 json_pointer const& rhs) noexcept
12486 {
12487 return lhs.reference_tokens == rhs.reference_tokens;
12488 }
12489
12490 /*!
12491 @brief compares two JSON pointers for inequality
12492
12493 @param[in] lhs JSON pointer to compare
12494 @param[in] rhs JSON pointer to compare
12495 @return whether @a lhs is not equal @a rhs
12496
12497 @complexity Linear in the length of the JSON pointer
12498
12499 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12500 */
12501 friend bool operator!=(json_pointer const& lhs,
12502 json_pointer const& rhs) noexcept
12503 {
12504 return !(lhs == rhs);
12505 }
12506
12507 /// the reference tokens
12508 std::vector<std::string> reference_tokens;
12509 };
12510 } // namespace nlohmann
12511
12512 // #include <nlohmann/detail/json_ref.hpp>
12513
12514
12515 #include <initializer_list>
12516 #include <utility>
12517
12518 // #include <nlohmann/detail/meta/type_traits.hpp>
12519
12520
12521 namespace nlohmann
12522 {
12523 namespace detail
12524 {
12525 template<typename BasicJsonType>
12526 class json_ref
12527 {
12528 public:
12529 using value_type = BasicJsonType;
12530
12531 json_ref(value_type&& value)
12532 : owned_value(std::move(value))
12533 , value_ref(&owned_value)
12534 , is_rvalue(true)
12535 {}
12536
12537 json_ref(const value_type& value)
12538 : value_ref(const_cast<value_type*>(&value))
12539 , is_rvalue(false)
12540 {}
12541
12542 json_ref(std::initializer_list<json_ref> init)
12543 : owned_value(init)
12544 , value_ref(&owned_value)
12545 , is_rvalue(true)
12546 {}
12547
12548 template <
12549 class... Args,
12550 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
12551 json_ref(Args && ... args)
12552 : owned_value(std::forward<Args>(args)...)
12553 , value_ref(&owned_value)
12554 , is_rvalue(true)
12555 {}
12556
12557 // class should be movable only
12558 json_ref(json_ref&&) = default;
12559 json_ref(const json_ref&) = delete;
12560 json_ref& operator=(const json_ref&) = delete;
12561 json_ref& operator=(json_ref&&) = delete;
12562 ~json_ref() = default;
12563
12564 value_type moved_or_copied() const
12565 {
12566 if (is_rvalue)
12567 {
12568 return std::move(*value_ref);
12569 }
12570 return *value_ref;
12571 }
12572
12573 value_type const& operator*() const
12574 {
12575 return *static_cast<value_type const*>(value_ref);
12576 }
12577
12578 value_type const* operator->() const
12579 {
12580 return static_cast<value_type const*>(value_ref);
12581 }
12582
12583 private:
12584 mutable value_type owned_value = nullptr;
12585 value_type* value_ref = nullptr;
12586 const bool is_rvalue = true;
12587 };
12588 } // namespace detail
12589 } // namespace nlohmann
12590
12591 // #include <nlohmann/detail/macro_scope.hpp>
12592
12593 // #include <nlohmann/detail/meta/cpp_future.hpp>
12594
12595 // #include <nlohmann/detail/meta/type_traits.hpp>
617912596
618012597 // #include <nlohmann/detail/output/binary_writer.hpp>
618112598
618212599
618312600 #include <algorithm> // reverse
6184 #include <array> // array
6185 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6186 #include <cstring> // memcpy
6187 #include <limits> // numeric_limits
12601 #include <array> // array
12602 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
12603 #include <cstring> // memcpy
12604 #include <limits> // numeric_limits
12605 #include <string> // string
12606 #include <cmath> // isnan, isinf
618812607
618912608 // #include <nlohmann/detail/input/binary_reader.hpp>
619012609
12610 // #include <nlohmann/detail/macro_scope.hpp>
12611
619112612 // #include <nlohmann/detail/output/output_adapters.hpp>
12613
12614
12615 #include <algorithm> // copy
12616 #include <cstddef> // size_t
12617 #include <ios> // streamsize
12618 #include <iterator> // back_inserter
12619 #include <memory> // shared_ptr, make_shared
12620 #include <ostream> // basic_ostream
12621 #include <string> // basic_string
12622 #include <vector> // vector
12623 // #include <nlohmann/detail/macro_scope.hpp>
12624
12625
12626 namespace nlohmann
12627 {
12628 namespace detail
12629 {
12630 /// abstract output adapter interface
12631 template<typename CharType> struct output_adapter_protocol
12632 {
12633 virtual void write_character(CharType c) = 0;
12634 virtual void write_characters(const CharType* s, std::size_t length) = 0;
12635 virtual ~output_adapter_protocol() = default;
12636 };
12637
12638 /// a type to simplify interfaces
12639 template<typename CharType>
12640 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
12641
12642 /// output adapter for byte vectors
12643 template<typename CharType>
12644 class output_vector_adapter : public output_adapter_protocol<CharType>
12645 {
12646 public:
12647 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
12648 : v(vec)
12649 {}
12650
12651 void write_character(CharType c) override
12652 {
12653 v.push_back(c);
12654 }
12655
12656 JSON_HEDLEY_NON_NULL(2)
12657 void write_characters(const CharType* s, std::size_t length) override
12658 {
12659 std::copy(s, s + length, std::back_inserter(v));
12660 }
12661
12662 private:
12663 std::vector<CharType>& v;
12664 };
12665
12666 /// output adapter for output streams
12667 template<typename CharType>
12668 class output_stream_adapter : public output_adapter_protocol<CharType>
12669 {
12670 public:
12671 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
12672 : stream(s)
12673 {}
12674
12675 void write_character(CharType c) override
12676 {
12677 stream.put(c);
12678 }
12679
12680 JSON_HEDLEY_NON_NULL(2)
12681 void write_characters(const CharType* s, std::size_t length) override
12682 {
12683 stream.write(s, static_cast<std::streamsize>(length));
12684 }
12685
12686 private:
12687 std::basic_ostream<CharType>& stream;
12688 };
12689
12690 /// output adapter for basic_string
12691 template<typename CharType, typename StringType = std::basic_string<CharType>>
12692 class output_string_adapter : public output_adapter_protocol<CharType>
12693 {
12694 public:
12695 explicit output_string_adapter(StringType& s) noexcept
12696 : str(s)
12697 {}
12698
12699 void write_character(CharType c) override
12700 {
12701 str.push_back(c);
12702 }
12703
12704 JSON_HEDLEY_NON_NULL(2)
12705 void write_characters(const CharType* s, std::size_t length) override
12706 {
12707 str.append(s, length);
12708 }
12709
12710 private:
12711 StringType& str;
12712 };
12713
12714 template<typename CharType, typename StringType = std::basic_string<CharType>>
12715 class output_adapter
12716 {
12717 public:
12718 output_adapter(std::vector<CharType>& vec)
12719 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
12720
12721 output_adapter(std::basic_ostream<CharType>& s)
12722 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
12723
12724 output_adapter(StringType& s)
12725 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
12726
12727 operator output_adapter_t<CharType>()
12728 {
12729 return oa;
12730 }
12731
12732 private:
12733 output_adapter_t<CharType> oa = nullptr;
12734 };
12735 } // namespace detail
12736 } // namespace nlohmann
619212737
619312738
619412739 namespace nlohmann
620212747 /*!
620312748 @brief serialization to CBOR and MessagePack values
620412749 */
6205 template <typename BasicJsonType, typename CharType>
12750 template<typename BasicJsonType, typename CharType>
620612751 class binary_writer
620712752 {
6208 public:
12753 using string_t = typename BasicJsonType::string_t;
12754 using binary_t = typename BasicJsonType::binary_t;
12755 using number_float_t = typename BasicJsonType::number_float_t;
12756
12757 public:
620912758 /*!
621012759 @brief create a binary writer
621112760
621312762 */
621412763 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
621512764 {
6216 assert(oa);
6217 }
6218
6219 /*!
6220 @brief[in] j JSON value to serialize
12765 JSON_ASSERT(oa);
12766 }
12767
12768 /*!
12769 @param[in] j JSON value to serialize
12770 @pre j.type() == value_t::object
12771 */
12772 void write_bson(const BasicJsonType& j)
12773 {
12774 switch (j.type())
12775 {
12776 case value_t::object:
12777 {
12778 write_bson_object(*j.m_value.object);
12779 break;
12780 }
12781
12782 default:
12783 {
12784 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
12785 }
12786 }
12787 }
12788
12789 /*!
12790 @param[in] j JSON value to serialize
622112791 */
622212792 void write_cbor(const BasicJsonType& j)
622312793 {
622512795 {
622612796 case value_t::null:
622712797 {
6228 oa->write_character(static_cast<CharType>(0xF6));
12798 oa->write_character(to_char_type(0xF6));
622912799 break;
623012800 }
623112801
623212802 case value_t::boolean:
623312803 {
6234 oa->write_character(j.m_value.boolean ? static_cast<CharType>(0xF5) : static_cast<CharType>(0xF4));
12804 oa->write_character(j.m_value.boolean
12805 ? to_char_type(0xF5)
12806 : to_char_type(0xF4));
623512807 break;
623612808 }
623712809
624412816 // code from the value_t::number_unsigned case here.
624512817 if (j.m_value.number_integer <= 0x17)
624612818 {
6247 write_number(static_cast<uint8_t>(j.m_value.number_integer));
12819 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
624812820 }
6249 else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
12821 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
625012822 {
6251 oa->write_character(static_cast<CharType>(0x18));
6252 write_number(static_cast<uint8_t>(j.m_value.number_integer));
12823 oa->write_character(to_char_type(0x18));
12824 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
625312825 }
6254 else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
12826 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
625512827 {
6256 oa->write_character(static_cast<CharType>(0x19));
6257 write_number(static_cast<uint16_t>(j.m_value.number_integer));
12828 oa->write_character(to_char_type(0x19));
12829 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
625812830 }
6259 else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
12831 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
626012832 {
6261 oa->write_character(static_cast<CharType>(0x1A));
6262 write_number(static_cast<uint32_t>(j.m_value.number_integer));
12833 oa->write_character(to_char_type(0x1A));
12834 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
626312835 }
626412836 else
626512837 {
6266 oa->write_character(static_cast<CharType>(0x1B));
6267 write_number(static_cast<uint64_t>(j.m_value.number_integer));
12838 oa->write_character(to_char_type(0x1B));
12839 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
626812840 }
626912841 }
627012842 else
627412846 const auto positive_number = -1 - j.m_value.number_integer;
627512847 if (j.m_value.number_integer >= -24)
627612848 {
6277 write_number(static_cast<uint8_t>(0x20 + positive_number));
12849 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
627812850 }
6279 else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
12851 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
628012852 {
6281 oa->write_character(static_cast<CharType>(0x38));
6282 write_number(static_cast<uint8_t>(positive_number));
12853 oa->write_character(to_char_type(0x38));
12854 write_number(static_cast<std::uint8_t>(positive_number));
628312855 }
6284 else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
12856 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
628512857 {
6286 oa->write_character(static_cast<CharType>(0x39));
6287 write_number(static_cast<uint16_t>(positive_number));
12858 oa->write_character(to_char_type(0x39));
12859 write_number(static_cast<std::uint16_t>(positive_number));
628812860 }
6289 else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
12861 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
629012862 {
6291 oa->write_character(static_cast<CharType>(0x3A));
6292 write_number(static_cast<uint32_t>(positive_number));
12863 oa->write_character(to_char_type(0x3A));
12864 write_number(static_cast<std::uint32_t>(positive_number));
629312865 }
629412866 else
629512867 {
6296 oa->write_character(static_cast<CharType>(0x3B));
6297 write_number(static_cast<uint64_t>(positive_number));
12868 oa->write_character(to_char_type(0x3B));
12869 write_number(static_cast<std::uint64_t>(positive_number));
629812870 }
629912871 }
630012872 break;
630412876 {
630512877 if (j.m_value.number_unsigned <= 0x17)
630612878 {
6307 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
12879 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
630812880 }
6309 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
12881 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
631012882 {
6311 oa->write_character(static_cast<CharType>(0x18));
6312 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
12883 oa->write_character(to_char_type(0x18));
12884 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
631312885 }
6314 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
12886 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
631512887 {
6316 oa->write_character(static_cast<CharType>(0x19));
6317 write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
12888 oa->write_character(to_char_type(0x19));
12889 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
631812890 }
6319 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
12891 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
632012892 {
6321 oa->write_character(static_cast<CharType>(0x1A));
6322 write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
12893 oa->write_character(to_char_type(0x1A));
12894 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
632312895 }
632412896 else
632512897 {
6326 oa->write_character(static_cast<CharType>(0x1B));
6327 write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
12898 oa->write_character(to_char_type(0x1B));
12899 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
632812900 }
632912901 break;
633012902 }
633112903
6332 case value_t::number_float: // Double-Precision Float
6333 {
6334 oa->write_character(static_cast<CharType>(0xFB));
6335 write_number(j.m_value.number_float);
12904 case value_t::number_float:
12905 {
12906 if (std::isnan(j.m_value.number_float))
12907 {
12908 // NaN is 0xf97e00 in CBOR
12909 oa->write_character(to_char_type(0xF9));
12910 oa->write_character(to_char_type(0x7E));
12911 oa->write_character(to_char_type(0x00));
12912 }
12913 else if (std::isinf(j.m_value.number_float))
12914 {
12915 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
12916 oa->write_character(to_char_type(0xf9));
12917 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
12918 oa->write_character(to_char_type(0x00));
12919 }
12920 else
12921 {
12922 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
12923 }
633612924 break;
633712925 }
633812926
634212930 const auto N = j.m_value.string->size();
634312931 if (N <= 0x17)
634412932 {
6345 write_number(static_cast<uint8_t>(0x60 + N));
12933 write_number(static_cast<std::uint8_t>(0x60 + N));
634612934 }
6347 else if (N <= (std::numeric_limits<uint8_t>::max)())
12935 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
634812936 {
6349 oa->write_character(static_cast<CharType>(0x78));
6350 write_number(static_cast<uint8_t>(N));
12937 oa->write_character(to_char_type(0x78));
12938 write_number(static_cast<std::uint8_t>(N));
635112939 }
6352 else if (N <= (std::numeric_limits<uint16_t>::max)())
12940 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
635312941 {
6354 oa->write_character(static_cast<CharType>(0x79));
6355 write_number(static_cast<uint16_t>(N));
12942 oa->write_character(to_char_type(0x79));
12943 write_number(static_cast<std::uint16_t>(N));
635612944 }
6357 else if (N <= (std::numeric_limits<uint32_t>::max)())
12945 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
635812946 {
6359 oa->write_character(static_cast<CharType>(0x7A));
6360 write_number(static_cast<uint32_t>(N));
12947 oa->write_character(to_char_type(0x7A));
12948 write_number(static_cast<std::uint32_t>(N));
636112949 }
636212950 // LCOV_EXCL_START
6363 else if (N <= (std::numeric_limits<uint64_t>::max)())
12951 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
636412952 {
6365 oa->write_character(static_cast<CharType>(0x7B));
6366 write_number(static_cast<uint64_t>(N));
12953 oa->write_character(to_char_type(0x7B));
12954 write_number(static_cast<std::uint64_t>(N));
636712955 }
636812956 // LCOV_EXCL_STOP
636912957
637012958 // step 2: write the string
6371 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()), j.m_value.string->size());
12959 oa->write_characters(
12960 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
12961 j.m_value.string->size());
637212962 break;
637312963 }
637412964
637812968 const auto N = j.m_value.array->size();
637912969 if (N <= 0x17)
638012970 {
6381 write_number(static_cast<uint8_t>(0x80 + N));
12971 write_number(static_cast<std::uint8_t>(0x80 + N));
638212972 }
6383 else if (N <= (std::numeric_limits<uint8_t>::max)())
12973 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
638412974 {
6385 oa->write_character(static_cast<CharType>(0x98));
6386 write_number(static_cast<uint8_t>(N));
12975 oa->write_character(to_char_type(0x98));
12976 write_number(static_cast<std::uint8_t>(N));
638712977 }
6388 else if (N <= (std::numeric_limits<uint16_t>::max)())
12978 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
638912979 {
6390 oa->write_character(static_cast<CharType>(0x99));
6391 write_number(static_cast<uint16_t>(N));
12980 oa->write_character(to_char_type(0x99));
12981 write_number(static_cast<std::uint16_t>(N));
639212982 }
6393 else if (N <= (std::numeric_limits<uint32_t>::max)())
12983 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
639412984 {
6395 oa->write_character(static_cast<CharType>(0x9A));
6396 write_number(static_cast<uint32_t>(N));
12985 oa->write_character(to_char_type(0x9A));
12986 write_number(static_cast<std::uint32_t>(N));
639712987 }
639812988 // LCOV_EXCL_START
6399 else if (N <= (std::numeric_limits<uint64_t>::max)())
12989 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
640012990 {
6401 oa->write_character(static_cast<CharType>(0x9B));
6402 write_number(static_cast<uint64_t>(N));
12991 oa->write_character(to_char_type(0x9B));
12992 write_number(static_cast<std::uint64_t>(N));
640312993 }
640412994 // LCOV_EXCL_STOP
640512995
641113001 break;
641213002 }
641313003
13004 case value_t::binary:
13005 {
13006 if (j.m_value.binary->has_subtype())
13007 {
13008 write_number(static_cast<std::uint8_t>(0xd8));
13009 write_number(j.m_value.binary->subtype());
13010 }
13011
13012 // step 1: write control byte and the binary array size
13013 const auto N = j.m_value.binary->size();
13014 if (N <= 0x17)
13015 {
13016 write_number(static_cast<std::uint8_t>(0x40 + N));
13017 }
13018 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13019 {
13020 oa->write_character(to_char_type(0x58));
13021 write_number(static_cast<std::uint8_t>(N));
13022 }
13023 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13024 {
13025 oa->write_character(to_char_type(0x59));
13026 write_number(static_cast<std::uint16_t>(N));
13027 }
13028 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13029 {
13030 oa->write_character(to_char_type(0x5A));
13031 write_number(static_cast<std::uint32_t>(N));
13032 }
13033 // LCOV_EXCL_START
13034 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13035 {
13036 oa->write_character(to_char_type(0x5B));
13037 write_number(static_cast<std::uint64_t>(N));
13038 }
13039 // LCOV_EXCL_STOP
13040
13041 // step 2: write each element
13042 oa->write_characters(
13043 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13044 N);
13045
13046 break;
13047 }
13048
641413049 case value_t::object:
641513050 {
641613051 // step 1: write control byte and the object size
641713052 const auto N = j.m_value.object->size();
641813053 if (N <= 0x17)
641913054 {
6420 write_number(static_cast<uint8_t>(0xA0 + N));
13055 write_number(static_cast<std::uint8_t>(0xA0 + N));
642113056 }
6422 else if (N <= (std::numeric_limits<uint8_t>::max)())
13057 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
642313058 {
6424 oa->write_character(static_cast<CharType>(0xB8));
6425 write_number(static_cast<uint8_t>(N));
13059 oa->write_character(to_char_type(0xB8));
13060 write_number(static_cast<std::uint8_t>(N));
642613061 }
6427 else if (N <= (std::numeric_limits<uint16_t>::max)())
13062 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
642813063 {
6429 oa->write_character(static_cast<CharType>(0xB9));
6430 write_number(static_cast<uint16_t>(N));
13064 oa->write_character(to_char_type(0xB9));
13065 write_number(static_cast<std::uint16_t>(N));
643113066 }
6432 else if (N <= (std::numeric_limits<uint32_t>::max)())
13067 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
643313068 {
6434 oa->write_character(static_cast<CharType>(0xBA));
6435 write_number(static_cast<uint32_t>(N));
13069 oa->write_character(to_char_type(0xBA));
13070 write_number(static_cast<std::uint32_t>(N));
643613071 }
643713072 // LCOV_EXCL_START
6438 else if (N <= (std::numeric_limits<uint64_t>::max)())
13073 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
643913074 {
6440 oa->write_character(static_cast<CharType>(0xBB));
6441 write_number(static_cast<uint64_t>(N));
13075 oa->write_character(to_char_type(0xBB));
13076 write_number(static_cast<std::uint64_t>(N));
644213077 }
644313078 // LCOV_EXCL_STOP
644413079
645713092 }
645813093
645913094 /*!
6460 @brief[in] j JSON value to serialize
13095 @param[in] j JSON value to serialize
646113096 */
646213097 void write_msgpack(const BasicJsonType& j)
646313098 {
646513100 {
646613101 case value_t::null: // nil
646713102 {
6468 oa->write_character(static_cast<CharType>(0xC0));
13103 oa->write_character(to_char_type(0xC0));
646913104 break;
647013105 }
647113106
647213107 case value_t::boolean: // true and false
647313108 {
6474 oa->write_character(j.m_value.boolean ? static_cast<CharType>(0xC3) : static_cast<CharType>(0xC2));
13109 oa->write_character(j.m_value.boolean
13110 ? to_char_type(0xC3)
13111 : to_char_type(0xC2));
647513112 break;
647613113 }
647713114
648513122 if (j.m_value.number_unsigned < 128)
648613123 {
648713124 // positive fixnum
6488 write_number(static_cast<uint8_t>(j.m_value.number_integer));
13125 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
648913126 }
6490 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
13127 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
649113128 {
649213129 // uint 8
6493 oa->write_character(static_cast<CharType>(0xCC));
6494 write_number(static_cast<uint8_t>(j.m_value.number_integer));
13130 oa->write_character(to_char_type(0xCC));
13131 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
649513132 }
6496 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
13133 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
649713134 {
649813135 // uint 16
6499 oa->write_character(static_cast<CharType>(0xCD));
6500 write_number(static_cast<uint16_t>(j.m_value.number_integer));
13136 oa->write_character(to_char_type(0xCD));
13137 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
650113138 }
6502 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
13139 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
650313140 {
650413141 // uint 32
6505 oa->write_character(static_cast<CharType>(0xCE));
6506 write_number(static_cast<uint32_t>(j.m_value.number_integer));
13142 oa->write_character(to_char_type(0xCE));
13143 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
650713144 }
6508 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
13145 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
650913146 {
651013147 // uint 64
6511 oa->write_character(static_cast<CharType>(0xCF));
6512 write_number(static_cast<uint64_t>(j.m_value.number_integer));
13148 oa->write_character(to_char_type(0xCF));
13149 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
651313150 }
651413151 }
651513152 else
651713154 if (j.m_value.number_integer >= -32)
651813155 {
651913156 // negative fixnum
6520 write_number(static_cast<int8_t>(j.m_value.number_integer));
13157 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
652113158 }
6522 else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
6523 j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
13159 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13160 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
652413161 {
652513162 // int 8
6526 oa->write_character(static_cast<CharType>(0xD0));
6527 write_number(static_cast<int8_t>(j.m_value.number_integer));
13163 oa->write_character(to_char_type(0xD0));
13164 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
652813165 }
6529 else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
6530 j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
13166 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13167 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
653113168 {
653213169 // int 16
6533 oa->write_character(static_cast<CharType>(0xD1));
6534 write_number(static_cast<int16_t>(j.m_value.number_integer));
13170 oa->write_character(to_char_type(0xD1));
13171 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
653513172 }
6536 else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
6537 j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
13173 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13174 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
653813175 {
653913176 // int 32
6540 oa->write_character(static_cast<CharType>(0xD2));
6541 write_number(static_cast<int32_t>(j.m_value.number_integer));
13177 oa->write_character(to_char_type(0xD2));
13178 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
654213179 }
6543 else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
6544 j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
13180 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13181 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
654513182 {
654613183 // int 64
6547 oa->write_character(static_cast<CharType>(0xD3));
6548 write_number(static_cast<int64_t>(j.m_value.number_integer));
13184 oa->write_character(to_char_type(0xD3));
13185 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
654913186 }
655013187 }
655113188 break;
655613193 if (j.m_value.number_unsigned < 128)
655713194 {
655813195 // positive fixnum
6559 write_number(static_cast<uint8_t>(j.m_value.number_integer));
13196 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
656013197 }
6561 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
13198 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
656213199 {
656313200 // uint 8
6564 oa->write_character(static_cast<CharType>(0xCC));
6565 write_number(static_cast<uint8_t>(j.m_value.number_integer));
13201 oa->write_character(to_char_type(0xCC));
13202 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
656613203 }
6567 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
13204 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
656813205 {
656913206 // uint 16
6570 oa->write_character(static_cast<CharType>(0xCD));
6571 write_number(static_cast<uint16_t>(j.m_value.number_integer));
13207 oa->write_character(to_char_type(0xCD));
13208 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
657213209 }
6573 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
13210 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
657413211 {
657513212 // uint 32
6576 oa->write_character(static_cast<CharType>(0xCE));
6577 write_number(static_cast<uint32_t>(j.m_value.number_integer));
13213 oa->write_character(to_char_type(0xCE));
13214 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
657813215 }
6579 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
13216 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
658013217 {
658113218 // uint 64
6582 oa->write_character(static_cast<CharType>(0xCF));
6583 write_number(static_cast<uint64_t>(j.m_value.number_integer));
13219 oa->write_character(to_char_type(0xCF));
13220 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
658413221 }
658513222 break;
658613223 }
658713224
6588 case value_t::number_float: // float 64
6589 {
6590 oa->write_character(static_cast<CharType>(0xCB));
6591 write_number(j.m_value.number_float);
13225 case value_t::number_float:
13226 {
13227 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
659213228 break;
659313229 }
659413230
659913235 if (N <= 31)
660013236 {
660113237 // fixstr
6602 write_number(static_cast<uint8_t>(0xA0 | N));
13238 write_number(static_cast<std::uint8_t>(0xA0 | N));
660313239 }
6604 else if (N <= (std::numeric_limits<uint8_t>::max)())
13240 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
660513241 {
660613242 // str 8
6607 oa->write_character(static_cast<CharType>(0xD9));
6608 write_number(static_cast<uint8_t>(N));
13243 oa->write_character(to_char_type(0xD9));
13244 write_number(static_cast<std::uint8_t>(N));
660913245 }
6610 else if (N <= (std::numeric_limits<uint16_t>::max)())
13246 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
661113247 {
661213248 // str 16
6613 oa->write_character(static_cast<CharType>(0xDA));
6614 write_number(static_cast<uint16_t>(N));
13249 oa->write_character(to_char_type(0xDA));
13250 write_number(static_cast<std::uint16_t>(N));
661513251 }
6616 else if (N <= (std::numeric_limits<uint32_t>::max)())
13252 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
661713253 {
661813254 // str 32
6619 oa->write_character(static_cast<CharType>(0xDB));
6620 write_number(static_cast<uint32_t>(N));
13255 oa->write_character(to_char_type(0xDB));
13256 write_number(static_cast<std::uint32_t>(N));
662113257 }
662213258
662313259 // step 2: write the string
6624 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()), j.m_value.string->size());
13260 oa->write_characters(
13261 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13262 j.m_value.string->size());
662513263 break;
662613264 }
662713265
663213270 if (N <= 15)
663313271 {
663413272 // fixarray
6635 write_number(static_cast<uint8_t>(0x90 | N));
13273 write_number(static_cast<std::uint8_t>(0x90 | N));
663613274 }
6637 else if (N <= (std::numeric_limits<uint16_t>::max)())
13275 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
663813276 {
663913277 // array 16
6640 oa->write_character(static_cast<CharType>(0xDC));
6641 write_number(static_cast<uint16_t>(N));
13278 oa->write_character(to_char_type(0xDC));
13279 write_number(static_cast<std::uint16_t>(N));
664213280 }
6643 else if (N <= (std::numeric_limits<uint32_t>::max)())
13281 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
664413282 {
664513283 // array 32
6646 oa->write_character(static_cast<CharType>(0xDD));
6647 write_number(static_cast<uint32_t>(N));
13284 oa->write_character(to_char_type(0xDD));
13285 write_number(static_cast<std::uint32_t>(N));
664813286 }
664913287
665013288 // step 2: write each element
665513293 break;
665613294 }
665713295
13296 case value_t::binary:
13297 {
13298 // step 0: determine if the binary type has a set subtype to
13299 // determine whether or not to use the ext or fixext types
13300 const bool use_ext = j.m_value.binary->has_subtype();
13301
13302 // step 1: write control byte and the byte string length
13303 const auto N = j.m_value.binary->size();
13304 if (N <= (std::numeric_limits<std::uint8_t>::max)())
13305 {
13306 std::uint8_t output_type{};
13307 bool fixed = true;
13308 if (use_ext)
13309 {
13310 switch (N)
13311 {
13312 case 1:
13313 output_type = 0xD4; // fixext 1
13314 break;
13315 case 2:
13316 output_type = 0xD5; // fixext 2
13317 break;
13318 case 4:
13319 output_type = 0xD6; // fixext 4
13320 break;
13321 case 8:
13322 output_type = 0xD7; // fixext 8
13323 break;
13324 case 16:
13325 output_type = 0xD8; // fixext 16
13326 break;
13327 default:
13328 output_type = 0xC7; // ext 8
13329 fixed = false;
13330 break;
13331 }
13332
13333 }
13334 else
13335 {
13336 output_type = 0xC4; // bin 8
13337 fixed = false;
13338 }
13339
13340 oa->write_character(to_char_type(output_type));
13341 if (!fixed)
13342 {
13343 write_number(static_cast<std::uint8_t>(N));
13344 }
13345 }
13346 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13347 {
13348 std::uint8_t output_type = use_ext
13349 ? 0xC8 // ext 16
13350 : 0xC5; // bin 16
13351
13352 oa->write_character(to_char_type(output_type));
13353 write_number(static_cast<std::uint16_t>(N));
13354 }
13355 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13356 {
13357 std::uint8_t output_type = use_ext
13358 ? 0xC9 // ext 32
13359 : 0xC6; // bin 32
13360
13361 oa->write_character(to_char_type(output_type));
13362 write_number(static_cast<std::uint32_t>(N));
13363 }
13364
13365 // step 1.5: if this is an ext type, write the subtype
13366 if (use_ext)
13367 {
13368 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13369 }
13370
13371 // step 2: write the byte string
13372 oa->write_characters(
13373 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13374 N);
13375
13376 break;
13377 }
13378
665813379 case value_t::object:
665913380 {
666013381 // step 1: write control byte and the object size
666213383 if (N <= 15)
666313384 {
666413385 // fixmap
6665 write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
13386 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
666613387 }
6667 else if (N <= (std::numeric_limits<uint16_t>::max)())
13388 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
666813389 {
666913390 // map 16
6670 oa->write_character(static_cast<CharType>(0xDE));
6671 write_number(static_cast<uint16_t>(N));
13391 oa->write_character(to_char_type(0xDE));
13392 write_number(static_cast<std::uint16_t>(N));
667213393 }
6673 else if (N <= (std::numeric_limits<uint32_t>::max)())
13394 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
667413395 {
667513396 // map 32
6676 oa->write_character(static_cast<CharType>(0xDF));
6677 write_number(static_cast<uint32_t>(N));
13397 oa->write_character(to_char_type(0xDF));
13398 write_number(static_cast<std::uint32_t>(N));
667813399 }
667913400
668013401 // step 2: write each element
669713418 @param[in] use_type whether to use '$' prefixes (optimized format)
669813419 @param[in] add_prefix whether prefixes need to be used for this value
669913420 */
6700 void write_ubjson(const BasicJsonType& j, const bool use_count, const bool use_type, const bool add_prefix = true)
13421 void write_ubjson(const BasicJsonType& j, const bool use_count,
13422 const bool use_type, const bool add_prefix = true)
670113423 {
670213424 switch (j.type())
670313425 {
670513427 {
670613428 if (add_prefix)
670713429 {
6708 oa->write_character(static_cast<CharType>('Z'));
13430 oa->write_character(to_char_type('Z'));
670913431 }
671013432 break;
671113433 }
671313435 case value_t::boolean:
671413436 {
671513437 if (add_prefix)
6716 oa->write_character(j.m_value.boolean ? static_cast<CharType>('T') : static_cast<CharType>('F'));
13438 {
13439 oa->write_character(j.m_value.boolean
13440 ? to_char_type('T')
13441 : to_char_type('F'));
13442 }
671713443 break;
671813444 }
671913445
673913465 {
674013466 if (add_prefix)
674113467 {
6742 oa->write_character(static_cast<CharType>('S'));
13468 oa->write_character(to_char_type('S'));
674313469 }
674413470 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
6745 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()), j.m_value.string->size());
13471 oa->write_characters(
13472 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13473 j.m_value.string->size());
674613474 break;
674713475 }
674813476
675013478 {
675113479 if (add_prefix)
675213480 {
6753 oa->write_character(static_cast<CharType>('['));
13481 oa->write_character(to_char_type('['));
675413482 }
675513483
675613484 bool prefix_required = true;
6757 if (use_type and not j.m_value.array->empty())
13485 if (use_type && !j.m_value.array->empty())
675813486 {
6759 assert(use_count);
6760 const char first_prefix = ubjson_prefix(j.front());
6761 const bool same_prefix =
6762 std::all_of(j.begin() + 1, j.end(), [this, first_prefix](const BasicJsonType& v) { return ubjson_prefix(v) == first_prefix; });
13487 JSON_ASSERT(use_count);
13488 const CharType first_prefix = ubjson_prefix(j.front());
13489 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
13490 [this, first_prefix](const BasicJsonType & v)
13491 {
13492 return ubjson_prefix(v) == first_prefix;
13493 });
676313494
676413495 if (same_prefix)
676513496 {
676613497 prefix_required = false;
6767 oa->write_character(static_cast<CharType>('$'));
6768 oa->write_character(static_cast<CharType>(first_prefix));
13498 oa->write_character(to_char_type('$'));
13499 oa->write_character(first_prefix);
676913500 }
677013501 }
677113502
677213503 if (use_count)
677313504 {
6774 oa->write_character(static_cast<CharType>('#'));
13505 oa->write_character(to_char_type('#'));
677513506 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
677613507 }
677713508
678013511 write_ubjson(el, use_count, use_type, prefix_required);
678113512 }
678213513
6783 if (not use_count)
13514 if (!use_count)
678413515 {
6785 oa->write_character(static_cast<CharType>(']'));
13516 oa->write_character(to_char_type(']'));
678613517 }
678713518
678813519 break;
678913520 }
679013521
6791 case value_t::object:
13522 case value_t::binary:
679213523 {
679313524 if (add_prefix)
679413525 {
6795 oa->write_character(static_cast<CharType>('{'));
13526 oa->write_character(to_char_type('['));
679613527 }
679713528
13529 if (use_type && !j.m_value.binary->empty())
13530 {
13531 JSON_ASSERT(use_count);
13532 oa->write_character(to_char_type('$'));
13533 oa->write_character('U');
13534 }
13535
13536 if (use_count)
13537 {
13538 oa->write_character(to_char_type('#'));
13539 write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
13540 }
13541
13542 if (use_type)
13543 {
13544 oa->write_characters(
13545 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13546 j.m_value.binary->size());
13547 }
13548 else
13549 {
13550 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
13551 {
13552 oa->write_character(to_char_type('U'));
13553 oa->write_character(j.m_value.binary->data()[i]);
13554 }
13555 }
13556
13557 if (!use_count)
13558 {
13559 oa->write_character(to_char_type(']'));
13560 }
13561
13562 break;
13563 }
13564
13565 case value_t::object:
13566 {
13567 if (add_prefix)
13568 {
13569 oa->write_character(to_char_type('{'));
13570 }
13571
679813572 bool prefix_required = true;
6799 if (use_type and not j.m_value.object->empty())
13573 if (use_type && !j.m_value.object->empty())
680013574 {
6801 assert(use_count);
6802 const char first_prefix = ubjson_prefix(j.front());
6803 const bool same_prefix =
6804 std::all_of(j.begin(), j.end(), [this, first_prefix](const BasicJsonType& v) { return ubjson_prefix(v) == first_prefix; });
13575 JSON_ASSERT(use_count);
13576 const CharType first_prefix = ubjson_prefix(j.front());
13577 const bool same_prefix = std::all_of(j.begin(), j.end(),
13578 [this, first_prefix](const BasicJsonType & v)
13579 {
13580 return ubjson_prefix(v) == first_prefix;
13581 });
680513582
680613583 if (same_prefix)
680713584 {
680813585 prefix_required = false;
6809 oa->write_character(static_cast<CharType>('$'));
6810 oa->write_character(static_cast<CharType>(first_prefix));
13586 oa->write_character(to_char_type('$'));
13587 oa->write_character(first_prefix);
681113588 }
681213589 }
681313590
681413591 if (use_count)
681513592 {
6816 oa->write_character(static_cast<CharType>('#'));
13593 oa->write_character(to_char_type('#'));
681713594 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
681813595 }
681913596
682013597 for (const auto& el : *j.m_value.object)
682113598 {
682213599 write_number_with_ubjson_prefix(el.first.size(), true);
6823 oa->write_characters(reinterpret_cast<const CharType*>(el.first.c_str()), el.first.size());
13600 oa->write_characters(
13601 reinterpret_cast<const CharType*>(el.first.c_str()),
13602 el.first.size());
682413603 write_ubjson(el.second, use_count, use_type, prefix_required);
682513604 }
682613605
6827 if (not use_count)
13606 if (!use_count)
682813607 {
6829 oa->write_character(static_cast<CharType>('}'));
13608 oa->write_character(to_char_type('}'));
683013609 }
683113610
683213611 break;
683713616 }
683813617 }
683913618
6840 private:
13619 private:
13620 //////////
13621 // BSON //
13622 //////////
13623
13624 /*!
13625 @return The size of a BSON document entry header, including the id marker
13626 and the entry name size (and its null-terminator).
13627 */
13628 static std::size_t calc_bson_entry_header_size(const string_t& name)
13629 {
13630 const auto it = name.find(static_cast<typename string_t::value_type>(0));
13631 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
13632 {
13633 JSON_THROW(out_of_range::create(409,
13634 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
13635 }
13636
13637 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
13638 }
13639
13640 /*!
13641 @brief Writes the given @a element_type and @a name to the output adapter
13642 */
13643 void write_bson_entry_header(const string_t& name,
13644 const std::uint8_t element_type)
13645 {
13646 oa->write_character(to_char_type(element_type)); // boolean
13647 oa->write_characters(
13648 reinterpret_cast<const CharType*>(name.c_str()),
13649 name.size() + 1u);
13650 }
13651
13652 /*!
13653 @brief Writes a BSON element with key @a name and boolean value @a value
13654 */
13655 void write_bson_boolean(const string_t& name,
13656 const bool value)
13657 {
13658 write_bson_entry_header(name, 0x08);
13659 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
13660 }
13661
13662 /*!
13663 @brief Writes a BSON element with key @a name and double value @a value
13664 */
13665 void write_bson_double(const string_t& name,
13666 const double value)
13667 {
13668 write_bson_entry_header(name, 0x01);
13669 write_number<double, true>(value);
13670 }
13671
13672 /*!
13673 @return The size of the BSON-encoded string in @a value
13674 */
13675 static std::size_t calc_bson_string_size(const string_t& value)
13676 {
13677 return sizeof(std::int32_t) + value.size() + 1ul;
13678 }
13679
13680 /*!
13681 @brief Writes a BSON element with key @a name and string value @a value
13682 */
13683 void write_bson_string(const string_t& name,
13684 const string_t& value)
13685 {
13686 write_bson_entry_header(name, 0x02);
13687
13688 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
13689 oa->write_characters(
13690 reinterpret_cast<const CharType*>(value.c_str()),
13691 value.size() + 1);
13692 }
13693
13694 /*!
13695 @brief Writes a BSON element with key @a name and null value
13696 */
13697 void write_bson_null(const string_t& name)
13698 {
13699 write_bson_entry_header(name, 0x0A);
13700 }
13701
13702 /*!
13703 @return The size of the BSON-encoded integer @a value
13704 */
13705 static std::size_t calc_bson_integer_size(const std::int64_t value)
13706 {
13707 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
13708 ? sizeof(std::int32_t)
13709 : sizeof(std::int64_t);
13710 }
13711
13712 /*!
13713 @brief Writes a BSON element with key @a name and integer @a value
13714 */
13715 void write_bson_integer(const string_t& name,
13716 const std::int64_t value)
13717 {
13718 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
13719 {
13720 write_bson_entry_header(name, 0x10); // int32
13721 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13722 }
13723 else
13724 {
13725 write_bson_entry_header(name, 0x12); // int64
13726 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13727 }
13728 }
13729
13730 /*!
13731 @return The size of the BSON-encoded unsigned integer in @a j
13732 */
13733 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
13734 {
13735 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13736 ? sizeof(std::int32_t)
13737 : sizeof(std::int64_t);
13738 }
13739
13740 /*!
13741 @brief Writes a BSON element with key @a name and unsigned @a value
13742 */
13743 void write_bson_unsigned(const string_t& name,
13744 const std::uint64_t value)
13745 {
13746 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13747 {
13748 write_bson_entry_header(name, 0x10 /* int32 */);
13749 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13750 }
13751 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
13752 {
13753 write_bson_entry_header(name, 0x12 /* int64 */);
13754 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13755 }
13756 else
13757 {
13758 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
13759 }
13760 }
13761
13762 /*!
13763 @brief Writes a BSON element with key @a name and object @a value
13764 */
13765 void write_bson_object_entry(const string_t& name,
13766 const typename BasicJsonType::object_t& value)
13767 {
13768 write_bson_entry_header(name, 0x03); // object
13769 write_bson_object(value);
13770 }
13771
13772 /*!
13773 @return The size of the BSON-encoded array @a value
13774 */
13775 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
13776 {
13777 std::size_t array_index = 0ul;
13778
13779 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
13780 {
13781 return result + calc_bson_element_size(std::to_string(array_index++), el);
13782 });
13783
13784 return sizeof(std::int32_t) + embedded_document_size + 1ul;
13785 }
13786
13787 /*!
13788 @return The size of the BSON-encoded binary array @a value
13789 */
13790 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
13791 {
13792 return sizeof(std::int32_t) + value.size() + 1ul;
13793 }
13794
13795 /*!
13796 @brief Writes a BSON element with key @a name and array @a value
13797 */
13798 void write_bson_array(const string_t& name,
13799 const typename BasicJsonType::array_t& value)
13800 {
13801 write_bson_entry_header(name, 0x04); // array
13802 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
13803
13804 std::size_t array_index = 0ul;
13805
13806 for (const auto& el : value)
13807 {
13808 write_bson_element(std::to_string(array_index++), el);
13809 }
13810
13811 oa->write_character(to_char_type(0x00));
13812 }
13813
13814 /*!
13815 @brief Writes a BSON element with key @a name and binary value @a value
13816 */
13817 void write_bson_binary(const string_t& name,
13818 const binary_t& value)
13819 {
13820 write_bson_entry_header(name, 0x05);
13821
13822 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
13823 write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
13824
13825 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
13826 }
13827
13828 /*!
13829 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
13830 @return The calculated size for the BSON document entry for @a j with the given @a name.
13831 */
13832 static std::size_t calc_bson_element_size(const string_t& name,
13833 const BasicJsonType& j)
13834 {
13835 const auto header_size = calc_bson_entry_header_size(name);
13836 switch (j.type())
13837 {
13838 case value_t::object:
13839 return header_size + calc_bson_object_size(*j.m_value.object);
13840
13841 case value_t::array:
13842 return header_size + calc_bson_array_size(*j.m_value.array);
13843
13844 case value_t::binary:
13845 return header_size + calc_bson_binary_size(*j.m_value.binary);
13846
13847 case value_t::boolean:
13848 return header_size + 1ul;
13849
13850 case value_t::number_float:
13851 return header_size + 8ul;
13852
13853 case value_t::number_integer:
13854 return header_size + calc_bson_integer_size(j.m_value.number_integer);
13855
13856 case value_t::number_unsigned:
13857 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
13858
13859 case value_t::string:
13860 return header_size + calc_bson_string_size(*j.m_value.string);
13861
13862 case value_t::null:
13863 return header_size + 0ul;
13864
13865 // LCOV_EXCL_START
13866 default:
13867 JSON_ASSERT(false);
13868 return 0ul;
13869 // LCOV_EXCL_STOP
13870 }
13871 }
13872
13873 /*!
13874 @brief Serializes the JSON value @a j to BSON and associates it with the
13875 key @a name.
13876 @param name The name to associate with the JSON entity @a j within the
13877 current BSON document
13878 @return The size of the BSON entry
13879 */
13880 void write_bson_element(const string_t& name,
13881 const BasicJsonType& j)
13882 {
13883 switch (j.type())
13884 {
13885 case value_t::object:
13886 return write_bson_object_entry(name, *j.m_value.object);
13887
13888 case value_t::array:
13889 return write_bson_array(name, *j.m_value.array);
13890
13891 case value_t::binary:
13892 return write_bson_binary(name, *j.m_value.binary);
13893
13894 case value_t::boolean:
13895 return write_bson_boolean(name, j.m_value.boolean);
13896
13897 case value_t::number_float:
13898 return write_bson_double(name, j.m_value.number_float);
13899
13900 case value_t::number_integer:
13901 return write_bson_integer(name, j.m_value.number_integer);
13902
13903 case value_t::number_unsigned:
13904 return write_bson_unsigned(name, j.m_value.number_unsigned);
13905
13906 case value_t::string:
13907 return write_bson_string(name, *j.m_value.string);
13908
13909 case value_t::null:
13910 return write_bson_null(name);
13911
13912 // LCOV_EXCL_START
13913 default:
13914 JSON_ASSERT(false);
13915 return;
13916 // LCOV_EXCL_STOP
13917 }
13918 }
13919
13920 /*!
13921 @brief Calculates the size of the BSON serialization of the given
13922 JSON-object @a j.
13923 @param[in] j JSON value to serialize
13924 @pre j.type() == value_t::object
13925 */
13926 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
13927 {
13928 std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
13929 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
13930 {
13931 return result += calc_bson_element_size(el.first, el.second);
13932 });
13933
13934 return sizeof(std::int32_t) + document_size + 1ul;
13935 }
13936
13937 /*!
13938 @param[in] j JSON value to serialize
13939 @pre j.type() == value_t::object
13940 */
13941 void write_bson_object(const typename BasicJsonType::object_t& value)
13942 {
13943 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
13944
13945 for (const auto& el : value)
13946 {
13947 write_bson_element(el.first, el.second);
13948 }
13949
13950 oa->write_character(to_char_type(0x00));
13951 }
13952
13953 //////////
13954 // CBOR //
13955 //////////
13956
13957 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
13958 {
13959 return to_char_type(0xFA); // Single-Precision Float
13960 }
13961
13962 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
13963 {
13964 return to_char_type(0xFB); // Double-Precision Float
13965 }
13966
13967 /////////////
13968 // MsgPack //
13969 /////////////
13970
13971 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
13972 {
13973 return to_char_type(0xCA); // float 32
13974 }
13975
13976 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
13977 {
13978 return to_char_type(0xCB); // float 64
13979 }
13980
13981 ////////////
13982 // UBJSON //
13983 ////////////
13984
13985 // UBJSON: write number (floating point)
13986 template<typename NumberType, typename std::enable_if<
13987 std::is_floating_point<NumberType>::value, int>::type = 0>
13988 void write_number_with_ubjson_prefix(const NumberType n,
13989 const bool add_prefix)
13990 {
13991 if (add_prefix)
13992 {
13993 oa->write_character(get_ubjson_float_prefix(n));
13994 }
13995 write_number(n);
13996 }
13997
13998 // UBJSON: write number (unsigned integer)
13999 template<typename NumberType, typename std::enable_if<
14000 std::is_unsigned<NumberType>::value, int>::type = 0>
14001 void write_number_with_ubjson_prefix(const NumberType n,
14002 const bool add_prefix)
14003 {
14004 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14005 {
14006 if (add_prefix)
14007 {
14008 oa->write_character(to_char_type('i')); // int8
14009 }
14010 write_number(static_cast<std::uint8_t>(n));
14011 }
14012 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14013 {
14014 if (add_prefix)
14015 {
14016 oa->write_character(to_char_type('U')); // uint8
14017 }
14018 write_number(static_cast<std::uint8_t>(n));
14019 }
14020 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14021 {
14022 if (add_prefix)
14023 {
14024 oa->write_character(to_char_type('I')); // int16
14025 }
14026 write_number(static_cast<std::int16_t>(n));
14027 }
14028 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14029 {
14030 if (add_prefix)
14031 {
14032 oa->write_character(to_char_type('l')); // int32
14033 }
14034 write_number(static_cast<std::int32_t>(n));
14035 }
14036 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14037 {
14038 if (add_prefix)
14039 {
14040 oa->write_character(to_char_type('L')); // int64
14041 }
14042 write_number(static_cast<std::int64_t>(n));
14043 }
14044 else
14045 {
14046 if (add_prefix)
14047 {
14048 oa->write_character(to_char_type('H')); // high-precision number
14049 }
14050
14051 const auto number = BasicJsonType(n).dump();
14052 write_number_with_ubjson_prefix(number.size(), true);
14053 for (std::size_t i = 0; i < number.size(); ++i)
14054 {
14055 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14056 }
14057 }
14058 }
14059
14060 // UBJSON: write number (signed integer)
14061 template < typename NumberType, typename std::enable_if <
14062 std::is_signed<NumberType>::value&&
14063 !std::is_floating_point<NumberType>::value, int >::type = 0 >
14064 void write_number_with_ubjson_prefix(const NumberType n,
14065 const bool add_prefix)
14066 {
14067 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14068 {
14069 if (add_prefix)
14070 {
14071 oa->write_character(to_char_type('i')); // int8
14072 }
14073 write_number(static_cast<std::int8_t>(n));
14074 }
14075 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14076 {
14077 if (add_prefix)
14078 {
14079 oa->write_character(to_char_type('U')); // uint8
14080 }
14081 write_number(static_cast<std::uint8_t>(n));
14082 }
14083 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14084 {
14085 if (add_prefix)
14086 {
14087 oa->write_character(to_char_type('I')); // int16
14088 }
14089 write_number(static_cast<std::int16_t>(n));
14090 }
14091 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14092 {
14093 if (add_prefix)
14094 {
14095 oa->write_character(to_char_type('l')); // int32
14096 }
14097 write_number(static_cast<std::int32_t>(n));
14098 }
14099 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14100 {
14101 if (add_prefix)
14102 {
14103 oa->write_character(to_char_type('L')); // int64
14104 }
14105 write_number(static_cast<std::int64_t>(n));
14106 }
14107 // LCOV_EXCL_START
14108 else
14109 {
14110 if (add_prefix)
14111 {
14112 oa->write_character(to_char_type('H')); // high-precision number
14113 }
14114
14115 const auto number = BasicJsonType(n).dump();
14116 write_number_with_ubjson_prefix(number.size(), true);
14117 for (std::size_t i = 0; i < number.size(); ++i)
14118 {
14119 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14120 }
14121 }
14122 // LCOV_EXCL_STOP
14123 }
14124
14125 /*!
14126 @brief determine the type prefix of container values
14127 */
14128 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14129 {
14130 switch (j.type())
14131 {
14132 case value_t::null:
14133 return 'Z';
14134
14135 case value_t::boolean:
14136 return j.m_value.boolean ? 'T' : 'F';
14137
14138 case value_t::number_integer:
14139 {
14140 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14141 {
14142 return 'i';
14143 }
14144 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14145 {
14146 return 'U';
14147 }
14148 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14149 {
14150 return 'I';
14151 }
14152 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14153 {
14154 return 'l';
14155 }
14156 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14157 {
14158 return 'L';
14159 }
14160 // anything else is treated as high-precision number
14161 return 'H'; // LCOV_EXCL_LINE
14162 }
14163
14164 case value_t::number_unsigned:
14165 {
14166 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14167 {
14168 return 'i';
14169 }
14170 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14171 {
14172 return 'U';
14173 }
14174 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14175 {
14176 return 'I';
14177 }
14178 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14179 {
14180 return 'l';
14181 }
14182 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14183 {
14184 return 'L';
14185 }
14186 // anything else is treated as high-precision number
14187 return 'H'; // LCOV_EXCL_LINE
14188 }
14189
14190 case value_t::number_float:
14191 return get_ubjson_float_prefix(j.m_value.number_float);
14192
14193 case value_t::string:
14194 return 'S';
14195
14196 case value_t::array: // fallthrough
14197 case value_t::binary:
14198 return '[';
14199
14200 case value_t::object:
14201 return '{';
14202
14203 default: // discarded values
14204 return 'N';
14205 }
14206 }
14207
14208 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14209 {
14210 return 'd'; // float 32
14211 }
14212
14213 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14214 {
14215 return 'D'; // float 64
14216 }
14217
14218 ///////////////////////
14219 // Utility functions //
14220 ///////////////////////
14221
684114222 /*
684214223 @brief write a number to output input
6843
684414224 @param[in] n number of type @a NumberType
684514225 @tparam NumberType the type of the number
14226 @tparam OutputIsLittleEndian Set to true if output data is
14227 required to be little endian
684614228
684714229 @note This function needs to respect the system's endianess, because bytes
684814230 in CBOR, MessagePack, and UBJSON are stored in network order (big
684914231 endian) and therefore need reordering on little endian systems.
685014232 */
6851 template <typename NumberType>
14233 template<typename NumberType, bool OutputIsLittleEndian = false>
685214234 void write_number(const NumberType n)
685314235 {
685414236 // step 1: write number to array of length NumberType
685614238 std::memcpy(vec.data(), &n, sizeof(NumberType));
685714239
685814240 // step 2: write array to output (with possible reordering)
6859 if (is_little_endian)
14241 if (is_little_endian != OutputIsLittleEndian)
686014242 {
686114243 // reverse byte order prior to conversion if necessary
686214244 std::reverse(vec.begin(), vec.end());
686514247 oa->write_characters(vec.data(), sizeof(NumberType));
686614248 }
686714249
6868 // UBJSON: write number (floating point)
6869 template <typename NumberType, typename std::enable_if<std::is_floating_point<NumberType>::value, int>::type = 0>
6870 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
6871 {
6872 if (add_prefix)
6873 {
6874 oa->write_character(static_cast<CharType>('D')); // float64
6875 }
6876 write_number(n);
6877 }
6878
6879 // UBJSON: write number (unsigned integer)
6880 template <typename NumberType, typename std::enable_if<std::is_unsigned<NumberType>::value, int>::type = 0>
6881 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
6882 {
6883 if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
6884 {
6885 if (add_prefix)
6886 {
6887 oa->write_character(static_cast<CharType>('i')); // int8
6888 }
6889 write_number(static_cast<uint8_t>(n));
6890 }
6891 else if (n <= (std::numeric_limits<uint8_t>::max)())
6892 {
6893 if (add_prefix)
6894 {
6895 oa->write_character(static_cast<CharType>('U')); // uint8
6896 }
6897 write_number(static_cast<uint8_t>(n));
6898 }
6899 else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
6900 {
6901 if (add_prefix)
6902 {
6903 oa->write_character(static_cast<CharType>('I')); // int16
6904 }
6905 write_number(static_cast<int16_t>(n));
6906 }
6907 else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
6908 {
6909 if (add_prefix)
6910 {
6911 oa->write_character(static_cast<CharType>('l')); // int32
6912 }
6913 write_number(static_cast<int32_t>(n));
6914 }
6915 else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
6916 {
6917 if (add_prefix)
6918 {
6919 oa->write_character(static_cast<CharType>('L')); // int64
6920 }
6921 write_number(static_cast<int64_t>(n));
14250 void write_compact_float(const number_float_t n, detail::input_format_t format)
14251 {
14252 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14253 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14254 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14255 {
14256 oa->write_character(format == detail::input_format_t::cbor
14257 ? get_cbor_float_prefix(static_cast<float>(n))
14258 : get_msgpack_float_prefix(static_cast<float>(n)));
14259 write_number(static_cast<float>(n));
692214260 }
692314261 else
692414262 {
6925 JSON_THROW(out_of_range::create(407, "number overflow serializing " + cpt::to_string(n)));
6926 }
6927 }
6928
6929 // UBJSON: write number (signed integer)
6930 template <typename NumberType, typename std::enable_if<std::is_signed<NumberType>::value and not std::is_floating_point<NumberType>::value, int>::type = 0>
6931 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
6932 {
6933 if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
6934 {
6935 if (add_prefix)
6936 {
6937 oa->write_character(static_cast<CharType>('i')); // int8
6938 }
6939 write_number(static_cast<int8_t>(n));
6940 }
6941 else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
6942 {
6943 if (add_prefix)
6944 {
6945 oa->write_character(static_cast<CharType>('U')); // uint8
6946 }
6947 write_number(static_cast<uint8_t>(n));
6948 }
6949 else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
6950 {
6951 if (add_prefix)
6952 {
6953 oa->write_character(static_cast<CharType>('I')); // int16
6954 }
6955 write_number(static_cast<int16_t>(n));
6956 }
6957 else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
6958 {
6959 if (add_prefix)
6960 {
6961 oa->write_character(static_cast<CharType>('l')); // int32
6962 }
6963 write_number(static_cast<int32_t>(n));
6964 }
6965 else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
6966 {
6967 if (add_prefix)
6968 {
6969 oa->write_character(static_cast<CharType>('L')); // int64
6970 }
6971 write_number(static_cast<int64_t>(n));
6972 }
6973 // LCOV_EXCL_START
6974 else
6975 {
6976 JSON_THROW(out_of_range::create(407, "number overflow serializing " + cpt::to_string(n)));
6977 }
6978 // LCOV_EXCL_STOP
6979 }
6980
6981 /*!
6982 @brief determine the type prefix of container values
6983
6984 @note This function does not need to be 100% accurate when it comes to
6985 integer limits. In case a number exceeds the limits of int64_t,
6986 this will be detected by a later call to function
6987 write_number_with_ubjson_prefix. Therefore, we return 'L' for any
6988 value that does not fit the previous limits.
6989 */
6990 char ubjson_prefix(const BasicJsonType& j) const noexcept
6991 {
6992 switch (j.type())
6993 {
6994 case value_t::null:
6995 return 'Z';
6996
6997 case value_t::boolean:
6998 return j.m_value.boolean ? 'T' : 'F';
6999
7000 case value_t::number_integer:
7001 {
7002 if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
7003 {
7004 return 'i';
7005 }
7006 else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and
7007 j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
7008 {
7009 return 'U';
7010 }
7011 else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and
7012 j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
7013 {
7014 return 'I';
7015 }
7016 else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and
7017 j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
7018 {
7019 return 'l';
7020 }
7021 else // no check and assume int64_t (see note above)
7022 {
7023 return 'L';
7024 }
7025 }
7026
7027 case value_t::number_unsigned:
7028 {
7029 if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
7030 {
7031 return 'i';
7032 }
7033 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7034 {
7035 return 'U';
7036 }
7037 else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
7038 {
7039 return 'I';
7040 }
7041 else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
7042 {
7043 return 'l';
7044 }
7045 else // no check and assume int64_t (see note above)
7046 {
7047 return 'L';
7048 }
7049 }
7050
7051 case value_t::number_float:
7052 return 'D';
7053
7054 case value_t::string:
7055 return 'S';
7056
7057 case value_t::array:
7058 return '[';
7059
7060 case value_t::object:
7061 return '{';
7062
7063 default: // discarded values
7064 return 'N';
7065 }
7066 }
7067
7068 private:
14263 oa->write_character(format == detail::input_format_t::cbor
14264 ? get_cbor_float_prefix(n)
14265 : get_msgpack_float_prefix(n));
14266 write_number(n);
14267 }
14268 }
14269
14270 public:
14271 // The following to_char_type functions are implement the conversion
14272 // between uint8_t and CharType. In case CharType is not unsigned,
14273 // such a conversion is required to allow values greater than 128.
14274 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14275 template < typename C = CharType,
14276 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14277 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14278 {
14279 return *reinterpret_cast<char*>(&x);
14280 }
14281
14282 template < typename C = CharType,
14283 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14284 static CharType to_char_type(std::uint8_t x) noexcept
14285 {
14286 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14287 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14288 CharType result;
14289 std::memcpy(&result, &x, sizeof(x));
14290 return result;
14291 }
14292
14293 template<typename C = CharType,
14294 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14295 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14296 {
14297 return x;
14298 }
14299
14300 template < typename InputCharType, typename C = CharType,
14301 enable_if_t <
14302 std::is_signed<C>::value &&
14303 std::is_signed<char>::value &&
14304 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14305 > * = nullptr >
14306 static constexpr CharType to_char_type(InputCharType x) noexcept
14307 {
14308 return x;
14309 }
14310
14311 private:
706914312 /// whether we can assume little endianess
7070 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
14313 const bool is_little_endian = little_endianess();
707114314
707214315 /// the output
707314316 output_adapter_t<CharType> oa = nullptr;
707414317 };
7075 }
7076 }
14318 } // namespace detail
14319 } // namespace nlohmann
14320
14321 // #include <nlohmann/detail/output/output_adapters.hpp>
707714322
707814323 // #include <nlohmann/detail/output/serializer.hpp>
707914324
708014325
7081 #include <algorithm> // reverse, remove, fill, find, none_of
7082 #include <array> // array
7083 #include <cassert> // assert
7084 #include <ciso646> // and, or
7085 #include <clocale> // localeconv, lconv
7086 #include <cmath> // labs, isfinite, isnan, signbit
7087 #include <cstddef> // size_t, ptrdiff_t
7088 #include <cstdint> // uint8_t
7089 #include <cstdio> // snprintf
7090 #include <iomanip> // setfill
7091 #include <iterator> // next
7092 #include <limits> // numeric_limits
7093 #include <sstream> // stringstream
7094 #include <string> // string
14326 #include <algorithm> // reverse, remove, fill, find, none_of
14327 #include <array> // array
14328 #include <clocale> // localeconv, lconv
14329 #include <cmath> // labs, isfinite, isnan, signbit
14330 #include <cstddef> // size_t, ptrdiff_t
14331 #include <cstdint> // uint8_t
14332 #include <cstdio> // snprintf
14333 #include <limits> // numeric_limits
14334 #include <string> // string, char_traits
709514335 #include <type_traits> // is_same
7096
7097 // #include <nlohmann/detail/exceptions.hpp>
14336 #include <utility> // move
709814337
709914338 // #include <nlohmann/detail/conversions/to_chars.hpp>
710014339
710114340
7102 #include <cassert> // assert
7103 #include <ciso646> // or, and, not
14341 #include <array> // array
710414342 #include <cmath> // signbit, isfinite
710514343 #include <cstdint> // intN_t, uintN_t
710614344 #include <cstring> // memcpy, memmove
14345 #include <limits> // numeric_limits
14346 #include <type_traits> // conditional
14347
14348 // #include <nlohmann/detail/macro_scope.hpp>
14349
710714350
710814351 namespace nlohmann
710914352 {
713214375 namespace dtoa_impl
713314376 {
713414377
7135 template <typename Target, typename Source>
14378 template<typename Target, typename Source>
713614379 Target reinterpret_bits(const Source source)
713714380 {
713814381 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
714614389 {
714714390 static constexpr int kPrecision = 64; // = q
714814391
7149 uint64_t f;
7150 int e;
7151
7152 constexpr diyfp() noexcept : f(0), e(0)
7153 {
7154 }
7155 constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_)
7156 {
7157 }
14392 std::uint64_t f = 0;
14393 int e = 0;
14394
14395 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
715814396
715914397 /*!
716014398 @brief returns x - y
716214400 */
716314401 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
716414402 {
7165 assert(x.e == y.e);
7166 assert(x.f >= y.f);
7167
7168 return diyfp(x.f - y.f, x.e);
14403 JSON_ASSERT(x.e == y.e);
14404 JSON_ASSERT(x.f >= y.f);
14405
14406 return {x.f - y.f, x.e};
716914407 }
717014408
717114409 /*!
719914437 //
720014438 // = p_lo + 2^64 p_hi
720114439
7202 const uint64_t u_lo = x.f & 0xFFFFFFFF;
7203 const uint64_t u_hi = x.f >> 32;
7204 const uint64_t v_lo = y.f & 0xFFFFFFFF;
7205 const uint64_t v_hi = y.f >> 32;
7206
7207 const uint64_t p0 = u_lo * v_lo;
7208 const uint64_t p1 = u_lo * v_hi;
7209 const uint64_t p2 = u_hi * v_lo;
7210 const uint64_t p3 = u_hi * v_hi;
7211
7212 const uint64_t p0_hi = p0 >> 32;
7213 const uint64_t p1_lo = p1 & 0xFFFFFFFF;
7214 const uint64_t p1_hi = p1 >> 32;
7215 const uint64_t p2_lo = p2 & 0xFFFFFFFF;
7216 const uint64_t p2_hi = p2 >> 32;
7217
7218 uint64_t Q = p0_hi + p1_lo + p2_lo;
14440 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
14441 const std::uint64_t u_hi = x.f >> 32u;
14442 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
14443 const std::uint64_t v_hi = y.f >> 32u;
14444
14445 const std::uint64_t p0 = u_lo * v_lo;
14446 const std::uint64_t p1 = u_lo * v_hi;
14447 const std::uint64_t p2 = u_hi * v_lo;
14448 const std::uint64_t p3 = u_hi * v_hi;
14449
14450 const std::uint64_t p0_hi = p0 >> 32u;
14451 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
14452 const std::uint64_t p1_hi = p1 >> 32u;
14453 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
14454 const std::uint64_t p2_hi = p2 >> 32u;
14455
14456 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
721914457
722014458 // The full product might now be computed as
722114459 //
722614464 // Effectively we only need to add the highest bit in p_lo to p_hi (and
722714465 // Q_hi + 1 does not overflow).
722814466
7229 Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
7230
7231 const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
7232
7233 return diyfp(h, x.e + y.e + 64);
14467 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
14468
14469 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
14470
14471 return {h, x.e + y.e + 64};
723414472 }
723514473
723614474 /*!
723914477 */
724014478 static diyfp normalize(diyfp x) noexcept
724114479 {
7242 assert(x.f != 0);
7243
7244 while ((x.f >> 63) == 0)
7245 {
7246 x.f <<= 1;
14480 JSON_ASSERT(x.f != 0);
14481
14482 while ((x.f >> 63u) == 0)
14483 {
14484 x.f <<= 1u;
724714485 x.e--;
724814486 }
724914487
725814496 {
725914497 const int delta = x.e - target_exponent;
726014498
7261 assert(delta >= 0);
7262 assert(((x.f << delta) >> delta) == x.f);
7263
7264 return diyfp(x.f << delta, target_exponent);
14499 JSON_ASSERT(delta >= 0);
14500 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
14501
14502 return {x.f << delta, target_exponent};
726514503 }
726614504 };
726714505
727814516
727914517 @pre value must be finite and positive
728014518 */
7281 template <typename FloatType>
14519 template<typename FloatType>
728214520 boundaries compute_boundaries(FloatType value)
728314521 {
7284 assert(std::isfinite(value));
7285 assert(value > 0);
14522 JSON_ASSERT(std::isfinite(value));
14523 JSON_ASSERT(value > 0);
728614524
728714525 // Convert the IEEE representation into a diyfp.
728814526 //
729114529 // If v is normalized:
729214530 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
729314531
7294 static_assert(std::numeric_limits<FloatType>::is_iec559, "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
7295
7296 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
7297 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
7298 constexpr int kMinExp = 1 - kBias;
7299 constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
7300
7301 using bits_type = typename std::conditional<kPrecision == 24, uint32_t, uint64_t>::type;
7302
7303 const uint64_t bits = reinterpret_bits<bits_type>(value);
7304 const uint64_t E = bits >> (kPrecision - 1);
7305 const uint64_t F = bits & (kHiddenBit - 1);
7306
7307 const bool is_denormal = (E == 0);
7308 const diyfp v = is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
14532 static_assert(std::numeric_limits<FloatType>::is_iec559,
14533 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
14534
14535 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
14536 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
14537 constexpr int kMinExp = 1 - kBias;
14538 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
14539
14540 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
14541
14542 const std::uint64_t bits = reinterpret_bits<bits_type>(value);
14543 const std::uint64_t E = bits >> (kPrecision - 1);
14544 const std::uint64_t F = bits & (kHiddenBit - 1);
14545
14546 const bool is_denormal = E == 0;
14547 const diyfp v = is_denormal
14548 ? diyfp(F, kMinExp)
14549 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
730914550
731014551 // Compute the boundaries m- and m+ of the floating-point value
731114552 // v = f * 2^e.
732814569 // -----------------+------+------+-------------+-------------+--- (B)
732914570 // v- m- v m+ v+
733014571
7331 const bool lower_boundary_is_closer = (F == 0 and E > 1);
14572 const bool lower_boundary_is_closer = F == 0 && E > 1;
733214573 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
7333 const diyfp m_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B)
7334 : diyfp(2 * v.f - 1, v.e - 1); // (A)
14574 const diyfp m_minus = lower_boundary_is_closer
14575 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
14576 : diyfp(2 * v.f - 1, v.e - 1); // (A)
733514577
733614578 // Determine the normalized w+ = m+.
733714579 const diyfp w_plus = diyfp::normalize(m_plus);
740214644
740314645 struct cached_power // c = f * 2^e ~= 10^k
740414646 {
7405 uint64_t f;
14647 std::uint64_t f;
740614648 int e;
740714649 int k;
740814650 };
742614668 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
742714669 // ==> 2^(alpha - e - 1) <= c
742814670 //
7429 // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
14671 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
743014672 //
743114673 // k = ceil( log_10( 2^(alpha - e - 1) ) )
743214674 // = ceil( (alpha - e - 1) * log_10(2) )
746614708 // NB:
746714709 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
746814710
7469 constexpr int kCachedPowersSize = 79;
747014711 constexpr int kCachedPowersMinDecExp = -300;
747114712 constexpr int kCachedPowersDecStep = 8;
747214713
7473 static constexpr cached_power kCachedPowers[] = {
7474 {0xAB70FE17C79AC6CA, -1060, -300}, {0xFF77B1FCBEBCDC4F, -1034, -292}, {0xBE5691EF416BD60C, -1007, -284}, {0x8DD01FAD907FFC3C, -980, -276},
7475 {0xD3515C2831559A83, -954, -268}, {0x9D71AC8FADA6C9B5, -927, -260}, {0xEA9C227723EE8BCB, -901, -252}, {0xAECC49914078536D, -874, -244},
7476 {0x823C12795DB6CE57, -847, -236}, {0xC21094364DFB5637, -821, -228}, {0x9096EA6F3848984F, -794, -220}, {0xD77485CB25823AC7, -768, -212},
7477 {0xA086CFCD97BF97F4, -741, -204}, {0xEF340A98172AACE5, -715, -196}, {0xB23867FB2A35B28E, -688, -188}, {0x84C8D4DFD2C63F3B, -661, -180},
7478 {0xC5DD44271AD3CDBA, -635, -172}, {0x936B9FCEBB25C996, -608, -164}, {0xDBAC6C247D62A584, -582, -156}, {0xA3AB66580D5FDAF6, -555, -148},
7479 {0xF3E2F893DEC3F126, -529, -140}, {0xB5B5ADA8AAFF80B8, -502, -132}, {0x87625F056C7C4A8B, -475, -124}, {0xC9BCFF6034C13053, -449, -116},
7480 {0x964E858C91BA2655, -422, -108}, {0xDFF9772470297EBD, -396, -100}, {0xA6DFBD9FB8E5B88F, -369, -92}, {0xF8A95FCF88747D94, -343, -84},
7481 {0xB94470938FA89BCF, -316, -76}, {0x8A08F0F8BF0F156B, -289, -68}, {0xCDB02555653131B6, -263, -60}, {0x993FE2C6D07B7FAC, -236, -52},
7482 {0xE45C10C42A2B3B06, -210, -44}, {0xAA242499697392D3, -183, -36}, {0xFD87B5F28300CA0E, -157, -28}, {0xBCE5086492111AEB, -130, -20},
7483 {0x8CBCCC096F5088CC, -103, -12}, {0xD1B71758E219652C, -77, -4}, {0x9C40000000000000, -50, 4}, {0xE8D4A51000000000, -24, 12},
7484 {0xAD78EBC5AC620000, 3, 20}, {0x813F3978F8940984, 30, 28}, {0xC097CE7BC90715B3, 56, 36}, {0x8F7E32CE7BEA5C70, 83, 44},
7485 {0xD5D238A4ABE98068, 109, 52}, {0x9F4F2726179A2245, 136, 60}, {0xED63A231D4C4FB27, 162, 68}, {0xB0DE65388CC8ADA8, 189, 76},
7486 {0x83C7088E1AAB65DB, 216, 84}, {0xC45D1DF942711D9A, 242, 92}, {0x924D692CA61BE758, 269, 100}, {0xDA01EE641A708DEA, 295, 108},
7487 {0xA26DA3999AEF774A, 322, 116}, {0xF209787BB47D6B85, 348, 124}, {0xB454E4A179DD1877, 375, 132}, {0x865B86925B9BC5C2, 402, 140},
7488 {0xC83553C5C8965D3D, 428, 148}, {0x952AB45CFA97A0B3, 455, 156}, {0xDE469FBD99A05FE3, 481, 164}, {0xA59BC234DB398C25, 508, 172},
7489 {0xF6C69A72A3989F5C, 534, 180}, {0xB7DCBF5354E9BECE, 561, 188}, {0x88FCF317F22241E2, 588, 196}, {0xCC20CE9BD35C78A5, 614, 204},
7490 {0x98165AF37B2153DF, 641, 212}, {0xE2A0B5DC971F303A, 667, 220}, {0xA8D9D1535CE3B396, 694, 228}, {0xFB9B7CD9A4A7443C, 720, 236},
7491 {0xBB764C4CA7A44410, 747, 244}, {0x8BAB8EEFB6409C1A, 774, 252}, {0xD01FEF10A657842C, 800, 260}, {0x9B10A4E5E9913129, 827, 268},
7492 {0xE7109BFBA19C0C9D, 853, 276}, {0xAC2820D9623BF429, 880, 284}, {0x80444B5E7AA7CF85, 907, 292}, {0xBF21E44003ACDD2D, 933, 300},
7493 {0x8E679C2F5E44FF8F, 960, 308}, {0xD433179D9C8CB841, 986, 316}, {0x9E19DB92B4E31BA9, 1013, 324},
14714 static constexpr std::array<cached_power, 79> kCachedPowers =
14715 {
14716 {
14717 { 0xAB70FE17C79AC6CA, -1060, -300 },
14718 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
14719 { 0xBE5691EF416BD60C, -1007, -284 },
14720 { 0x8DD01FAD907FFC3C, -980, -276 },
14721 { 0xD3515C2831559A83, -954, -268 },
14722 { 0x9D71AC8FADA6C9B5, -927, -260 },
14723 { 0xEA9C227723EE8BCB, -901, -252 },
14724 { 0xAECC49914078536D, -874, -244 },
14725 { 0x823C12795DB6CE57, -847, -236 },
14726 { 0xC21094364DFB5637, -821, -228 },
14727 { 0x9096EA6F3848984F, -794, -220 },
14728 { 0xD77485CB25823AC7, -768, -212 },
14729 { 0xA086CFCD97BF97F4, -741, -204 },
14730 { 0xEF340A98172AACE5, -715, -196 },
14731 { 0xB23867FB2A35B28E, -688, -188 },
14732 { 0x84C8D4DFD2C63F3B, -661, -180 },
14733 { 0xC5DD44271AD3CDBA, -635, -172 },
14734 { 0x936B9FCEBB25C996, -608, -164 },
14735 { 0xDBAC6C247D62A584, -582, -156 },
14736 { 0xA3AB66580D5FDAF6, -555, -148 },
14737 { 0xF3E2F893DEC3F126, -529, -140 },
14738 { 0xB5B5ADA8AAFF80B8, -502, -132 },
14739 { 0x87625F056C7C4A8B, -475, -124 },
14740 { 0xC9BCFF6034C13053, -449, -116 },
14741 { 0x964E858C91BA2655, -422, -108 },
14742 { 0xDFF9772470297EBD, -396, -100 },
14743 { 0xA6DFBD9FB8E5B88F, -369, -92 },
14744 { 0xF8A95FCF88747D94, -343, -84 },
14745 { 0xB94470938FA89BCF, -316, -76 },
14746 { 0x8A08F0F8BF0F156B, -289, -68 },
14747 { 0xCDB02555653131B6, -263, -60 },
14748 { 0x993FE2C6D07B7FAC, -236, -52 },
14749 { 0xE45C10C42A2B3B06, -210, -44 },
14750 { 0xAA242499697392D3, -183, -36 },
14751 { 0xFD87B5F28300CA0E, -157, -28 },
14752 { 0xBCE5086492111AEB, -130, -20 },
14753 { 0x8CBCCC096F5088CC, -103, -12 },
14754 { 0xD1B71758E219652C, -77, -4 },
14755 { 0x9C40000000000000, -50, 4 },
14756 { 0xE8D4A51000000000, -24, 12 },
14757 { 0xAD78EBC5AC620000, 3, 20 },
14758 { 0x813F3978F8940984, 30, 28 },
14759 { 0xC097CE7BC90715B3, 56, 36 },
14760 { 0x8F7E32CE7BEA5C70, 83, 44 },
14761 { 0xD5D238A4ABE98068, 109, 52 },
14762 { 0x9F4F2726179A2245, 136, 60 },
14763 { 0xED63A231D4C4FB27, 162, 68 },
14764 { 0xB0DE65388CC8ADA8, 189, 76 },
14765 { 0x83C7088E1AAB65DB, 216, 84 },
14766 { 0xC45D1DF942711D9A, 242, 92 },
14767 { 0x924D692CA61BE758, 269, 100 },
14768 { 0xDA01EE641A708DEA, 295, 108 },
14769 { 0xA26DA3999AEF774A, 322, 116 },
14770 { 0xF209787BB47D6B85, 348, 124 },
14771 { 0xB454E4A179DD1877, 375, 132 },
14772 { 0x865B86925B9BC5C2, 402, 140 },
14773 { 0xC83553C5C8965D3D, 428, 148 },
14774 { 0x952AB45CFA97A0B3, 455, 156 },
14775 { 0xDE469FBD99A05FE3, 481, 164 },
14776 { 0xA59BC234DB398C25, 508, 172 },
14777 { 0xF6C69A72A3989F5C, 534, 180 },
14778 { 0xB7DCBF5354E9BECE, 561, 188 },
14779 { 0x88FCF317F22241E2, 588, 196 },
14780 { 0xCC20CE9BD35C78A5, 614, 204 },
14781 { 0x98165AF37B2153DF, 641, 212 },
14782 { 0xE2A0B5DC971F303A, 667, 220 },
14783 { 0xA8D9D1535CE3B396, 694, 228 },
14784 { 0xFB9B7CD9A4A7443C, 720, 236 },
14785 { 0xBB764C4CA7A44410, 747, 244 },
14786 { 0x8BAB8EEFB6409C1A, 774, 252 },
14787 { 0xD01FEF10A657842C, 800, 260 },
14788 { 0x9B10A4E5E9913129, 827, 268 },
14789 { 0xE7109BFBA19C0C9D, 853, 276 },
14790 { 0xAC2820D9623BF429, 880, 284 },
14791 { 0x80444B5E7AA7CF85, 907, 292 },
14792 { 0xBF21E44003ACDD2D, 933, 300 },
14793 { 0x8E679C2F5E44FF8F, 960, 308 },
14794 { 0xD433179D9C8CB841, 986, 316 },
14795 { 0x9E19DB92B4E31BA9, 1013, 324 },
14796 }
749414797 };
749514798
749614799 // This computation gives exactly the same results for k as
749714800 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
749814801 // for |e| <= 1500, but doesn't require floating-point operations.
749914802 // NB: log_10(2) ~= 78913 / 2^18
7500 assert(e >= -1500);
7501 assert(e <= 1500);
14803 JSON_ASSERT(e >= -1500);
14804 JSON_ASSERT(e <= 1500);
750214805 const int f = kAlpha - e - 1;
7503 const int k = (f * 78913) / (1 << 18) + (f > 0);
14806 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
750414807
750514808 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
7506 assert(index >= 0);
7507 assert(index < kCachedPowersSize);
7508 static_cast<void>(kCachedPowersSize); // Fix warning.
7509
7510 const cached_power cached = kCachedPowers[index];
7511 assert(kAlpha <= cached.e + e + 64);
7512 assert(kGamma >= cached.e + e + 64);
14809 JSON_ASSERT(index >= 0);
14810 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
14811
14812 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
14813 JSON_ASSERT(kAlpha <= cached.e + e + 64);
14814 JSON_ASSERT(kGamma >= cached.e + e + 64);
751314815
751414816 return cached;
751514817 }
751814820 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
751914821 For n == 0, returns 1 and sets pow10 := 1.
752014822 */
7521 inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
14823 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
752214824 {
752314825 // LCOV_EXCL_START
752414826 if (n >= 1000000000)
753014832 else if (n >= 100000000)
753114833 {
753214834 pow10 = 100000000;
7533 return 9;
14835 return 9;
753414836 }
753514837 else if (n >= 10000000)
753614838 {
753714839 pow10 = 10000000;
7538 return 8;
14840 return 8;
753914841 }
754014842 else if (n >= 1000000)
754114843 {
754214844 pow10 = 1000000;
7543 return 7;
14845 return 7;
754414846 }
754514847 else if (n >= 100000)
754614848 {
754714849 pow10 = 100000;
7548 return 6;
14850 return 6;
754914851 }
755014852 else if (n >= 10000)
755114853 {
755214854 pow10 = 10000;
7553 return 5;
14855 return 5;
755414856 }
755514857 else if (n >= 1000)
755614858 {
755714859 pow10 = 1000;
7558 return 4;
14860 return 4;
755914861 }
756014862 else if (n >= 100)
756114863 {
756214864 pow10 = 100;
7563 return 3;
14865 return 3;
756414866 }
756514867 else if (n >= 10)
756614868 {
756714869 pow10 = 10;
7568 return 2;
14870 return 2;
756914871 }
757014872 else
757114873 {
757414876 }
757514877 }
757614878
7577 inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta, uint64_t rest, uint64_t ten_k)
14879 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
14880 std::uint64_t rest, std::uint64_t ten_k)
757814881 {
7579 assert(len >= 1);
7580 assert(dist <= delta);
7581 assert(rest <= delta);
7582 assert(ten_k > 0);
14882 JSON_ASSERT(len >= 1);
14883 JSON_ASSERT(dist <= delta);
14884 JSON_ASSERT(rest <= delta);
14885 JSON_ASSERT(ten_k > 0);
758314886
758414887 // <--------------------------- delta ---->
758514888 // <---- dist --------->
760014903 // The tests are written in this order to avoid overflow in unsigned
760114904 // integer arithmetic.
760214905
7603 while (rest < dist and delta - rest >= ten_k and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
7604 {
7605 assert(buf[len - 1] != '0');
14906 while (rest < dist
14907 && delta - rest >= ten_k
14908 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
14909 {
14910 JSON_ASSERT(buf[len - 1] != '0');
760614911 buf[len - 1]--;
760714912 rest += ten_k;
760814913 }
761214917 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
761314918 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
761414919 */
7615 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
14920 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
14921 diyfp M_minus, diyfp w, diyfp M_plus)
761614922 {
761714923 static_assert(kAlpha >= -60, "internal error");
761814924 static_assert(kGamma <= -32, "internal error");
762914935 // Grisu2 generates the digits of M+ from left to right and stops as soon as
763014936 // V is in [M-,M+].
763114937
7632 assert(M_plus.e >= kAlpha);
7633 assert(M_plus.e <= kGamma);
7634
7635 uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
7636 uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
14938 JSON_ASSERT(M_plus.e >= kAlpha);
14939 JSON_ASSERT(M_plus.e <= kGamma);
14940
14941 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
14942 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
763714943
763814944 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
763914945 //
764214948 // = ((p1 ) * 2^-e + (p2 )) * 2^e
764314949 // = p1 + p2 * 2^e
764414950
7645 const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
7646
7647 uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
7648 uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
14951 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
14952
14953 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
14954 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
764914955
765014956 // 1)
765114957 //
765214958 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
765314959
7654 assert(p1 > 0);
7655
7656 uint32_t pow10;
14960 JSON_ASSERT(p1 > 0);
14961
14962 std::uint32_t pow10;
765714963 const int k = find_largest_pow10(p1, pow10);
765814964
765914965 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
768114987 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
768214988 // pow10 = 10^(n-1) <= p1 < 10^n
768314989 //
7684 const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
7685 const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
14990 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
14991 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
768614992 //
768714993 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
768814994 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
768914995 //
7690 assert(d <= 9);
14996 JSON_ASSERT(d <= 9);
769114997 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
769214998 //
769314999 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
770715013 // Note:
770815014 // Since rest and delta share the same exponent e, it suffices to
770915015 // compare the significands.
7710 const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
15016 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
771115017 if (rest <= delta)
771215018 {
771315019 // V = buffer * 10^n, with M- <= V <= M+.
772315029 //
772415030 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
772515031 //
7726 const uint64_t ten_n = uint64_t{pow10} << -one.e;
15032 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
772715033 grisu2_round(buffer, length, dist, delta, rest, ten_n);
772815034
772915035 return;
777415080 //
777515081 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
777615082
7777 assert(p2 > delta);
15083 JSON_ASSERT(p2 > delta);
777815084
777915085 int m = 0;
778015086 for (;;)
778515091 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
778615092 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
778715093 //
7788 assert(p2 <= UINT64_MAX / 10);
15094 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
778915095 p2 *= 10;
7790 const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
7791 const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15096 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15097 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
779215098 //
779315099 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
779415100 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
779515101 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
779615102 //
7797 assert(d <= 9);
15103 JSON_ASSERT(d <= 9);
779815104 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
779915105 //
780015106 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
781115117 // p2 * 2^e <= 10^m * delta * 2^e
781215118 // p2 <= 10^m * delta
781315119 delta *= 10;
7814 dist *= 10;
15120 dist *= 10;
781515121 if (p2 <= delta)
781615122 {
781715123 break;
782815134 //
782915135 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
783015136 //
7831 const uint64_t ten_m = one.f;
15137 const std::uint64_t ten_m = one.f;
783215138 grisu2_round(buffer, length, dist, delta, p2, ten_m);
783315139
783415140 // By construction this algorithm generates the shortest possible decimal
785115157 len is the length of the buffer (number of decimal digits)
785215158 The buffer must be large enough, i.e. >= max_digits10.
785315159 */
7854 inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
15160 JSON_HEDLEY_NON_NULL(1)
15161 inline void grisu2(char* buf, int& len, int& decimal_exponent,
15162 diyfp m_minus, diyfp v, diyfp m_plus)
785515163 {
7856 assert(m_plus.e == m_minus.e);
7857 assert(m_plus.e == v.e);
15164 JSON_ASSERT(m_plus.e == m_minus.e);
15165 JSON_ASSERT(m_plus.e == v.e);
785815166
785915167 // --------(-----------------------+-----------------------)-------- (A)
786015168 // m- v m+
787015178 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
787115179
787215180 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
7873 const diyfp w = diyfp::mul(v, c_minus_k);
15181 const diyfp w = diyfp::mul(v, c_minus_k);
787415182 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
7875 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15183 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
787615184
787715185 // ----(---+---)---------------(---+---)---------------(---+---)----
787815186 // w- w w+
789615204 // Note that this does not mean that Grisu2 always generates the shortest
789715205 // possible number in the interval (m-, m+).
789815206 const diyfp M_minus(w_minus.f + 1, w_minus.e);
7899 const diyfp M_plus(w_plus.f - 1, w_plus.e);
15207 const diyfp M_plus (w_plus.f - 1, w_plus.e );
790015208
790115209 decimal_exponent = -cached.k; // = -(-k) = k
790215210
790815216 len is the length of the buffer (number of decimal digits)
790915217 The buffer must be large enough, i.e. >= max_digits10.
791015218 */
7911 template <typename FloatType>
15219 template<typename FloatType>
15220 JSON_HEDLEY_NON_NULL(1)
791215221 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
791315222 {
7914 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, "internal error: not enough precision");
7915
7916 assert(std::isfinite(value));
7917 assert(value > 0);
7918
7919 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
7920 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
7921 // decimal representations are not exactly "short".
7922 //
7923 // The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars)
7924 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
7925 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
7926 // does.
7927 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
7928 // representation using the corresponding std::from_chars function recovers value exactly". That
7929 // indicates that single precision floating-point numbers should be recovered using
7930 // 'cpt::strtof'.
7931 //
7932 // NB: If the neighbors are computed for single-precision numbers, there is a single float
7933 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
7934 // value is off by 1 ulp.
15223 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15224 "internal error: not enough precision");
15225
15226 JSON_ASSERT(std::isfinite(value));
15227 JSON_ASSERT(value > 0);
15228
15229 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
15230 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15231 // decimal representations are not exactly "short".
15232 //
15233 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15234 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15235 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
15236 // does.
15237 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15238 // representation using the corresponding std::from_chars function recovers value exactly". That
15239 // indicates that single precision floating-point numbers should be recovered using
15240 // 'std::strtof'.
15241 //
15242 // NB: If the neighbors are computed for single-precision numbers, there is a single float
15243 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15244 // value is off by 1 ulp.
793515245 #if 0
793615246 const boundaries w = compute_boundaries(static_cast<double>(value));
793715247 #else
794615256 @return a pointer to the element following the exponent.
794715257 @pre -1000 < e < 1000
794815258 */
15259 JSON_HEDLEY_NON_NULL(1)
15260 JSON_HEDLEY_RETURNS_NON_NULL
794915261 inline char* append_exponent(char* buf, int e)
795015262 {
7951 assert(e > -1000);
7952 assert(e < 1000);
15263 JSON_ASSERT(e > -1000);
15264 JSON_ASSERT(e < 1000);
795315265
795415266 if (e < 0)
795515267 {
796115273 *buf++ = '+';
796215274 }
796315275
7964 uint32_t k = static_cast<uint32_t>(e);
15276 auto k = static_cast<std::uint32_t>(e);
796515277 if (k < 10)
796615278 {
796715279 // Always print at least two digits in the exponent.
799615308 @pre min_exp < 0
799715309 @pre max_exp > 0
799815310 */
7999 inline char* format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp)
15311 JSON_HEDLEY_NON_NULL(1)
15312 JSON_HEDLEY_RETURNS_NON_NULL
15313 inline char* format_buffer(char* buf, int len, int decimal_exponent,
15314 int min_exp, int max_exp)
800015315 {
8001 assert(min_exp < 0);
8002 assert(max_exp > 0);
15316 JSON_ASSERT(min_exp < 0);
15317 JSON_ASSERT(max_exp > 0);
800315318
800415319 const int k = len;
800515320 const int n = len + decimal_exponent;
800815323 // k is the length of the buffer (number of decimal digits)
800915324 // n is the position of the decimal point relative to the start of the buffer.
801015325
8011 if (k <= n and n <= max_exp)
15326 if (k <= n && n <= max_exp)
801215327 {
801315328 // digits[000]
801415329 // len <= max_exp + 2
801515330
8016 std::memset(buf + k, '0', static_cast<size_t>(n - k));
15331 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
801715332 // Make it look like a floating-point number (#362, #378)
801815333 buf[n + 0] = '.';
801915334 buf[n + 1] = '0';
8020 return buf + (n + 2);
8021 }
8022
8023 if (0 < n and n <= max_exp)
15335 return buf + (static_cast<size_t>(n) + 2);
15336 }
15337
15338 if (0 < n && n <= max_exp)
802415339 {
802515340 // dig.its
802615341 // len <= max_digits10 + 1
802715342
8028 assert(k > n);
8029
8030 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
15343 JSON_ASSERT(k > n);
15344
15345 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
803115346 buf[n] = '.';
8032 return buf + (k + 1);
8033 }
8034
8035 if (min_exp < n and n <= 0)
15347 return buf + (static_cast<size_t>(k) + 1U);
15348 }
15349
15350 if (min_exp < n && n <= 0)
803615351 {
803715352 // 0.[000]digits
803815353 // len <= 2 + (-min_exp - 1) + max_digits10
803915354
8040 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
15355 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
804115356 buf[0] = '0';
804215357 buf[1] = '.';
804315358 std::memset(buf + 2, '0', static_cast<size_t>(-n));
8044 return buf + (2 + (-n) + k);
15359 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
804515360 }
804615361
804715362 if (k == 1)
805615371 // d.igitsE+123
805715372 // len <= max_digits10 + 1 + 5
805815373
8059 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
15374 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
806015375 buf[1] = '.';
8061 buf += 1 + k;
15376 buf += 1 + static_cast<size_t>(k);
806215377 }
806315378
806415379 *buf++ = 'e';
807715392 @note The buffer must be large enough.
807815393 @note The result is NOT null-terminated.
807915394 */
8080 template <typename FloatType>
8081 char* to_chars(char* first, char* last, FloatType value)
15395 template<typename FloatType>
15396 JSON_HEDLEY_NON_NULL(1, 2)
15397 JSON_HEDLEY_RETURNS_NON_NULL
15398 char* to_chars(char* first, const char* last, FloatType value)
808215399 {
808315400 static_cast<void>(last); // maybe unused - fix warning
8084 assert(std::isfinite(value));
15401 JSON_ASSERT(std::isfinite(value));
808515402
808615403 // Use signbit(value) instead of (value < 0) since signbit works for -0.
808715404 if (std::signbit(value))
809915416 return first;
810015417 }
810115418
8102 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
15419 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
810315420
810415421 // Compute v = buffer * 10^decimal_exponent.
810515422 // The decimal digits are stored in the buffer, which needs to be interpreted
810915426 int decimal_exponent = 0;
811015427 dtoa_impl::grisu2(first, len, decimal_exponent, value);
811115428
8112 assert(len <= std::numeric_limits<FloatType>::max_digits10);
15429 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
811315430
811415431 // Format the buffer like printf("%.*g", prec, value)
811515432 constexpr int kMinExp = -4;
811615433 // Use digits10 here to increase compatibility with version 2.
811715434 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
811815435
8119 assert(last - first >= kMaxExp + 2);
8120 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
8121 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
15436 JSON_ASSERT(last - first >= kMaxExp + 2);
15437 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
15438 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
812215439
812315440 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
812415441 }
812615443 } // namespace detail
812715444 } // namespace nlohmann
812815445
15446 // #include <nlohmann/detail/exceptions.hpp>
15447
812915448 // #include <nlohmann/detail/macro_scope.hpp>
813015449
8131 // #include <nlohmann/detail/meta.hpp>
15450 // #include <nlohmann/detail/meta/cpp_future.hpp>
15451
15452 // #include <nlohmann/detail/output/binary_writer.hpp>
813215453
813315454 // #include <nlohmann/detail/output/output_adapters.hpp>
813415455
814315464 // serialization //
814415465 ///////////////////
814515466
8146 template <typename BasicJsonType>
15467 /// how to treat decoding errors
15468 enum class error_handler_t
15469 {
15470 strict, ///< throw a type_error exception in case of invalid UTF-8
15471 replace, ///< replace invalid UTF-8 sequences with U+FFFD
15472 ignore ///< ignore invalid UTF-8 sequences
15473 };
15474
15475 template<typename BasicJsonType>
814715476 class serializer
814815477 {
814915478 using string_t = typename BasicJsonType::string_t;
815015479 using number_float_t = typename BasicJsonType::number_float_t;
815115480 using number_integer_t = typename BasicJsonType::number_integer_t;
815215481 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8153 static constexpr uint8_t UTF8_ACCEPT = 0;
8154 static constexpr uint8_t UTF8_REJECT = 1;
8155
8156 public:
15482 using binary_char_t = typename BasicJsonType::binary_t::value_type;
15483 static constexpr std::uint8_t UTF8_ACCEPT = 0;
15484 static constexpr std::uint8_t UTF8_REJECT = 1;
15485
15486 public:
815715487 /*!
815815488 @param[in] s output stream to serialize to
815915489 @param[in] ichar indentation character to use
8160 */
8161 serializer(output_adapter_t<char> s, const char ichar)
8162 : o(std::move(s)), loc(cpt::localeconv()), thousands_sep(loc->thousands_sep == nullptr ? '\0' : *(loc->thousands_sep)),
8163 decimal_point(loc->decimal_point == nullptr ? '\0' : *(loc->decimal_point)), indent_char(ichar), indent_string(512, indent_char)
8164 {
8165 }
15490 @param[in] error_handler_ how to react on decoding errors
15491 */
15492 serializer(output_adapter_t<char> s, const char ichar,
15493 error_handler_t error_handler_ = error_handler_t::strict)
15494 : o(std::move(s))
15495 , loc(std::localeconv())
15496 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
15497 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
15498 , indent_char(ichar)
15499 , indent_string(512, indent_char)
15500 , error_handler(error_handler_)
15501 {}
816615502
816715503 // delete because of pointer members
816815504 serializer(const serializer&) = delete;
816915505 serializer& operator=(const serializer&) = delete;
15506 serializer(serializer&&) = delete;
15507 serializer& operator=(serializer&&) = delete;
15508 ~serializer() = default;
817015509
817115510 /*!
817215511 @brief internal implementation of the serialization function
817915518 - strings and object keys are escaped using `escape_string()`
818015519 - integer numbers are converted implicitly via `operator<<`
818115520 - floating-point numbers are converted to a string using `"%g"` format
8182
8183 @param[in] val value to serialize
8184 @param[in] pretty_print whether the output shall be pretty-printed
8185 @param[in] indent_step the indent level
8186 @param[in] current_indent the current indent level (only used internally)
8187 */
8188 void dump(const BasicJsonType& val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent = 0)
15521 - binary values are serialized as objects containing the subtype and the
15522 byte array
15523
15524 @param[in] val value to serialize
15525 @param[in] pretty_print whether the output shall be pretty-printed
15526 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
15527 in the output are escaped with `\uXXXX` sequences, and the result consists
15528 of ASCII characters only.
15529 @param[in] indent_step the indent level
15530 @param[in] current_indent the current indent level (only used internally)
15531 */
15532 void dump(const BasicJsonType& val,
15533 const bool pretty_print,
15534 const bool ensure_ascii,
15535 const unsigned int indent_step,
15536 const unsigned int current_indent = 0)
818915537 {
819015538 switch (val.m_type)
819115539 {
820315551
820415552 // variable to hold indentation for recursive calls
820515553 const auto new_indent = current_indent + indent_step;
8206 if (JSON_UNLIKELY(indent_string.size() < new_indent))
15554 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
820715555 {
820815556 indent_string.resize(indent_string.size() * 2, ' ');
820915557 }
822115569 }
822215570
822315571 // last element
8224 assert(i != val.m_value.object->cend());
8225 assert(std::next(i) == val.m_value.object->cend());
15572 JSON_ASSERT(i != val.m_value.object->cend());
15573 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
822615574 o->write_characters(indent_string.c_str(), new_indent);
822715575 o->write_character('\"');
822815576 dump_escaped(i->first, ensure_ascii);
824915597 }
825015598
825115599 // last element
8252 assert(i != val.m_value.object->cend());
8253 assert(std::next(i) == val.m_value.object->cend());
15600 JSON_ASSERT(i != val.m_value.object->cend());
15601 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
825415602 o->write_character('\"');
825515603 dump_escaped(i->first, ensure_ascii);
825615604 o->write_characters("\":", 2);
827615624
827715625 // variable to hold indentation for recursive calls
827815626 const auto new_indent = current_indent + indent_step;
8279 if (JSON_UNLIKELY(indent_string.size() < new_indent))
15627 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
828015628 {
828115629 indent_string.resize(indent_string.size() * 2, ' ');
828215630 }
828315631
828415632 // first n-1 elements
8285 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
15633 for (auto i = val.m_value.array->cbegin();
15634 i != val.m_value.array->cend() - 1; ++i)
828615635 {
828715636 o->write_characters(indent_string.c_str(), new_indent);
828815637 dump(*i, true, ensure_ascii, indent_step, new_indent);
829015639 }
829115640
829215641 // last element
8293 assert(not val.m_value.array->empty());
15642 JSON_ASSERT(!val.m_value.array->empty());
829415643 o->write_characters(indent_string.c_str(), new_indent);
829515644 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
829615645
830315652 o->write_character('[');
830415653
830515654 // first n-1 elements
8306 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
15655 for (auto i = val.m_value.array->cbegin();
15656 i != val.m_value.array->cend() - 1; ++i)
830715657 {
830815658 dump(*i, false, ensure_ascii, indent_step, current_indent);
830915659 o->write_character(',');
831015660 }
831115661
831215662 // last element
8313 assert(not val.m_value.array->empty());
15663 JSON_ASSERT(!val.m_value.array->empty());
831415664 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
831515665
831615666 o->write_character(']');
832415674 o->write_character('\"');
832515675 dump_escaped(*val.m_value.string, ensure_ascii);
832615676 o->write_character('\"');
15677 return;
15678 }
15679
15680 case value_t::binary:
15681 {
15682 if (pretty_print)
15683 {
15684 o->write_characters("{\n", 2);
15685
15686 // variable to hold indentation for recursive calls
15687 const auto new_indent = current_indent + indent_step;
15688 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15689 {
15690 indent_string.resize(indent_string.size() * 2, ' ');
15691 }
15692
15693 o->write_characters(indent_string.c_str(), new_indent);
15694
15695 o->write_characters("\"bytes\": [", 10);
15696
15697 if (!val.m_value.binary->empty())
15698 {
15699 for (auto i = val.m_value.binary->cbegin();
15700 i != val.m_value.binary->cend() - 1; ++i)
15701 {
15702 dump_integer(*i);
15703 o->write_characters(", ", 2);
15704 }
15705 dump_integer(val.m_value.binary->back());
15706 }
15707
15708 o->write_characters("],\n", 3);
15709 o->write_characters(indent_string.c_str(), new_indent);
15710
15711 o->write_characters("\"subtype\": ", 11);
15712 if (val.m_value.binary->has_subtype())
15713 {
15714 dump_integer(val.m_value.binary->subtype());
15715 }
15716 else
15717 {
15718 o->write_characters("null", 4);
15719 }
15720 o->write_character('\n');
15721 o->write_characters(indent_string.c_str(), current_indent);
15722 o->write_character('}');
15723 }
15724 else
15725 {
15726 o->write_characters("{\"bytes\":[", 10);
15727
15728 if (!val.m_value.binary->empty())
15729 {
15730 for (auto i = val.m_value.binary->cbegin();
15731 i != val.m_value.binary->cend() - 1; ++i)
15732 {
15733 dump_integer(*i);
15734 o->write_character(',');
15735 }
15736 dump_integer(val.m_value.binary->back());
15737 }
15738
15739 o->write_characters("],\"subtype\":", 12);
15740 if (val.m_value.binary->has_subtype())
15741 {
15742 dump_integer(val.m_value.binary->subtype());
15743 o->write_character('}');
15744 }
15745 else
15746 {
15747 o->write_characters("null}", 5);
15748 }
15749 }
832715750 return;
832815751 }
832915752
836915792 o->write_characters("null", 4);
837015793 return;
837115794 }
8372 }
8373 }
8374
8375 private:
15795
15796 default: // LCOV_EXCL_LINE
15797 JSON_ASSERT(false); // LCOV_EXCL_LINE
15798 }
15799 }
15800
15801 private:
837615802 /*!
837715803 @brief dump escaped string
837815804
838915815 */
839015816 void dump_escaped(const string_t& s, const bool ensure_ascii)
839115817 {
8392 uint32_t codepoint;
8393 uint8_t state = UTF8_ACCEPT;
8394 std::size_t bytes = 0; // number of bytes written to string_buffer
15818 std::uint32_t codepoint;
15819 std::uint8_t state = UTF8_ACCEPT;
15820 std::size_t bytes = 0; // number of bytes written to string_buffer
15821
15822 // number of bytes written at the point of the last valid byte
15823 std::size_t bytes_after_last_accept = 0;
15824 std::size_t undumped_chars = 0;
839515825
839615826 for (std::size_t i = 0; i < s.size(); ++i)
839715827 {
839915829
840015830 switch (decode(state, codepoint, byte))
840115831 {
8402 case UTF8_ACCEPT: // decode found a new code point
15832 case UTF8_ACCEPT: // decode found a new code point
840315833 {
840415834 switch (codepoint)
840515835 {
845615886 {
845715887 // escape control characters (0x00..0x1F) or, if
845815888 // ensure_ascii parameter is used, non-ASCII characters
8459 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
15889 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
846015890 {
846115891 if (codepoint <= 0xFFFF)
846215892 {
8463 snprintf(string_buffer.data() + bytes, 7, "\\u%04x", static_cast<uint16_t>(codepoint));
15893 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
15894 static_cast<std::uint16_t>(codepoint));
846415895 bytes += 6;
846515896 }
846615897 else
846715898 {
8468 snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
8469 static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
15899 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
15900 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
15901 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
847015902 bytes += 12;
847115903 }
847215904 }
848815920 o->write_characters(string_buffer.data(), bytes);
848915921 bytes = 0;
849015922 }
15923
15924 // remember the byte position of this accept
15925 bytes_after_last_accept = bytes;
15926 undumped_chars = 0;
849115927 break;
849215928 }
849315929
8494 case UTF8_REJECT: // decode found invalid UTF-8 byte
15930 case UTF8_REJECT: // decode found invalid UTF-8 byte
849515931 {
8496 std::stringstream ss;
8497 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte);
8498 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + cpt::to_string(i) + ": 0x" + ss.str()));
15932 switch (error_handler)
15933 {
15934 case error_handler_t::strict:
15935 {
15936 std::string sn(3, '\0');
15937 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
15938 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
15939 }
15940
15941 case error_handler_t::ignore:
15942 case error_handler_t::replace:
15943 {
15944 // in case we saw this character the first time, we
15945 // would like to read it again, because the byte
15946 // may be OK for itself, but just not OK for the
15947 // previous sequence
15948 if (undumped_chars > 0)
15949 {
15950 --i;
15951 }
15952
15953 // reset length buffer to the last accepted index;
15954 // thus removing/ignoring the invalid characters
15955 bytes = bytes_after_last_accept;
15956
15957 if (error_handler == error_handler_t::replace)
15958 {
15959 // add a replacement character
15960 if (ensure_ascii)
15961 {
15962 string_buffer[bytes++] = '\\';
15963 string_buffer[bytes++] = 'u';
15964 string_buffer[bytes++] = 'f';
15965 string_buffer[bytes++] = 'f';
15966 string_buffer[bytes++] = 'f';
15967 string_buffer[bytes++] = 'd';
15968 }
15969 else
15970 {
15971 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
15972 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
15973 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
15974 }
15975
15976 // write buffer and reset index; there must be 13 bytes
15977 // left, as this is the maximal number of bytes to be
15978 // written ("\uxxxx\uxxxx\0") for one code point
15979 if (string_buffer.size() - bytes < 13)
15980 {
15981 o->write_characters(string_buffer.data(), bytes);
15982 bytes = 0;
15983 }
15984
15985 bytes_after_last_accept = bytes;
15986 }
15987
15988 undumped_chars = 0;
15989
15990 // continue processing the string
15991 state = UTF8_ACCEPT;
15992 break;
15993 }
15994
15995 default: // LCOV_EXCL_LINE
15996 JSON_ASSERT(false); // LCOV_EXCL_LINE
15997 }
15998 break;
849915999 }
850016000
8501 default: // decode found yet incomplete multi-byte code point
16001 default: // decode found yet incomplete multi-byte code point
850216002 {
8503 if (not ensure_ascii)
16003 if (!ensure_ascii)
850416004 {
850516005 // code point will not be escaped - copy byte to buffer
850616006 string_buffer[bytes++] = s[i];
850716007 }
16008 ++undumped_chars;
850816009 break;
850916010 }
851016011 }
851116012 }
851216013
8513 if (JSON_LIKELY(state == UTF8_ACCEPT))
16014 // we finished processing the string
16015 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
851416016 {
851516017 // write buffer
851616018 if (bytes > 0)
852116023 else
852216024 {
852316025 // we finish reading, but do not accept: string was incomplete
8524 std::stringstream ss;
8525 ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(s.back()));
8526 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str()));
16026 switch (error_handler)
16027 {
16028 case error_handler_t::strict:
16029 {
16030 std::string sn(3, '\0');
16031 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
16032 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
16033 }
16034
16035 case error_handler_t::ignore:
16036 {
16037 // write all accepted bytes
16038 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16039 break;
16040 }
16041
16042 case error_handler_t::replace:
16043 {
16044 // write all accepted bytes
16045 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16046 // add a replacement character
16047 if (ensure_ascii)
16048 {
16049 o->write_characters("\\ufffd", 6);
16050 }
16051 else
16052 {
16053 o->write_characters("\xEF\xBF\xBD", 3);
16054 }
16055 break;
16056 }
16057
16058 default: // LCOV_EXCL_LINE
16059 JSON_ASSERT(false); // LCOV_EXCL_LINE
16060 }
16061 }
16062 }
16063
16064 /*!
16065 @brief count digits
16066
16067 Count the number of decimal (base 10) digits for an input unsigned integer.
16068
16069 @param[in] x unsigned integer number to count its digits
16070 @return number of decimal digits
16071 */
16072 inline unsigned int count_digits(number_unsigned_t x) noexcept
16073 {
16074 unsigned int n_digits = 1;
16075 for (;;)
16076 {
16077 if (x < 10)
16078 {
16079 return n_digits;
16080 }
16081 if (x < 100)
16082 {
16083 return n_digits + 1;
16084 }
16085 if (x < 1000)
16086 {
16087 return n_digits + 2;
16088 }
16089 if (x < 10000)
16090 {
16091 return n_digits + 3;
16092 }
16093 x = x / 10000u;
16094 n_digits += 4;
852716095 }
852816096 }
852916097
853616104 @param[in] x integer number (signed or unsigned) to dump
853716105 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
853816106 */
8539 template <typename NumberType,
8540 detail::enable_if_t<std::is_same<NumberType, number_unsigned_t>::value or std::is_same<NumberType, number_integer_t>::value, int> = 0>
16107 template < typename NumberType, detail::enable_if_t <
16108 std::is_same<NumberType, number_unsigned_t>::value ||
16109 std::is_same<NumberType, number_integer_t>::value ||
16110 std::is_same<NumberType, binary_char_t>::value,
16111 int > = 0 >
854116112 void dump_integer(NumberType x)
854216113 {
16114 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16115 {
16116 {
16117 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16118 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16119 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16120 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16121 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16122 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16123 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16124 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16125 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16126 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16127 }
16128 };
16129
854316130 // special case for "0"
854416131 if (x == 0)
854516132 {
854716134 return;
854816135 }
854916136
8550 const bool is_negative = (x <= 0) and (x != 0); // see issue #755
8551 std::size_t i = 0;
8552
8553 while (x != 0)
8554 {
8555 // spare 1 byte for '\0'
8556 assert(i < number_buffer.size() - 1);
8557
8558 const auto digit = std::labs(static_cast<long>(x % 10));
8559 number_buffer[i++] = static_cast<char>('0' + digit);
8560 x /= 10;
8561 }
16137 // use a pointer to fill the buffer
16138 auto buffer_ptr = number_buffer.begin();
16139
16140 const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
16141 number_unsigned_t abs_value;
16142
16143 unsigned int n_chars;
856216144
856316145 if (is_negative)
856416146 {
8565 // make sure there is capacity for the '-'
8566 assert(i < number_buffer.size() - 2);
8567 number_buffer[i++] = '-';
8568 }
8569
8570 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
8571 o->write_characters(number_buffer.data(), i);
16147 *buffer_ptr = '-';
16148 abs_value = remove_sign(static_cast<number_integer_t>(x));
16149
16150 // account one more byte for the minus sign
16151 n_chars = 1 + count_digits(abs_value);
16152 }
16153 else
16154 {
16155 abs_value = static_cast<number_unsigned_t>(x);
16156 n_chars = count_digits(abs_value);
16157 }
16158
16159 // spare 1 byte for '\0'
16160 JSON_ASSERT(n_chars < number_buffer.size() - 1);
16161
16162 // jump to the end to generate the string from backward
16163 // so we later avoid reversing the result
16164 buffer_ptr += n_chars;
16165
16166 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16167 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16168 while (abs_value >= 100)
16169 {
16170 const auto digits_index = static_cast<unsigned>((abs_value % 100));
16171 abs_value /= 100;
16172 *(--buffer_ptr) = digits_to_99[digits_index][1];
16173 *(--buffer_ptr) = digits_to_99[digits_index][0];
16174 }
16175
16176 if (abs_value >= 10)
16177 {
16178 const auto digits_index = static_cast<unsigned>(abs_value);
16179 *(--buffer_ptr) = digits_to_99[digits_index][1];
16180 *(--buffer_ptr) = digits_to_99[digits_index][0];
16181 }
16182 else
16183 {
16184 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
16185 }
16186
16187 o->write_characters(number_buffer.data(), n_chars);
857216188 }
857316189
857416190 /*!
858216198 void dump_float(number_float_t x)
858316199 {
858416200 // NaN / inf
8585 if (not std::isfinite(x))
16201 if (!std::isfinite(x))
858616202 {
858716203 o->write_characters("null", 4);
858816204 return;
859316209 // guaranteed to round-trip, using strtof and strtod, resp.
859416210 //
859516211 // NB: The test below works if <long double> == <double>.
8596 static constexpr bool is_ieee_single_or_double =
8597 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and
8598 std::numeric_limits<number_float_t>::max_exponent == 128) or
8599 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and
8600 std::numeric_limits<number_float_t>::max_exponent == 1024);
16212 static constexpr bool is_ieee_single_or_double
16213 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16214 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
860116215
860216216 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
860316217 }
861616230 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
861716231
861816232 // the actual conversion
8619 std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16233 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
862016234
862116235 // negative value indicates an error
8622 assert(len > 0);
16236 JSON_ASSERT(len > 0);
862316237 // check if buffer was large enough
8624 assert(static_cast<std::size_t>(len) < number_buffer.size());
16238 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
862516239
862616240 // erase thousands separator
862716241 if (thousands_sep != '\0')
862816242 {
8629 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
16243 const auto end = std::remove(number_buffer.begin(),
16244 number_buffer.begin() + len, thousands_sep);
863016245 std::fill(end, number_buffer.end(), '\0');
8631 assert((end - number_buffer.begin()) <= len);
16246 JSON_ASSERT((end - number_buffer.begin()) <= len);
863216247 len = (end - number_buffer.begin());
863316248 }
863416249
863516250 // convert decimal point to '.'
8636 if (decimal_point != '\0' and decimal_point != '.')
16251 if (decimal_point != '\0' && decimal_point != '.')
863716252 {
863816253 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
863916254 if (dec_pos != number_buffer.end())
864516260 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
864616261
864716262 // determine if need to append ".0"
8648 const bool value_is_int_like = std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, [](char c) { return (c == '.' or c == 'e'); });
16263 const bool value_is_int_like =
16264 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16265 [](char c)
16266 {
16267 return c == '.' || c == 'e';
16268 });
864916269
865016270 if (value_is_int_like)
865116271 {
867416294 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
867516295 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
867616296 */
8677 static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
8678 {
8679 static const std::array<uint8_t, 400> utf8d = {{
8680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
8681 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
8682 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
8683 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
8684 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
8685 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
8686 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
8687 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
8688 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
8689 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
8690 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
8691 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
8692 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
8693 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
8694 }};
8695
8696 const uint8_t type = utf8d[byte];
8697
8698 codep = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codep << 6) : static_cast<uint32_t>(0xff >> type) & (byte);
8699
8700 state = utf8d[256u + state * 16u + type];
16297 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16298 {
16299 static const std::array<std::uint8_t, 400> utf8d =
16300 {
16301 {
16302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16306 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16307 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16308 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16309 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16310 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16311 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16312 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16313 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16314 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16315 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16316 }
16317 };
16318
16319 const std::uint8_t type = utf8d[byte];
16320
16321 codep = (state != UTF8_ACCEPT)
16322 ? (byte & 0x3fu) | (codep << 6u)
16323 : (0xFFu >> type) & (byte);
16324
16325 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16326 JSON_ASSERT(index < 400);
16327 state = utf8d[index];
870116328 return state;
870216329 }
870316330
8704 private:
16331 /*
16332 * Overload to make the compiler happy while it is instantiating
16333 * dump_integer for number_unsigned_t.
16334 * Must never be called.
16335 */
16336 number_unsigned_t remove_sign(number_unsigned_t x)
16337 {
16338 JSON_ASSERT(false); // LCOV_EXCL_LINE
16339 return x; // LCOV_EXCL_LINE
16340 }
16341
16342 /*
16343 * Helper function for dump_integer
16344 *
16345 * This function takes a negative signed integer and returns its absolute
16346 * value as unsigned integer. The plus/minus shuffling is necessary as we can
16347 * not directly remove the sign of an arbitrary signed integer as the
16348 * absolute values of INT_MIN and INT_MAX are usually not the same. See
16349 * #1708 for details.
16350 */
16351 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16352 {
16353 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
16354 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16355 }
16356
16357 private:
870516358 /// the output of the serializer
870616359 output_adapter_t<char> o = nullptr;
870716360
872216375 const char indent_char;
872316376 /// the indentation string
872416377 string_t indent_string;
16378
16379 /// error_handler how to react on decoding errors
16380 const error_handler_t error_handler;
872516381 };
8726 }
8727 }
8728
8729 // #include <nlohmann/detail/json_ref.hpp>
8730
8731
8732 #include <initializer_list>
8733 #include <utility>
16382 } // namespace detail
16383 } // namespace nlohmann
16384
16385 // #include <nlohmann/detail/value_t.hpp>
16386
16387 // #include <nlohmann/json_fwd.hpp>
16388
16389 // #include <nlohmann/ordered_map.hpp>
16390
16391
16392 #include <functional> // less
16393 #include <memory> // allocator
16394 #include <utility> // pair
16395 #include <vector> // vector
873416396
873516397 namespace nlohmann
873616398 {
8737 namespace detail
16399
16400 /// ordered_map: a minimal map-like container that preserves insertion order
16401 /// for use within nlohmann::basic_json<ordered_map>
16402 template <class Key, class T, class IgnoredLess = std::less<Key>,
16403 class Allocator = std::allocator<std::pair<const Key, T>>>
16404 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
873816405 {
8739 template <typename BasicJsonType>
8740 class json_ref
8741 {
8742 public:
8743 using value_type = BasicJsonType;
8744
8745 json_ref(value_type&& value) : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
8746 {
8747 }
8748
8749 json_ref(const value_type& value) : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
8750 {
8751 }
8752
8753 json_ref(std::initializer_list<json_ref> init) : owned_value(init), value_ref(&owned_value), is_rvalue(true)
8754 {
8755 }
8756
8757 template <class... Args>
8758 json_ref(Args&&... args) : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
8759 {
8760 }
8761
8762 // class should be movable only
8763 json_ref(json_ref&&) = default;
8764 json_ref(const json_ref&) = delete;
8765 json_ref& operator=(const json_ref&) = delete;
8766
8767 value_type moved_or_copied() const
8768 {
8769 if (is_rvalue)
8770 {
8771 return std::move(*value_ref);
8772 }
8773 return *value_ref;
8774 }
8775
8776 value_type const& operator*() const
8777 {
8778 return *static_cast<value_type const*>(value_ref);
8779 }
8780
8781 value_type const* operator->() const
8782 {
8783 return static_cast<value_type const*>(value_ref);
8784 }
8785
8786 private:
8787 mutable value_type owned_value = nullptr;
8788 value_type* value_ref = nullptr;
8789 const bool is_rvalue;
16406 using key_type = Key;
16407 using mapped_type = T;
16408 using Container = std::vector<std::pair<const Key, T>, Allocator>;
16409 using typename Container::iterator;
16410 using typename Container::const_iterator;
16411 using typename Container::size_type;
16412 using typename Container::value_type;
16413
16414 // Explicit constructors instead of `using Container::Container`
16415 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
16416 ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
16417 template <class It>
16418 ordered_map(It first, It last, const Allocator& alloc = Allocator())
16419 : Container{first, last, alloc} {}
16420 ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
16421 : Container{init, alloc} {}
16422
16423 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
16424 {
16425 for (auto it = this->begin(); it != this->end(); ++it)
16426 {
16427 if (it->first == key)
16428 {
16429 return {it, false};
16430 }
16431 }
16432 Container::emplace_back(key, t);
16433 return {--this->end(), true};
16434 }
16435
16436 T& operator[](const Key& key)
16437 {
16438 return emplace(key, T{}).first->second;
16439 }
16440
16441 const T& operator[](const Key& key) const
16442 {
16443 return at(key);
16444 }
16445
16446 T& at(const Key& key)
16447 {
16448 for (auto it = this->begin(); it != this->end(); ++it)
16449 {
16450 if (it->first == key)
16451 {
16452 return it->second;
16453 }
16454 }
16455
16456 throw std::out_of_range("key not found");
16457 }
16458
16459 const T& at(const Key& key) const
16460 {
16461 for (auto it = this->begin(); it != this->end(); ++it)
16462 {
16463 if (it->first == key)
16464 {
16465 return it->second;
16466 }
16467 }
16468
16469 throw std::out_of_range("key not found");
16470 }
16471
16472 size_type erase(const Key& key)
16473 {
16474 for (auto it = this->begin(); it != this->end(); ++it)
16475 {
16476 if (it->first == key)
16477 {
16478 // Since we cannot move const Keys, re-construct them in place
16479 for (auto next = it; ++next != this->end(); ++it)
16480 {
16481 it->~value_type(); // Destroy but keep allocation
16482 new (&*it) value_type{std::move(*next)};
16483 }
16484 Container::pop_back();
16485 return 1;
16486 }
16487 }
16488 return 0;
16489 }
16490
16491 iterator erase(iterator pos)
16492 {
16493 auto it = pos;
16494
16495 // Since we cannot move const Keys, re-construct them in place
16496 for (auto next = it; ++next != this->end(); ++it)
16497 {
16498 it->~value_type(); // Destroy but keep allocation
16499 new (&*it) value_type{std::move(*next)};
16500 }
16501 Container::pop_back();
16502 return pos;
16503 }
16504
16505 size_type count(const Key& key) const
16506 {
16507 for (auto it = this->begin(); it != this->end(); ++it)
16508 {
16509 if (it->first == key)
16510 {
16511 return 1;
16512 }
16513 }
16514 return 0;
16515 }
16516
16517 iterator find(const Key& key)
16518 {
16519 for (auto it = this->begin(); it != this->end(); ++it)
16520 {
16521 if (it->first == key)
16522 {
16523 return it;
16524 }
16525 }
16526 return Container::end();
16527 }
16528
16529 const_iterator find(const Key& key) const
16530 {
16531 for (auto it = this->begin(); it != this->end(); ++it)
16532 {
16533 if (it->first == key)
16534 {
16535 return it;
16536 }
16537 }
16538 return Container::end();
16539 }
16540
16541 std::pair<iterator, bool> insert( value_type&& value )
16542 {
16543 return emplace(value.first, std::move(value.second));
16544 }
16545
16546 std::pair<iterator, bool> insert( const value_type& value )
16547 {
16548 for (auto it = this->begin(); it != this->end(); ++it)
16549 {
16550 if (it->first == value.first)
16551 {
16552 return {it, false};
16553 }
16554 }
16555 Container::push_back(value);
16556 return {--this->end(), true};
16557 }
879016558 };
8791 }
8792 }
8793
8794 // #include <nlohmann/detail/json_pointer.hpp>
8795
8796
8797 #include <cassert> // assert
8798 #include <numeric> // accumulate
8799 #include <string> // string
8800 #include <vector> // vector
8801
8802 // #include <nlohmann/detail/macro_scope.hpp>
8803
8804 // #include <nlohmann/detail/exceptions.hpp>
8805
8806 // #include <nlohmann/detail/value_t.hpp>
8807
8808
8809 namespace nlohmann
8810 {
8811 template <typename BasicJsonType>
8812 class json_pointer
8813 {
8814 // allow basic_json to access private members
8815 NLOHMANN_BASIC_JSON_TPL_DECLARATION
8816 friend class basic_json;
8817
8818 public:
8819 /*!
8820 @brief create JSON pointer
8821
8822 Create a JSON pointer according to the syntax described in
8823 [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
8824
8825 @param[in] s string representing the JSON pointer; if omitted, the empty
8826 string is assumed which references the whole JSON value
8827
8828 @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
8829 not begin with a slash (`/`); see example below
8830
8831 @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
8832 not followed by `0` (representing `~`) or `1` (representing `/`); see
8833 example below
8834
8835 @liveexample{The example shows the construction several valid JSON pointers
8836 as well as the exceptional behavior.,json_pointer}
8837
8838 @since version 2.0.0
8839 */
8840 explicit json_pointer(const std::string& s = "") : reference_tokens(split(s))
8841 {
8842 }
8843
8844 /*!
8845 @brief return a string representation of the JSON pointer
8846
8847 @invariant For each JSON pointer `ptr`, it holds:
8848 @code {.cpp}
8849 ptr == json_pointer(ptr.to_string());
8850 @endcode
8851
8852 @return a string representation of the JSON pointer
8853
8854 @liveexample{The example shows the result of `to_string`.,
8855 json_pointer__to_string}
8856
8857 @since version 2.0.0
8858 */
8859 std::string to_string() const noexcept
8860 {
8861 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), std::string{},
8862 [](const std::string& a, const std::string& b) { return a + "/" + escape(b); });
8863 }
8864
8865 /// @copydoc to_string()
8866 operator std::string() const
8867 {
8868 return to_string();
8869 }
8870
8871 /*!
8872 @param[in] s reference token to be converted into an array index
8873
8874 @return integer representation of @a s
8875
8876 @throw out_of_range.404 if string @a s could not be converted to an integer
8877 */
8878 static int array_index(const std::string& s)
8879 {
8880 std::size_t processed_chars = s.size();
8881 const int res = cpt::stoi(s);
8882
8883 // check if the string was completely read
8884 if (JSON_UNLIKELY(processed_chars != s.size()))
8885 {
8886 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
8887 }
8888
8889 return res;
8890 }
8891
8892 private:
8893 /*!
8894 @brief remove and return last reference pointer
8895 @throw out_of_range.405 if JSON pointer has no parent
8896 */
8897 std::string pop_back()
8898 {
8899 if (JSON_UNLIKELY(is_root()))
8900 {
8901 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
8902 }
8903
8904 auto last = reference_tokens.back();
8905 reference_tokens.pop_back();
8906 return last;
8907 }
8908
8909 /// return whether pointer points to the root document
8910 bool is_root() const
8911 {
8912 return reference_tokens.empty();
8913 }
8914
8915 json_pointer top() const
8916 {
8917 if (JSON_UNLIKELY(is_root()))
8918 {
8919 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
8920 }
8921
8922 json_pointer result = *this;
8923 result.reference_tokens = {reference_tokens[0]};
8924 return result;
8925 }
8926
8927 /*!
8928 @brief create and return a reference to the pointed to value
8929
8930 @complexity Linear in the number of reference tokens.
8931
8932 @throw parse_error.109 if array index is not a number
8933 @throw type_error.313 if value cannot be unflattened
8934 */
8935 BasicJsonType& get_and_create(BasicJsonType& j) const
8936 {
8937 using size_type = typename BasicJsonType::size_type;
8938 auto result = &j;
8939
8940 // in case no reference tokens exist, return a reference to the JSON value
8941 // j which will be overwritten by a primitive value
8942 for (const auto& reference_token : reference_tokens)
8943 {
8944 switch (result->m_type)
8945 {
8946 case detail::value_t::null:
8947 {
8948 if (reference_token == "0")
8949 {
8950 // start a new array if reference token is 0
8951 result = &result->operator[](0);
8952 }
8953 else
8954 {
8955 // start a new object otherwise
8956 result = &result->operator[](reference_token);
8957 }
8958 break;
8959 }
8960
8961 case detail::value_t::object:
8962 {
8963 // create an entry in the object
8964 result = &result->operator[](reference_token);
8965 break;
8966 }
8967
8968 case detail::value_t::array:
8969 {
8970 // create an entry in the array
8971 JSON_TRY
8972 {
8973 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
8974 }
8975 JSON_CATCH(std::invalid_argument&)
8976 {
8977 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
8978 }
8979 break;
8980 }
8981
8982 /*
8983 The following code is only reached if there exists a reference
8984 token _and_ the current value is primitive. In this case, we have
8985 an error situation, because primitive values may only occur as
8986 single value; that is, with an empty list of reference tokens.
8987 */
8988 default:
8989 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
8990 }
8991 }
8992
8993 return *result;
8994 }
8995
8996 /*!
8997 @brief return a reference to the pointed to value
8998
8999 @note This version does not throw if a value is not present, but tries to
9000 create nested values instead. For instance, calling this function
9001 with pointer `"/this/that"` on a null value is equivalent to calling
9002 `operator[]("this").operator[]("that")` on that value, effectively
9003 changing the null value to an object.
9004
9005 @param[in] ptr a JSON value
9006
9007 @return reference to the JSON value pointed to by the JSON pointer
9008
9009 @complexity Linear in the length of the JSON pointer.
9010
9011 @throw parse_error.106 if an array index begins with '0'
9012 @throw parse_error.109 if an array index was not a number
9013 @throw out_of_range.404 if the JSON pointer can not be resolved
9014 */
9015 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
9016 {
9017 using size_type = typename BasicJsonType::size_type;
9018 for (const auto& reference_token : reference_tokens)
9019 {
9020 // convert null values to arrays or objects before continuing
9021 if (ptr->m_type == detail::value_t::null)
9022 {
9023 // check if reference token is a number
9024 const bool nums = std::all_of(reference_token.begin(), reference_token.end(), [](const char x) { return (x >= '0' and x <= '9'); });
9025
9026 // change value to array for numbers or "-" or to object otherwise
9027 *ptr = (nums or reference_token == "-") ? detail::value_t::array : detail::value_t::object;
9028 }
9029
9030 switch (ptr->m_type)
9031 {
9032 case detail::value_t::object:
9033 {
9034 // use unchecked object access
9035 ptr = &ptr->operator[](reference_token);
9036 break;
9037 }
9038
9039 case detail::value_t::array:
9040 {
9041 // error condition (cf. RFC 6901, Sect. 4)
9042 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9043 {
9044 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
9045 }
9046
9047 if (reference_token == "-")
9048 {
9049 // explicitly treat "-" as index beyond the end
9050 ptr = &ptr->operator[](ptr->m_value.array->size());
9051 }
9052 else
9053 {
9054 // convert array index to number; unchecked access
9055 JSON_TRY
9056 {
9057 ptr = &ptr->operator[](static_cast<size_type>(array_index(reference_token)));
9058 }
9059 JSON_CATCH(std::invalid_argument&)
9060 {
9061 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9062 }
9063 }
9064 break;
9065 }
9066
9067 default:
9068 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9069 }
9070 }
9071
9072 return *ptr;
9073 }
9074
9075 /*!
9076 @throw parse_error.106 if an array index begins with '0'
9077 @throw parse_error.109 if an array index was not a number
9078 @throw out_of_range.402 if the array index '-' is used
9079 @throw out_of_range.404 if the JSON pointer can not be resolved
9080 */
9081 BasicJsonType& get_checked(BasicJsonType* ptr) const
9082 {
9083 using size_type = typename BasicJsonType::size_type;
9084 for (const auto& reference_token : reference_tokens)
9085 {
9086 switch (ptr->m_type)
9087 {
9088 case detail::value_t::object:
9089 {
9090 // note: at performs range check
9091 ptr = &ptr->at(reference_token);
9092 break;
9093 }
9094
9095 case detail::value_t::array:
9096 {
9097 if (JSON_UNLIKELY(reference_token == "-"))
9098 {
9099 // "-" always fails the range check
9100 JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + cpt::to_string(ptr->m_value.array->size()) + ") is out of range"));
9101 }
9102
9103 // error condition (cf. RFC 6901, Sect. 4)
9104 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9105 {
9106 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
9107 }
9108
9109 // note: at performs range check
9110 JSON_TRY
9111 {
9112 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
9113 }
9114 JSON_CATCH(std::invalid_argument&)
9115 {
9116 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9117 }
9118 break;
9119 }
9120
9121 default:
9122 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9123 }
9124 }
9125
9126 return *ptr;
9127 }
9128
9129 /*!
9130 @brief return a const reference to the pointed to value
9131
9132 @param[in] ptr a JSON value
9133
9134 @return const reference to the JSON value pointed to by the JSON
9135 pointer
9136
9137 @throw parse_error.106 if an array index begins with '0'
9138 @throw parse_error.109 if an array index was not a number
9139 @throw out_of_range.402 if the array index '-' is used
9140 @throw out_of_range.404 if the JSON pointer can not be resolved
9141 */
9142 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
9143 {
9144 using size_type = typename BasicJsonType::size_type;
9145 for (const auto& reference_token : reference_tokens)
9146 {
9147 switch (ptr->m_type)
9148 {
9149 case detail::value_t::object:
9150 {
9151 // use unchecked object access
9152 ptr = &ptr->operator[](reference_token);
9153 break;
9154 }
9155
9156 case detail::value_t::array:
9157 {
9158 if (JSON_UNLIKELY(reference_token == "-"))
9159 {
9160 // "-" cannot be used for const access
9161 JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + cpt::to_string(ptr->m_value.array->size()) + ") is out of range"));
9162 }
9163
9164 // error condition (cf. RFC 6901, Sect. 4)
9165 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9166 {
9167 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
9168 }
9169
9170 // use unchecked array access
9171 JSON_TRY
9172 {
9173 ptr = &ptr->operator[](static_cast<size_type>(array_index(reference_token)));
9174 }
9175 JSON_CATCH(std::invalid_argument&)
9176 {
9177 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9178 }
9179 break;
9180 }
9181
9182 default:
9183 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9184 }
9185 }
9186
9187 return *ptr;
9188 }
9189
9190 /*!
9191 @throw parse_error.106 if an array index begins with '0'
9192 @throw parse_error.109 if an array index was not a number
9193 @throw out_of_range.402 if the array index '-' is used
9194 @throw out_of_range.404 if the JSON pointer can not be resolved
9195 */
9196 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
9197 {
9198 using size_type = typename BasicJsonType::size_type;
9199 for (const auto& reference_token : reference_tokens)
9200 {
9201 switch (ptr->m_type)
9202 {
9203 case detail::value_t::object:
9204 {
9205 // note: at performs range check
9206 ptr = &ptr->at(reference_token);
9207 break;
9208 }
9209
9210 case detail::value_t::array:
9211 {
9212 if (JSON_UNLIKELY(reference_token == "-"))
9213 {
9214 // "-" always fails the range check
9215 JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + cpt::to_string(ptr->m_value.array->size()) + ") is out of range"));
9216 }
9217
9218 // error condition (cf. RFC 6901, Sect. 4)
9219 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
9220 {
9221 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'"));
9222 }
9223
9224 // note: at performs range check
9225 JSON_TRY
9226 {
9227 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
9228 }
9229 JSON_CATCH(std::invalid_argument&)
9230 {
9231 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
9232 }
9233 break;
9234 }
9235
9236 default:
9237 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
9238 }
9239 }
9240
9241 return *ptr;
9242 }
9243
9244 /*!
9245 @brief split the string input to reference tokens
9246
9247 @note This function is only called by the json_pointer constructor.
9248 All exceptions below are documented there.
9249
9250 @throw parse_error.107 if the pointer is not empty or begins with '/'
9251 @throw parse_error.108 if character '~' is not followed by '0' or '1'
9252 */
9253 static std::vector<std::string> split(const std::string& reference_string)
9254 {
9255 std::vector<std::string> result;
9256
9257 // special case: empty reference string -> no reference tokens
9258 if (reference_string.empty())
9259 {
9260 return result;
9261 }
9262
9263 // check if nonempty reference string begins with slash
9264 if (JSON_UNLIKELY(reference_string[0] != '/'))
9265 {
9266 JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'"));
9267 }
9268
9269 // extract the reference tokens:
9270 // - slash: position of the last read slash (or end of string)
9271 // - start: position after the previous slash
9272 for (
9273 // search for the first slash after the first character
9274 std::size_t slash = reference_string.find_first_of('/', 1),
9275 // set the beginning of the first reference token
9276 start = 1;
9277 // we can stop if start == string::npos+1 = 0
9278 start != 0;
9279 // set the beginning of the next reference token
9280 // (will eventually be 0 if slash == std::string::npos)
9281 start = slash + 1,
9282 // find next slash
9283 slash = reference_string.find_first_of('/', start))
9284 {
9285 // use the text between the beginning of the reference token
9286 // (start) and the last slash (slash).
9287 auto reference_token = reference_string.substr(start, slash - start);
9288
9289 // check reference tokens are properly escaped
9290 for (std::size_t pos = reference_token.find_first_of('~'); pos != std::string::npos; pos = reference_token.find_first_of('~', pos + 1))
9291 {
9292 assert(reference_token[pos] == '~');
9293
9294 // ~ must be followed by 0 or 1
9295 if (JSON_UNLIKELY(pos == reference_token.size() - 1 or (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1')))
9296 {
9297 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
9298 }
9299 }
9300
9301 // finally, store the reference token
9302 unescape(reference_token);
9303 result.push_back(reference_token);
9304 }
9305
9306 return result;
9307 }
9308
9309 /*!
9310 @brief replace all occurrences of a substring by another string
9311
9312 @param[in,out] s the string to manipulate; changed so that all
9313 occurrences of @a f are replaced with @a t
9314 @param[in] f the substring to replace with @a t
9315 @param[in] t the string to replace @a f
9316
9317 @pre The search string @a f must not be empty. **This precondition is
9318 enforced with an assertion.**
9319
9320 @since version 2.0.0
9321 */
9322 static void replace_substring(std::string& s, const std::string& f, const std::string& t)
9323 {
9324 assert(not f.empty());
9325 for (auto pos = s.find(f); // find first occurrence of f
9326 pos != std::string::npos; // make sure f was found
9327 s.replace(pos, f.size(), t), // replace with t, and
9328 pos = s.find(f, pos + t.size())) // find next occurrence of f
9329 {
9330 }
9331 }
9332
9333 /// escape "~"" to "~0" and "/" to "~1"
9334 static std::string escape(std::string s)
9335 {
9336 replace_substring(s, "~", "~0");
9337 replace_substring(s, "/", "~1");
9338 return s;
9339 }
9340
9341 /// unescape "~1" to tilde and "~0" to slash (order is important!)
9342 static void unescape(std::string& s)
9343 {
9344 replace_substring(s, "~1", "/");
9345 replace_substring(s, "~0", "~");
9346 }
9347
9348 /*!
9349 @param[in] reference_string the reference string to the current value
9350 @param[in] value the value to consider
9351 @param[in,out] result the result object to insert values to
9352
9353 @note Empty objects or arrays are flattened to `null`.
9354 */
9355 static void flatten(const std::string& reference_string, const BasicJsonType& value, BasicJsonType& result)
9356 {
9357 switch (value.m_type)
9358 {
9359 case detail::value_t::array:
9360 {
9361 if (value.m_value.array->empty())
9362 {
9363 // flatten empty array as null
9364 result[reference_string] = nullptr;
9365 }
9366 else
9367 {
9368 // iterate array and use index as reference string
9369 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
9370 {
9371 flatten(reference_string + "/" + cpt::to_string(i), value.m_value.array->operator[](i), result);
9372 }
9373 }
9374 break;
9375 }
9376
9377 case detail::value_t::object:
9378 {
9379 if (value.m_value.object->empty())
9380 {
9381 // flatten empty object as null
9382 result[reference_string] = nullptr;
9383 }
9384 else
9385 {
9386 // iterate object and use keys as reference string
9387 for (const auto& element : *value.m_value.object)
9388 {
9389 flatten(reference_string + "/" + escape(element.first), element.second, result);
9390 }
9391 }
9392 break;
9393 }
9394
9395 default:
9396 {
9397 // add primitive value with its reference string
9398 result[reference_string] = value;
9399 break;
9400 }
9401 }
9402 }
9403
9404 /*!
9405 @param[in] value flattened JSON
9406
9407 @return unflattened JSON
9408
9409 @throw parse_error.109 if array index is not a number
9410 @throw type_error.314 if value is not an object
9411 @throw type_error.315 if object values are not primitive
9412 @throw type_error.313 if value cannot be unflattened
9413 */
9414 static BasicJsonType unflatten(const BasicJsonType& value)
9415 {
9416 if (JSON_UNLIKELY(not value.is_object()))
9417 {
9418 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
9419 }
9420
9421 BasicJsonType result;
9422
9423 // iterate the JSON object values
9424 for (const auto& element : *value.m_value.object)
9425 {
9426 if (JSON_UNLIKELY(not element.second.is_primitive()))
9427 {
9428 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
9429 }
9430
9431 // assign value to reference pointed to by JSON pointer; Note that if
9432 // the JSON pointer is "" (i.e., points to the whole value), function
9433 // get_and_create returns a reference to result itself. An assignment
9434 // will then create a primitive value.
9435 json_pointer(element.first).get_and_create(result) = element.second;
9436 }
9437
9438 return result;
9439 }
9440
9441 friend bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept
9442 {
9443 return (lhs.reference_tokens == rhs.reference_tokens);
9444 }
9445
9446 friend bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept
9447 {
9448 return not(lhs == rhs);
9449 }
9450
9451 /// the reference tokens
9452 std::vector<std::string> reference_tokens;
9453 };
9454 }
9455
9456 // #include <nlohmann/adl_serializer.hpp>
9457
9458
9459 #include <utility>
9460
9461 // #include <nlohmann/detail/conversions/from_json.hpp>
9462
9463 // #include <nlohmann/detail/conversions/to_json.hpp>
9464
9465
9466 namespace nlohmann
9467 {
9468 template <typename, typename>
9469 struct adl_serializer
9470 {
9471 /*!
9472 @brief convert a JSON value to any value type
9473
9474 This function is usually called by the `get()` function of the
9475 @ref basic_json class (either explicit or via conversion operators).
9476
9477 @param[in] j JSON value to read from
9478 @param[in,out] val value to write to
9479 */
9480 template <typename BasicJsonType, typename ValueType>
9481 static void from_json(BasicJsonType&& j, ValueType& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
9482 {
9483 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
9484 }
9485
9486 /*!
9487 @brief convert any value type to a JSON value
9488
9489 This function is usually called by the constructors of the @ref basic_json
9490 class.
9491
9492 @param[in,out] j JSON value to write to
9493 @param[in] val value to read from
9494 */
9495 template <typename BasicJsonType, typename ValueType>
9496 static void to_json(BasicJsonType& j, ValueType&& val) noexcept(noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
9497 {
9498 ::nlohmann::to_json(j, std::forward<ValueType>(val));
9499 }
9500 };
9501 }
16559
16560 } // namespace nlohmann
950216561
950316562
950416563 /*!
952616585 `uint64_t` by default; will be used in @ref number_unsigned_t)
952716586 @tparam NumberFloatType type for JSON floating-point numbers (`double` by
952816587 default; will be used in @ref number_float_t)
16588 @tparam BinaryType type for packed binary data for compatibility with binary
16589 serialization formats (`std::vector<std::uint8_t>` by default; will be used in
16590 @ref binary_t)
952916591 @tparam AllocatorType type of the allocator to use (`std::allocator` by
953016592 default)
953116593 @tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
953316595
953416596 @requirement The class satisfies the following concept requirements:
953516597 - Basic
9536 - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
16598 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
953716599 JSON values can be default constructed. The result will be a JSON null
953816600 value.
9539 - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
16601 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
954016602 A JSON value can be constructed from an rvalue argument.
9541 - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
16603 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
954216604 A JSON value can be copy-constructed from an lvalue expression.
9543 - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
16605 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
954416606 A JSON value van be assigned from an rvalue argument.
9545 - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
16607 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
954616608 A JSON value can be copy-assigned from an lvalue expression.
9547 - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
16609 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
954816610 JSON values can be destructed.
954916611 - Layout
9550 - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
16612 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
955116613 JSON values have
9552 [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
16614 [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
955316615 All non-static data members are private and standard layout types, the
955416616 class has no virtual functions or (virtual) base classes.
955516617 - Library-wide
9556 - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
16618 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
955716619 JSON values can be compared with `==`, see @ref
955816620 operator==(const_reference,const_reference).
9559 - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
16621 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
956016622 JSON values can be compared with `<`, see @ref
956116623 operator<(const_reference,const_reference).
9562 - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
16624 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
956316625 Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
956416626 other compatible types, using unqualified function call @ref swap().
9565 - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
16627 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
956616628 JSON values can be compared against `std::nullptr_t` objects which are used
956716629 to model the `null` value.
956816630 - Container
9569 - [Container](http://en.cppreference.com/w/cpp/concept/Container):
16631 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
957016632 JSON values can be used like STL containers and provide iterator access.
9571 - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
16633 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
957216634 JSON values can be used like STL containers and provide reverse iterator
957316635 access.
957416636
958016642 The invariants are checked by member function assert_invariant().
958116643
958216644 @internal
9583 @note ObjectType trick from http://stackoverflow.com/a/9860911
16645 @note ObjectType trick from https://stackoverflow.com/a/9860911
958416646 @endinternal
958516647
958616648 @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
959316655 NLOHMANN_BASIC_JSON_TPL_DECLARATION
959416656 class basic_json
959516657 {
9596 private:
9597 template <detail::value_t>
9598 friend struct detail::external_constructor;
16658 private:
16659 template<detail::value_t> friend struct detail::external_constructor;
959916660 friend ::nlohmann::json_pointer<basic_json>;
9600 friend ::nlohmann::detail::parser<basic_json>;
16661
16662 template<typename BasicJsonType, typename InputType>
16663 friend class ::nlohmann::detail::parser;
960116664 friend ::nlohmann::detail::serializer<basic_json>;
9602 template <typename BasicJsonType>
16665 template<typename BasicJsonType>
960316666 friend class ::nlohmann::detail::iter_impl;
9604 template <typename BasicJsonType, typename CharType>
16667 template<typename BasicJsonType, typename CharType>
960516668 friend class ::nlohmann::detail::binary_writer;
9606 template <typename BasicJsonType>
16669 template<typename BasicJsonType, typename InputType, typename SAX>
960716670 friend class ::nlohmann::detail::binary_reader;
16671 template<typename BasicJsonType>
16672 friend class ::nlohmann::detail::json_sax_dom_parser;
16673 template<typename BasicJsonType>
16674 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
960816675
960916676 /// workaround type for MSVC
961016677 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
961116678
961216679 // convenience aliases for types residing in namespace detail;
9613 using lexer = ::nlohmann::detail::lexer<basic_json>;
9614 using parser = ::nlohmann::detail::parser<basic_json>;
16680 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
16681
16682 template<typename InputAdapterType>
16683 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
16684 InputAdapterType adapter,
16685 detail::parser_callback_t<basic_json>cb = nullptr,
16686 const bool allow_exceptions = true,
16687 const bool ignore_comments = false
16688 )
16689 {
16690 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
16691 std::move(cb), allow_exceptions, ignore_comments);
16692 }
961516693
961616694 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
9617 template <typename BasicJsonType>
16695 template<typename BasicJsonType>
961816696 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
9619 template <typename BasicJsonType>
16697 template<typename BasicJsonType>
962016698 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
9621 template <typename Iterator>
16699 template<typename Iterator>
962216700 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
9623 template <typename Base>
9624 using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
9625
9626 template <typename CharType>
16701 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
16702
16703 template<typename CharType>
962716704 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
962816705
9629 using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
9630 template <typename CharType>
9631 using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
16706 template<typename InputType>
16707 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
16708 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
963216709
963316710 using serializer = ::nlohmann::detail::serializer<basic_json>;
963416711
9635 public:
16712 public:
963616713 using value_t = detail::value_t;
9637 /// @copydoc nlohmann::json_pointer
16714 /// JSON Pointer, see @ref nlohmann::json_pointer
963816715 using json_pointer = ::nlohmann::json_pointer<basic_json>;
9639 template <typename T, typename SFINAE>
16716 template<typename T, typename SFINAE>
964016717 using json_serializer = JSONSerializer<T, SFINAE>;
16718 /// how to treat decoding errors
16719 using error_handler_t = detail::error_handler_t;
16720 /// how to treat CBOR tags
16721 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
964116722 /// helper type for initializer lists of basic_json values
964216723 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
16724
16725 using input_format_t = detail::input_format_t;
16726 /// SAX interface type, see @ref nlohmann::json_sax
16727 using json_sax_t = json_sax<basic_json>;
964316728
964416729 ////////////////
964516730 // exceptions //
972416809 @return JSON object holding version information
972516810 key | description
972616811 ----------- | ---------------
9727 `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family;
9728 possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
16812 `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
972916813 `copyright` | The copyright line for the library as string.
973016814 `name` | The name of the library as string.
973116815 `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
973216816 `url` | The URL of the project as string.
9733 `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic
9734 Versioning](http://semver.org), and `string` (the version string).
16817 `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
973516818
973616819 @liveexample{The following code shows an example output of the `meta()`
973716820 function.,meta}
974316826
974416827 @since 2.1.0
974516828 */
16829 JSON_HEDLEY_WARN_UNUSED_RESULT
974616830 static basic_json meta()
974716831 {
974816832 basic_json result;
974916833
9750 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
16834 result["copyright"] = "(C) 2013-2020 Niels Lohmann";
975116835 result["name"] = "JSON for Modern C++";
975216836 result["url"] = "https://github.com/nlohmann/json";
975316837 result["version"]["string"] =
9754 cpt::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + cpt::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + cpt::to_string(NLOHMANN_JSON_VERSION_PATCH);
16838 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
16839 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
16840 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
975516841 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
975616842 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
975716843 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
977316859 #elif defined(__clang__)
977416860 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
977516861 #elif defined(__GNUC__) || defined(__GNUG__)
9776 result["compiler"] = {{"family", "gcc"},
9777 {"version", cpt::to_string(__GNUC__) + "." + cpt::to_string(__GNUC_MINOR__) + "." + cpt::to_string(__GNUC_PATCHLEVEL__)}};
16862 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
977816863 #elif defined(__HP_cc) || defined(__HP_aCC)
977916864 result["compiler"] = "hp"
978016865 #elif defined(__IBMCPP__)
979016875 #endif
979116876
979216877 #ifdef __cplusplus
9793 result["compiler"]["c++"] = cpt::to_string(__cplusplus);
16878 result["compiler"]["c++"] = std::to_string(__cplusplus);
979416879 #else
979516880 result["compiler"]["c++"] = "unknown";
979616881 #endif
979816883 }
979916884
980016885
9801 ///////////////////////////
9802 // JSON value data types //
9803 ///////////////////////////
9804
9805 /// @name JSON value data types
9806 /// The data types to store a JSON value. These types are derived from
9807 /// the template arguments passed to class @ref basic_json.
9808 /// @{
16886 ///////////////////////////
16887 // JSON value data types //
16888 ///////////////////////////
16889
16890 /// @name JSON value data types
16891 /// The data types to store a JSON value. These types are derived from
16892 /// the template arguments passed to class @ref basic_json.
16893 /// @{
980916894
981016895 #if defined(JSON_HAS_CPP_14)
981116896 // Use transparent comparator if possible, combined with perfect forwarding
989816983 7159](http://rfc7159.net/rfc7159), because any order implements the
989916984 specified "unordered" nature of JSON objects.
990016985 */
9901 using object_t = ObjectType<StringType, basic_json, object_comparator_t, AllocatorType<std::pair<const StringType, basic_json>>>;
16986 using object_t = ObjectType<StringType,
16987 basic_json,
16988 object_comparator_t,
16989 AllocatorType<std::pair<const StringType,
16990 basic_json>>>;
990216991
990316992 /*!
990416993 @brief a type for an array
1023617325 */
1023717326 using number_float_t = NumberFloatType;
1023817327
17328 /*!
17329 @brief a type for a packed binary type
17330
17331 This type is a type designed to carry binary data that appears in various
17332 serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
17333 BSON's generic binary subtype. This type is NOT a part of standard JSON and
17334 exists solely for compatibility with these binary types. As such, it is
17335 simply defined as an ordered sequence of zero or more byte values.
17336
17337 Additionally, as an implementation detail, the subtype of the binary data is
17338 carried around as a `std::uint8_t`, which is compatible with both of the
17339 binary data formats that use binary subtyping, (though the specific
17340 numbering is incompatible with each other, and it is up to the user to
17341 translate between them).
17342
17343 [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
17344 as:
17345 > Major type 2: a byte string. The string's length in bytes is represented
17346 > following the rules for positive integers (major type 0).
17347
17348 [MessagePack's documentation on the bin type
17349 family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
17350 describes this type as:
17351 > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
17352 > in addition to the size of the byte array.
17353
17354 [BSON's specifications](http://bsonspec.org/spec.html) describe several
17355 binary types; however, this type is intended to represent the generic binary
17356 type which has the description:
17357 > Generic binary subtype - This is the most commonly used binary subtype and
17358 > should be the 'default' for drivers and tools.
17359
17360 None of these impose any limitations on the internal representation other
17361 than the basic unit of storage be some type of array whose parts are
17362 decomposable into bytes.
17363
17364 The default representation of this binary format is a
17365 `std::vector<std::uint8_t>`, which is a very common way to represent a byte
17366 array in modern C++.
17367
17368 #### Default type
17369
17370 The default values for @a BinaryType is `std::vector<std::uint8_t>`
17371
17372 #### Storage
17373
17374 Binary Arrays are stored as pointers in a @ref basic_json type. That is,
17375 for any access to array values, a pointer of the type `binary_t*` must be
17376 dereferenced.
17377
17378 #### Notes on subtypes
17379
17380 - CBOR
17381 - Binary values are represented as byte strings. No subtypes are
17382 supported and will be ignored when CBOR is written.
17383 - MessagePack
17384 - If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
17385 or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
17386 is used. For other sizes, the ext family (ext8, ext16, ext32) is used.
17387 The subtype is then added as singed 8-bit integer.
17388 - If no subtype is given, the bin family (bin8, bin16, bin32) is used.
17389 - BSON
17390 - If a subtype is given, it is used and added as unsigned 8-bit integer.
17391 - If no subtype is given, the generic binary subtype 0x00 is used.
17392
17393 @sa @ref binary -- create a binary array
17394
17395 @since version 3.8.0
17396 */
17397 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
1023917398 /// @}
1024017399
10241 private:
17400 private:
17401
1024217402 /// helper for exception-safe object creation
10243 template <typename T, typename... Args>
10244 static T* create(Args&&... args)
17403 template<typename T, typename... Args>
17404 JSON_HEDLEY_RETURNS_NON_NULL
17405 static T* create(Args&& ... args)
1024517406 {
1024617407 AllocatorType<T> alloc;
1024717408 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
1024817409
10249 auto deleter = [&](T* object) { AllocatorTraits::deallocate(alloc, object, 1); };
17410 auto deleter = [&](T * object)
17411 {
17412 AllocatorTraits::deallocate(alloc, object, 1);
17413 };
1025017414 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
1025117415 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
10252 assert(object != nullptr);
17416 JSON_ASSERT(object != nullptr);
1025317417 return object.release();
1025417418 }
1025517419
1027317437 number | number_integer | @ref number_integer_t
1027417438 number | number_unsigned | @ref number_unsigned_t
1027517439 number | number_float | @ref number_float_t
17440 binary | binary | pointer to @ref binary_t
1027617441 null | null | *no value is stored*
1027717442
1027817443 @note Variable-length types (objects, arrays, and strings) are stored as
1028117446
1028217447 @since version 1.0.0
1028317448 */
10284 union json_value {
17449 union json_value
17450 {
1028517451 /// object (stored with pointer to save storage)
1028617452 object_t* object;
1028717453 /// array (stored with pointer to save storage)
1028817454 array_t* array;
1028917455 /// string (stored with pointer to save storage)
1029017456 string_t* string;
17457 /// binary (stored with pointer to save storage)
17458 binary_t* binary;
1029117459 /// boolean
1029217460 boolean_t boolean;
1029317461 /// number (integer)
1030017468 /// default constructor (for null values)
1030117469 json_value() = default;
1030217470 /// constructor for booleans
10303 json_value(boolean_t v) noexcept : boolean(v)
10304 {
10305 }
17471 json_value(boolean_t v) noexcept : boolean(v) {}
1030617472 /// constructor for numbers (integer)
10307 json_value(number_integer_t v) noexcept : number_integer(v)
10308 {
10309 }
17473 json_value(number_integer_t v) noexcept : number_integer(v) {}
1031017474 /// constructor for numbers (unsigned)
10311 json_value(number_unsigned_t v) noexcept : number_unsigned(v)
10312 {
10313 }
17475 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1031417476 /// constructor for numbers (floating-point)
10315 json_value(number_float_t v) noexcept : number_float(v)
10316 {
10317 }
17477 json_value(number_float_t v) noexcept : number_float(v) {}
1031817478 /// constructor for empty values of a given type
1031917479 json_value(value_t t)
1032017480 {
1033817498 break;
1033917499 }
1034017500
17501 case value_t::binary:
17502 {
17503 binary = create<binary_t>();
17504 break;
17505 }
17506
1034117507 case value_t::boolean:
1034217508 {
1034317509 boolean = boolean_t(false);
1036417530
1036517531 case value_t::null:
1036617532 {
10367 object = nullptr; // silence warning, see #821
17533 object = nullptr; // silence warning, see #821
1036817534 break;
1036917535 }
1037017536
1037117537 default:
1037217538 {
10373 object = nullptr; // silence warning, see #821
10374 if (JSON_UNLIKELY(t == value_t::null))
17539 object = nullptr; // silence warning, see #821
17540 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
1037517541 {
10376 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.1.2")); // LCOV_EXCL_LINE
17542 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE
1037717543 }
1037817544 break;
1037917545 }
1041617582 array = create<array_t>(std::move(value));
1041717583 }
1041817584
17585 /// constructor for binary arrays
17586 json_value(const typename binary_t::container_type& value)
17587 {
17588 binary = create<binary_t>(value);
17589 }
17590
17591 /// constructor for rvalue binary arrays
17592 json_value(typename binary_t::container_type&& value)
17593 {
17594 binary = create<binary_t>(std::move(value));
17595 }
17596
17597 /// constructor for binary arrays (internal type)
17598 json_value(const binary_t& value)
17599 {
17600 binary = create<binary_t>(value);
17601 }
17602
17603 /// constructor for rvalue binary arrays (internal type)
17604 json_value(binary_t&& value)
17605 {
17606 binary = create<binary_t>(std::move(value));
17607 }
17608
1041917609 void destroy(value_t t) noexcept
1042017610 {
17611 // flatten the current json_value to a heap-allocated stack
17612 std::vector<basic_json> stack;
17613
17614 // move the top-level items to stack
17615 if (t == value_t::array)
17616 {
17617 stack.reserve(array->size());
17618 std::move(array->begin(), array->end(), std::back_inserter(stack));
17619 }
17620 else if (t == value_t::object)
17621 {
17622 stack.reserve(object->size());
17623 for (auto&& it : *object)
17624 {
17625 stack.push_back(std::move(it.second));
17626 }
17627 }
17628
17629 while (!stack.empty())
17630 {
17631 // move the last item to local variable to be processed
17632 basic_json current_item(std::move(stack.back()));
17633 stack.pop_back();
17634
17635 // if current_item is array/object, move
17636 // its children to the stack to be processed later
17637 if (current_item.is_array())
17638 {
17639 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
17640 std::back_inserter(stack));
17641
17642 current_item.m_value.array->clear();
17643 }
17644 else if (current_item.is_object())
17645 {
17646 for (auto&& it : *current_item.m_value.object)
17647 {
17648 stack.push_back(std::move(it.second));
17649 }
17650
17651 current_item.m_value.object->clear();
17652 }
17653
17654 // it's now safe that current_item get destructed
17655 // since it doesn't have any children
17656 }
17657
1042117658 switch (t)
1042217659 {
1042317660 case value_t::object:
1044417681 break;
1044517682 }
1044617683
17684 case value_t::binary:
17685 {
17686 AllocatorType<binary_t> alloc;
17687 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17688 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17689 break;
17690 }
17691
1044717692 default:
1044817693 {
1044917694 break;
1046317708 */
1046417709 void assert_invariant() const noexcept
1046517710 {
10466 assert(m_type != value_t::object or m_value.object != nullptr);
10467 assert(m_type != value_t::array or m_value.array != nullptr);
10468 assert(m_type != value_t::string or m_value.string != nullptr);
10469 }
10470
10471 public:
17711 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17712 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17713 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17714 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17715 }
17716
17717 public:
1047217718 //////////////////////////
1047317719 // JSON parser callback //
1047417720 //////////////////////////
1048817734
1048917735 @sa @ref parser_callback_t for more information and examples
1049017736 */
10491 using parse_event_t = typename parser::parse_event_t;
17737 using parse_event_t = detail::parse_event_t;
1049217738
1049317739 /*!
1049417740 @brief per-element parser callback type
1050617752
1050717753 parameter @a event | description | parameter @a depth | parameter @a parsed
1050817754 ------------------ | ----------- | ------------------ | -------------------
10509 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type
10510 discarded
17755 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
1051117756 parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
1051217757 parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
10513 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type
10514 discarded
17758 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
1051517759 parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
1051617760 parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
1051717761
1054117785
1054217786 @since version 1.0.0
1054317787 */
10544 using parser_callback_t = typename parser::parser_callback_t;
10545
17788 using parser_callback_t = detail::parser_callback_t<basic_json>;
1054617789
1054717790 //////////////////
1054817791 // constructors //
1056717810 number | `0`
1056817811 object | `{}`
1056917812 array | `[]`
17813 binary | empty array
1057017814
1057117815 @param[in] v the type of the value to create
1057217816
1058217826
1058317827 @since version 1.0.0
1058417828 */
10585 basic_json(const value_t v) : m_type(v), m_value(v)
17829 basic_json(const value_t v)
17830 : m_type(v), m_value(v)
1058617831 {
1058717832 assert_invariant();
1058817833 }
1060517850
1060617851 @since version 1.0.0
1060717852 */
10608 basic_json(std::nullptr_t = nullptr) noexcept : basic_json(value_t::null)
17853 basic_json(std::nullptr_t = nullptr) noexcept
17854 : basic_json(value_t::null)
1060917855 {
1061017856 assert_invariant();
1061117857 }
1063617882 @ref number_float_t, and all convertible number types such as `int`,
1063717883 `size_t`, `int64_t`, `float` or `double` can be used.
1063817884 - **boolean**: @ref boolean_t / `bool` can be used.
17885 - **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
17886 unfortunately because string literals cannot be distinguished from binary
17887 character arrays by the C++ type system, all types compatible with `const
17888 char*` will be directed to the string constructor instead. This is both
17889 for backwards compatibility, and due to the fact that a binary type is not
17890 a standard JSON type.
1063917891
1064017892 See the examples below.
1064117893
1066717919
1066817920 @since version 2.1.0
1066917921 */
10670 template <typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
10671 detail::enable_if_t<detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
10672 basic_json(CompatibleType&& val) noexcept(noexcept(JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
17922 template < typename CompatibleType,
17923 typename U = detail::uncvref_t<CompatibleType>,
17924 detail::enable_if_t <
17925 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17926 basic_json(CompatibleType && val) noexcept(noexcept(
17927 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17928 std::forward<CompatibleType>(val))))
1067317929 {
1067417930 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1067517931 assert_invariant();
1069917955 was provided), strong guarantee holds: if an exception is thrown, there are
1070017956 no changes to any JSON value.
1070117957
10702 @since version 3.1.2
10703 */
10704 template <typename BasicJsonType,
10705 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
17958 @since version 3.2.0
17959 */
17960 template < typename BasicJsonType,
17961 detail::enable_if_t <
17962 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
1070617963 basic_json(const BasicJsonType& val)
1070717964 {
1070817965 using other_boolean_t = typename BasicJsonType::boolean_t;
1071217969 using other_string_t = typename BasicJsonType::string_t;
1071317970 using other_object_t = typename BasicJsonType::object_t;
1071417971 using other_array_t = typename BasicJsonType::array_t;
17972 using other_binary_t = typename BasicJsonType::binary_t;
1071517973
1071617974 switch (val.type())
1071717975 {
1073617994 case value_t::array:
1073717995 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
1073817996 break;
17997 case value_t::binary:
17998 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
17999 break;
1073918000 case value_t::null:
1074018001 *this = nullptr;
1074118002 break;
1074218003 case value_t::discarded:
1074318004 m_type = value_t::discarded;
1074418005 break;
18006 default: // LCOV_EXCL_LINE
18007 JSON_ASSERT(false); // LCOV_EXCL_LINE
1074518008 }
1074618009 assert_invariant();
1074718010 }
1082018083
1082118084 @since version 1.0.0
1082218085 */
10823 basic_json(initializer_list_t init, bool type_deduction = true, value_t manual_type = value_t::array)
18086 basic_json(initializer_list_t init,
18087 bool type_deduction = true,
18088 value_t manual_type = value_t::array)
1082418089 {
1082518090 // check if each element is an array with two elements whose first
1082618091 // element is a string
10827 bool is_an_object = std::all_of(init.begin(), init.end(), [](const detail::json_ref<basic_json>& element_ref) {
10828 return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
18092 bool is_an_object = std::all_of(init.begin(), init.end(),
18093 [](const detail::json_ref<basic_json>& element_ref)
18094 {
18095 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
1082918096 });
1083018097
1083118098 // adjust type if type deduction is not wanted
10832 if (not type_deduction)
18099 if (!type_deduction)
1083318100 {
1083418101 // if array is wanted, do not create an object though possible
1083518102 if (manual_type == value_t::array)
1083818105 }
1083918106
1084018107 // if object is wanted but impossible, throw an exception
10841 if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
18108 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
1084218109 {
1084318110 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
1084418111 }
1085018117 m_type = value_t::object;
1085118118 m_value = value_t::object;
1085218119
10853 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref) {
18120 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
18121 {
1085418122 auto element = element_ref.moved_or_copied();
10855 m_value.object->emplace(std::move(*((*element.m_value.array)[0].m_value.string)), std::move((*element.m_value.array)[1]));
18123 m_value.object->emplace(
18124 std::move(*((*element.m_value.array)[0].m_value.string)),
18125 std::move((*element.m_value.array)[1]));
1085618126 });
1085718127 }
1085818128 else
1086318133 }
1086418134
1086518135 assert_invariant();
18136 }
18137
18138 /*!
18139 @brief explicitly create a binary array (without subtype)
18140
18141 Creates a JSON binary array value from a given binary container. Binary
18142 values are part of various binary formats, such as CBOR, MessagePack, and
18143 BSON. This constructor is used to create a value for serialization to those
18144 formats.
18145
18146 @note Note, this function exists because of the difficulty in correctly
18147 specifying the correct template overload in the standard value ctor, as both
18148 JSON arrays and JSON binary arrays are backed with some form of a
18149 `std::vector`. Because JSON binary arrays are a non-standard extension it
18150 was decided that it would be best to prevent automatic initialization of a
18151 binary array type, for backwards compatibility and so it does not happen on
18152 accident.
18153
18154 @param[in] init container containing bytes to use as binary type
18155
18156 @return JSON binary array value
18157
18158 @complexity Linear in the size of @a init.
18159
18160 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18161 changes to any JSON value.
18162
18163 @since version 3.8.0
18164 */
18165 JSON_HEDLEY_WARN_UNUSED_RESULT
18166 static basic_json binary(const typename binary_t::container_type& init)
18167 {
18168 auto res = basic_json();
18169 res.m_type = value_t::binary;
18170 res.m_value = init;
18171 return res;
18172 }
18173
18174 /*!
18175 @brief explicitly create a binary array (with subtype)
18176
18177 Creates a JSON binary array value from a given binary container. Binary
18178 values are part of various binary formats, such as CBOR, MessagePack, and
18179 BSON. This constructor is used to create a value for serialization to those
18180 formats.
18181
18182 @note Note, this function exists because of the difficulty in correctly
18183 specifying the correct template overload in the standard value ctor, as both
18184 JSON arrays and JSON binary arrays are backed with some form of a
18185 `std::vector`. Because JSON binary arrays are a non-standard extension it
18186 was decided that it would be best to prevent automatic initialization of a
18187 binary array type, for backwards compatibility and so it does not happen on
18188 accident.
18189
18190 @param[in] init container containing bytes to use as binary type
18191 @param[in] subtype subtype to use in MessagePack and BSON
18192
18193 @return JSON binary array value
18194
18195 @complexity Linear in the size of @a init.
18196
18197 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18198 changes to any JSON value.
18199
18200 @since version 3.8.0
18201 */
18202 JSON_HEDLEY_WARN_UNUSED_RESULT
18203 static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype)
18204 {
18205 auto res = basic_json();
18206 res.m_type = value_t::binary;
18207 res.m_value = binary_t(init, subtype);
18208 return res;
18209 }
18210
18211 /// @copydoc binary(const typename binary_t::container_type&)
18212 JSON_HEDLEY_WARN_UNUSED_RESULT
18213 static basic_json binary(typename binary_t::container_type&& init)
18214 {
18215 auto res = basic_json();
18216 res.m_type = value_t::binary;
18217 res.m_value = std::move(init);
18218 return res;
18219 }
18220
18221 /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t)
18222 JSON_HEDLEY_WARN_UNUSED_RESULT
18223 static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype)
18224 {
18225 auto res = basic_json();
18226 res.m_type = value_t::binary;
18227 res.m_value = binary_t(std::move(init), subtype);
18228 return res;
1086618229 }
1086718230
1086818231 /*!
1090218265
1090318266 @since version 1.0.0
1090418267 */
18268 JSON_HEDLEY_WARN_UNUSED_RESULT
1090518269 static basic_json array(initializer_list_t init = {})
1090618270 {
1090718271 return basic_json(init, false, value_t::array);
1094518309
1094618310 @since version 1.0.0
1094718311 */
18312 JSON_HEDLEY_WARN_UNUSED_RESULT
1094818313 static basic_json object(initializer_list_t init = {})
1094918314 {
1095018315 return basic_json(init, false, value_t::object);
1097218337
1097318338 @since version 1.0.0
1097418339 */
10975 basic_json(size_type cnt, const basic_json& val) : m_type(value_t::array)
18340 basic_json(size_type cnt, const basic_json& val)
18341 : m_type(value_t::array)
1097618342 {
1097718343 m_value.array = create<array_t>(cnt, val);
1097818344 assert_invariant();
1101018376 @warning A precondition is enforced with a runtime assertion that will
1101118377 result in calling `std::abort` if this precondition is not met.
1101218378 Assertions can be disabled by defining `NDEBUG` at compile time.
11013 See http://en.cppreference.com/w/cpp/error/assert for more
18379 See https://en.cppreference.com/w/cpp/error/assert for more
1101418380 information.
1101518381
1101618382 @throw invalid_iterator.201 if iterators @a first and @a last are not
1103318399
1103418400 @since version 1.0.0
1103518401 */
11036 template <class InputIT, typename std::enable_if<std::is_same<InputIT, typename basic_json_t::iterator>::value or
11037 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
11038 int>::type = 0>
18402 template < class InputIT, typename std::enable_if <
18403 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18404 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
1103918405 basic_json(InputIT first, InputIT last)
1104018406 {
11041 assert(first.m_object != nullptr);
11042 assert(last.m_object != nullptr);
18407 JSON_ASSERT(first.m_object != nullptr);
18408 JSON_ASSERT(last.m_object != nullptr);
1104318409
1104418410 // make sure iterator fits the current value
11045 if (JSON_UNLIKELY(first.m_object != last.m_object))
18411 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1104618412 {
1104718413 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
1104818414 }
1105918425 case value_t::number_unsigned:
1106018426 case value_t::string:
1106118427 {
11062 if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()))
18428 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18429 || !last.m_it.primitive_iterator.is_end()))
1106318430 {
1106418431 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
1106518432 }
1110418471
1110518472 case value_t::object:
1110618473 {
11107 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
18474 m_value.object = create<object_t>(first.m_it.object_iterator,
18475 last.m_it.object_iterator);
1110818476 break;
1110918477 }
1111018478
1111118479 case value_t::array:
1111218480 {
11113 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
18481 m_value.array = create<array_t>(first.m_it.array_iterator,
18482 last.m_it.array_iterator);
1111418483 break;
1111518484 }
1111618485
18486 case value_t::binary:
18487 {
18488 m_value = *first.m_object->m_value.binary;
18489 break;
18490 }
18491
1111718492 default:
11118 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name())));
18493 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
18494 std::string(first.m_object->type_name())));
1111918495 }
1112018496
1112118497 assert_invariant();
1112618502 // other constructors and destructor //
1112718503 ///////////////////////////////////////
1112818504
11129 /// @private
11130 basic_json(const detail::json_ref<basic_json>& ref) : basic_json(ref.moved_or_copied())
11131 {
11132 }
18505 template<typename JsonRef,
18506 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18507 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18508 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
1113318509
1113418510 /*!
1113518511 @brief copy constructor
1114618522 changes to any JSON value.
1114718523
1114818524 @requirement This function helps `basic_json` satisfying the
11149 [Container](http://en.cppreference.com/w/cpp/concept/Container)
18525 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1115018526 requirements:
1115118527 - The complexity is linear.
1115218528 - As postcondition, it holds: `other == basic_json(other)`.
1115618532
1115718533 @since version 1.0.0
1115818534 */
11159 basic_json(const basic_json& other) : m_type(other.m_type)
18535 basic_json(const basic_json& other)
18536 : m_type(other.m_type)
1116018537 {
1116118538 // check of passed value is valid
1116218539 other.assert_invariant();
1120218579 case value_t::number_float:
1120318580 {
1120418581 m_value = other.m_value.number_float;
18582 break;
18583 }
18584
18585 case value_t::binary:
18586 {
18587 m_value = *other.m_value.binary;
1120518588 break;
1120618589 }
1120718590
1123018613 exceptions.
1123118614
1123218615 @requirement This function helps `basic_json` satisfying the
11233 [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible)
18616 [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
1123418617 requirements.
1123518618
1123618619 @liveexample{The code below shows the move constructor explicitly called
1123818621
1123918622 @since version 1.0.0
1124018623 */
11241 basic_json(basic_json&& other) noexcept : m_type(std::move(other.m_type)), m_value(std::move(other.m_value))
18624 basic_json(basic_json&& other) noexcept
18625 : m_type(std::move(other.m_type)),
18626 m_value(std::move(other.m_value))
1124218627 {
1124318628 // check that passed value is valid
1124418629 other.assert_invariant();
1126218647 @complexity Linear.
1126318648
1126418649 @requirement This function helps `basic_json` satisfying the
11265 [Container](http://en.cppreference.com/w/cpp/concept/Container)
18650 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1126618651 requirements:
1126718652 - The complexity is linear.
1126818653
1127318658
1127418659 @since version 1.0.0
1127518660 */
11276 reference&
11277 operator=(basic_json other) noexcept(std::is_nothrow_move_constructible<value_t>::value and std::is_nothrow_move_assignable<value_t>::value and
11278 std::is_nothrow_move_constructible<json_value>::value and std::is_nothrow_move_assignable<json_value>::value)
18661 basic_json& operator=(basic_json other) noexcept (
18662 std::is_nothrow_move_constructible<value_t>::value&&
18663 std::is_nothrow_move_assignable<value_t>::value&&
18664 std::is_nothrow_move_constructible<json_value>::value&&
18665 std::is_nothrow_move_assignable<json_value>::value
18666 )
1127918667 {
1128018668 // check that passed value is valid
1128118669 other.assert_invariant();
1129618684 @complexity Linear.
1129718685
1129818686 @requirement This function helps `basic_json` satisfying the
11299 [Container](http://en.cppreference.com/w/cpp/concept/Container)
18687 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1130018688 requirements:
1130118689 - The complexity is linear.
1130218690 - All stored elements are destroyed and all memory is freed.
1131118699
1131218700 /// @}
1131318701
11314 public:
18702 public:
1131518703 ///////////////////////
1131618704 // object inspection //
1131718705 ///////////////////////
1133618724 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
1133718725 in the output are escaped with `\uXXXX` sequences, and the result consists
1133818726 of ASCII characters only.
18727 @param[in] error_handler how to react on decoding errors; there are three
18728 possible values: `strict` (throws and exception in case a decoding error
18729 occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
18730 and `ignore` (ignore invalid UTF-8 sequences during serialization; all
18731 bytes are copied to the output unchanged).
1133918732
1134018733 @return string containing the serialization of the JSON value
1134118734
1134218735 @throw type_error.316 if a string stored inside the JSON value is not
11343 UTF-8 encoded
18736 UTF-8 encoded and @a error_handler is set to strict
18737
18738 @note Binary values are serialized as object containing two keys:
18739 - "bytes": an array of bytes as integers
18740 - "subtype": the subtype as integer or "null" if the binary has no subtype
1134418741
1134518742 @complexity Linear.
1134618743
1135418751 @see https://docs.python.org/2/library/json.html#json.dump
1135518752
1135618753 @since version 1.0.0; indentation character @a indent_char, option
11357 @a ensure_ascii and exceptions added in version 3.0.0
11358 */
11359 string_t dump(const int indent = -1, const char indent_char = ' ', const bool ensure_ascii = false) const
18754 @a ensure_ascii and exceptions added in version 3.0.0; error
18755 handlers added in version 3.4.0; serialization of binary values added
18756 in version 3.8.0.
18757 */
18758 string_t dump(const int indent = -1,
18759 const char indent_char = ' ',
18760 const bool ensure_ascii = false,
18761 const error_handler_t error_handler = error_handler_t::strict) const
1136018762 {
1136118763 string_t result;
11362 serializer s(detail::output_adapter<char, string_t>(result), indent_char);
18764 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
1136318765
1136418766 if (indent >= 0)
1136518767 {
1139018792 number (floating-point) | value_t::number_float
1139118793 object | value_t::object
1139218794 array | value_t::array
18795 binary | value_t::binary
1139318796 discarded | value_t::discarded
1139418797
1139518798 @complexity Constant.
1143218835 @sa @ref is_string() -- returns whether JSON value is a string
1143318836 @sa @ref is_boolean() -- returns whether JSON value is a boolean
1143418837 @sa @ref is_number() -- returns whether JSON value is a number
18838 @sa @ref is_binary() -- returns whether JSON value is a binary array
1143518839
1143618840 @since version 1.0.0
1143718841 */
1143818842 constexpr bool is_primitive() const noexcept
1143918843 {
11440 return is_null() or is_string() or is_boolean() or is_number();
18844 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
1144118845 }
1144218846
1144318847 /*!
1146418868 */
1146518869 constexpr bool is_structured() const noexcept
1146618870 {
11467 return is_array() or is_object();
18871 return is_array() || is_object();
1146818872 }
1146918873
1147018874 /*!
1148618890 */
1148718891 constexpr bool is_null() const noexcept
1148818892 {
11489 return (m_type == value_t::null);
18893 return m_type == value_t::null;
1149018894 }
1149118895
1149218896 /*!
1150818912 */
1150918913 constexpr bool is_boolean() const noexcept
1151018914 {
11511 return (m_type == value_t::boolean);
18915 return m_type == value_t::boolean;
1151218916 }
1151318917
1151418918 /*!
1153818942 */
1153918943 constexpr bool is_number() const noexcept
1154018944 {
11541 return is_number_integer() or is_number_float();
18945 return is_number_integer() || is_number_float();
1154218946 }
1154318947
1154418948 /*!
1156718971 */
1156818972 constexpr bool is_number_integer() const noexcept
1156918973 {
11570 return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
18974 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
1157118975 }
1157218976
1157318977 /*!
1159518999 */
1159619000 constexpr bool is_number_unsigned() const noexcept
1159719001 {
11598 return (m_type == value_t::number_unsigned);
19002 return m_type == value_t::number_unsigned;
1159919003 }
1160019004
1160119005 /*!
1162319027 */
1162419028 constexpr bool is_number_float() const noexcept
1162519029 {
11626 return (m_type == value_t::number_float);
19030 return m_type == value_t::number_float;
1162719031 }
1162819032
1162919033 /*!
1164519049 */
1164619050 constexpr bool is_object() const noexcept
1164719051 {
11648 return (m_type == value_t::object);
19052 return m_type == value_t::object;
1164919053 }
1165019054
1165119055 /*!
1166719071 */
1166819072 constexpr bool is_array() const noexcept
1166919073 {
11670 return (m_type == value_t::array);
19074 return m_type == value_t::array;
1167119075 }
1167219076
1167319077 /*!
1168919093 */
1169019094 constexpr bool is_string() const noexcept
1169119095 {
11692 return (m_type == value_t::string);
19096 return m_type == value_t::string;
19097 }
19098
19099 /*!
19100 @brief return whether value is a binary array
19101
19102 This function returns true if and only if the JSON value is a binary array.
19103
19104 @return `true` if type is binary array, `false` otherwise.
19105
19106 @complexity Constant.
19107
19108 @exceptionsafety No-throw guarantee: this member function never throws
19109 exceptions.
19110
19111 @liveexample{The following code exemplifies `is_binary()` for all JSON
19112 types.,is_binary}
19113
19114 @since version 3.8.0
19115 */
19116 constexpr bool is_binary() const noexcept
19117 {
19118 return m_type == value_t::binary;
1169319119 }
1169419120
1169519121 /*!
1171619142 */
1171719143 constexpr bool is_discarded() const noexcept
1171819144 {
11719 return (m_type == value_t::discarded);
19145 return m_type == value_t::discarded;
1172019146 }
1172119147
1172219148 /*!
1174719173
1174819174 /// @}
1174919175
11750 private:
19176 private:
1175119177 //////////////////
1175219178 // value access //
1175319179 //////////////////
1175519181 /// get a boolean (explicit)
1175619182 boolean_t get_impl(boolean_t* /*unused*/) const
1175719183 {
11758 if (JSON_LIKELY(is_boolean()))
19184 if (JSON_HEDLEY_LIKELY(is_boolean()))
1175919185 {
1176019186 return m_value.boolean;
1176119187 }
1184719273 return is_number_float() ? &m_value.number_float : nullptr;
1184819274 }
1184919275
19276 /// get a pointer to the value (binary)
19277 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
19278 {
19279 return is_binary() ? m_value.binary : nullptr;
19280 }
19281
19282 /// get a pointer to the value (binary)
19283 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
19284 {
19285 return is_binary() ? m_value.binary : nullptr;
19286 }
19287
1185019288 /*!
1185119289 @brief helper function to implement get_ref()
1185219290
1185819296 @throw type_error.303 if ReferenceType does not match underlying value
1185919297 type of the current JSON
1186019298 */
11861 template <typename ReferenceType, typename ThisType>
19299 template<typename ReferenceType, typename ThisType>
1186219300 static ReferenceType get_ref_impl(ThisType& obj)
1186319301 {
1186419302 // delegate the call to get_ptr<>()
1186519303 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
1186619304
11867 if (JSON_LIKELY(ptr != nullptr))
19305 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
1186819306 {
1186919307 return *ptr;
1187019308 }
1187219310 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
1187319311 }
1187419312
11875 public:
19313 public:
1187619314 /// @name value access
1187719315 /// Direct access to the stored value of a JSON value.
1187819316 /// @{
1189119329
1189219330 @since version 2.1.0
1189319331 */
11894 template <typename BasicJsonType, detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value, int> = 0>
19332 template<typename BasicJsonType, detail::enable_if_t<
19333 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
19334 int> = 0>
1189519335 basic_json get() const
1189619336 {
1189719337 return *this;
1191019350 @complexity Depending on the implementation of the called `from_json()`
1191119351 method.
1191219352
11913 @since version 3.1.2
11914 */
11915 template <typename BasicJsonType,
11916 detail::enable_if_t<not std::is_same<BasicJsonType, basic_json>::value and detail::is_basic_json<BasicJsonType>::value, int> = 0>
19353 @since version 3.2.0
19354 */
19355 template < typename BasicJsonType, detail::enable_if_t <
19356 !std::is_same<BasicJsonType, basic_json>::value&&
19357 detail::is_basic_json<BasicJsonType>::value, int > = 0 >
1191719358 BasicJsonType get() const
1191819359 {
1191919360 return *this;
1192319364 @brief get a value (explicit)
1192419365
1192519366 Explicit type conversion between the JSON value and a compatible value
11926 which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
11927 and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
19367 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19368 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1192819369 The value is converted by calling the @ref json_serializer<ValueType>
1192919370 `from_json()` method.
1193019371
1195819399
1195919400 @since version 2.1.0
1196019401 */
11961 template <typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
11962 detail::enable_if_t<not detail::is_basic_json<ValueType>::value and detail::has_from_json<basic_json_t, ValueType>::value and
11963 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
11964 int> = 0>
11965 ValueType get() const noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
19402 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19403 detail::enable_if_t <
19404 !detail::is_basic_json<ValueType>::value &&
19405 detail::has_from_json<basic_json_t, ValueType>::value &&
19406 !detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19407 int > = 0 >
19408 ValueType get() const noexcept(noexcept(
19409 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
1196619410 {
1196719411 // we cannot static_assert on ValueTypeCV being non-const, because
1196819412 // there is support for get<const basic_json_t>(), which is why we
1196919413 // still need the uncvref
11970 static_assert(not std::is_reference<ValueTypeCV>::value, "get() cannot be used with reference types, you might want to use get_ref()");
11971 static_assert(std::is_default_constructible<ValueType>::value, "types must be DefaultConstructible when used with get()");
19414 static_assert(!std::is_reference<ValueTypeCV>::value,
19415 "get() cannot be used with reference types, you might want to use get_ref()");
19416 static_assert(std::is_default_constructible<ValueType>::value,
19417 "types must be DefaultConstructible when used with get()");
1197219418
1197319419 ValueType ret;
1197419420 JSONSerializer<ValueType>::from_json(*this, ret);
1197919425 @brief get a value (explicit); special case
1198019426
1198119427 Explicit type conversion between the JSON value and a compatible value
11982 which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
11983 and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
19428 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19429 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1198419430 The value is converted by calling the @ref json_serializer<ValueType>
1198519431 `from_json()` method.
1198619432
1200619452
1200719453 @since version 2.1.0
1200819454 */
19455 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19456 detail::enable_if_t < !std::is_same<basic_json_t, ValueType>::value &&
19457 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19458 int > = 0 >
19459 ValueType get() const noexcept(noexcept(
19460 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
19461 {
19462 static_assert(!std::is_reference<ValueTypeCV>::value,
19463 "get() cannot be used with reference types, you might want to use get_ref()");
19464 return JSONSerializer<ValueType>::from_json(*this);
19465 }
19466
19467 /*!
19468 @brief get a value (explicit)
19469
19470 Explicit type conversion between the JSON value and a compatible value.
19471 The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
19472 `from_json()` method.
19473
19474 The function is equivalent to executing
19475 @code {.cpp}
19476 ValueType v;
19477 JSONSerializer<ValueType>::from_json(*this, v);
19478 @endcode
19479
19480 This overloads is chosen if:
19481 - @a ValueType is not @ref basic_json,
19482 - @ref json_serializer<ValueType> has a `from_json()` method of the form
19483 `void from_json(const basic_json&, ValueType&)`, and
19484
19485 @tparam ValueType the input parameter type.
19486
19487 @return the input parameter, allowing chaining calls.
19488
19489 @throw what @ref json_serializer<ValueType> `from_json()` method throws
19490
19491 @liveexample{The example below shows several conversions from JSON values
19492 to other types. There a few things to note: (1) Floating-point numbers can
19493 be converted to integers\, (2) A JSON array can be converted to a standard
19494 `std::vector<short>`\, (3) A JSON object can be converted to C++
19495 associative containers such as `std::unordered_map<std::string\,
19496 json>`.,get_to}
19497
19498 @since version 3.3.0
19499 */
19500 template < typename ValueType,
19501 detail::enable_if_t <
19502 !detail::is_basic_json<ValueType>::value&&
19503 detail::has_from_json<basic_json_t, ValueType>::value,
19504 int > = 0 >
19505 ValueType & get_to(ValueType& v) const noexcept(noexcept(
19506 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
19507 {
19508 JSONSerializer<ValueType>::from_json(*this, v);
19509 return v;
19510 }
19511
19512 // specialization to allow to call get_to with a basic_json value
19513 // see https://github.com/nlohmann/json/issues/2175
19514 template<typename ValueType,
19515 detail::enable_if_t <
19516 detail::is_basic_json<ValueType>::value,
19517 int> = 0>
19518 ValueType & get_to(ValueType& v) const
19519 {
19520 v = *this;
19521 return v;
19522 }
19523
1200919524 template <
12010 typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
12011 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and detail::has_non_default_from_json<basic_json_t, ValueType>::value, int> = 0>
12012 ValueType get() const noexcept(noexcept(JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
12013 {
12014 static_assert(not std::is_reference<ValueTypeCV>::value, "get() cannot be used with reference types, you might want to use get_ref()");
12015 return JSONSerializer<ValueTypeCV>::from_json(*this);
19525 typename T, std::size_t N,
19526 typename Array = T (&)[N],
19527 detail::enable_if_t <
19528 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
19529 Array get_to(T (&v)[N]) const
19530 noexcept(noexcept(JSONSerializer<Array>::from_json(
19531 std::declval<const basic_json_t&>(), v)))
19532 {
19533 JSONSerializer<Array>::from_json(*this, v);
19534 return v;
19535 }
19536
19537
19538 /*!
19539 @brief get a pointer value (implicit)
19540
19541 Implicit pointer access to the internally stored JSON value. No copies are
19542 made.
19543
19544 @warning Writing data to the pointee of the result yields an undefined
19545 state.
19546
19547 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
19548 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
19549 @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
19550 assertion.
19551
19552 @return pointer to the internally stored JSON value if the requested
19553 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
19554
19555 @complexity Constant.
19556
19557 @liveexample{The example below shows how pointers to internal values of a
19558 JSON value can be requested. Note that no type conversions are made and a
19559 `nullptr` is returned if the value and the requested pointer type does not
19560 match.,get_ptr}
19561
19562 @since version 1.0.0
19563 */
19564 template<typename PointerType, typename std::enable_if<
19565 std::is_pointer<PointerType>::value, int>::type = 0>
19566 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19567 {
19568 // delegate the call to get_impl_ptr<>()
19569 return get_impl_ptr(static_cast<PointerType>(nullptr));
19570 }
19571
19572 /*!
19573 @brief get a pointer value (implicit)
19574 @copydoc get_ptr()
19575 */
19576 template < typename PointerType, typename std::enable_if <
19577 std::is_pointer<PointerType>::value&&
19578 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
19579 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19580 {
19581 // delegate the call to get_impl_ptr<>() const
19582 return get_impl_ptr(static_cast<PointerType>(nullptr));
1201619583 }
1201719584
1201819585 /*!
1204219609
1204319610 @since version 1.0.0
1204419611 */
12045 template <typename PointerType, typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
12046 PointerType get() noexcept
19612 template<typename PointerType, typename std::enable_if<
19613 std::is_pointer<PointerType>::value, int>::type = 0>
19614 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
1204719615 {
1204819616 // delegate the call to get_ptr
1204919617 return get_ptr<PointerType>();
1205319621 @brief get a pointer value (explicit)
1205419622 @copydoc get()
1205519623 */
12056 template <typename PointerType, typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
12057 constexpr const PointerType get() const noexcept
19624 template<typename PointerType, typename std::enable_if<
19625 std::is_pointer<PointerType>::value, int>::type = 0>
19626 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
1205819627 {
1205919628 // delegate the call to get_ptr
1206019629 return get_ptr<PointerType>();
12061 }
12062
12063 /*!
12064 @brief get a pointer value (implicit)
12065
12066 Implicit pointer access to the internally stored JSON value. No copies are
12067 made.
12068
12069 @warning Writing data to the pointee of the result yields an undefined
12070 state.
12071
12072 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
12073 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
12074 @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
12075 assertion.
12076
12077 @return pointer to the internally stored JSON value if the requested
12078 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
12079
12080 @complexity Constant.
12081
12082 @liveexample{The example below shows how pointers to internal values of a
12083 JSON value can be requested. Note that no type conversions are made and a
12084 `nullptr` is returned if the value and the requested pointer type does not
12085 match.,get_ptr}
12086
12087 @since version 1.0.0
12088 */
12089 template <typename PointerType, typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
12090 PointerType get_ptr() noexcept
12091 {
12092 // get the type of the PointerType (remove pointer and const)
12093 using pointee_t = typename std::remove_const<typename std::remove_pointer<typename std::remove_const<PointerType>::type>::type>::type;
12094 // make sure the type matches the allowed types
12095 static_assert(std::is_same<object_t, pointee_t>::value or std::is_same<array_t, pointee_t>::value or std::is_same<string_t, pointee_t>::value or
12096 std::is_same<boolean_t, pointee_t>::value or std::is_same<number_integer_t, pointee_t>::value or
12097 std::is_same<number_unsigned_t, pointee_t>::value or std::is_same<number_float_t, pointee_t>::value,
12098 "incompatible pointer type");
12099
12100 // delegate the call to get_impl_ptr<>()
12101 return get_impl_ptr(static_cast<PointerType>(nullptr));
12102 }
12103
12104 /*!
12105 @brief get a pointer value (implicit)
12106 @copydoc get_ptr()
12107 */
12108 template <
12109 typename PointerType,
12110 typename std::enable_if<std::is_pointer<PointerType>::value and std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
12111 constexpr const PointerType get_ptr() const noexcept
12112 {
12113 // get the type of the PointerType (remove pointer and const)
12114 using pointee_t = typename std::remove_const<typename std::remove_pointer<typename std::remove_const<PointerType>::type>::type>::type;
12115 // make sure the type matches the allowed types
12116 static_assert(std::is_same<object_t, pointee_t>::value or std::is_same<array_t, pointee_t>::value or std::is_same<string_t, pointee_t>::value or
12117 std::is_same<boolean_t, pointee_t>::value or std::is_same<number_integer_t, pointee_t>::value or
12118 std::is_same<number_unsigned_t, pointee_t>::value or std::is_same<number_float_t, pointee_t>::value,
12119 "incompatible pointer type");
12120
12121 // delegate the call to get_impl_ptr<>() const
12122 return get_impl_ptr(static_cast<PointerType>(nullptr));
1212319630 }
1212419631
1212519632 /*!
1214819655
1214919656 @since version 1.1.0
1215019657 */
12151 template <typename ReferenceType, typename std::enable_if<std::is_reference<ReferenceType>::value, int>::type = 0>
19658 template<typename ReferenceType, typename std::enable_if<
19659 std::is_reference<ReferenceType>::value, int>::type = 0>
1215219660 ReferenceType get_ref()
1215319661 {
1215419662 // delegate call to get_ref_impl
1215919667 @brief get a reference value (implicit)
1216019668 @copydoc get_ref()
1216119669 */
12162 template <typename ReferenceType,
12163 typename std::enable_if<std::is_reference<ReferenceType>::value and std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
12164 int>::type = 0>
19670 template < typename ReferenceType, typename std::enable_if <
19671 std::is_reference<ReferenceType>::value&&
19672 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
1216519673 ReferenceType get_ref() const
1216619674 {
1216719675 // delegate call to get_ref_impl
1219719705
1219819706 @since version 1.0.0
1219919707 */
12200 template <typename ValueType,
12201 typename std::enable_if<not std::is_pointer<ValueType>::value and not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
12202 not std::is_same<ValueType, typename string_t::value_type>::value and not detail::is_basic_json<ValueType>::value
12203 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
12204 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
12205 #endif
12206 #if defined(JSON_HAS_CPP_17)
12207 and not std::is_same<ValueType, typename std::string_view>::value
12208 #endif
12209 ,
12210 int>::type = 0>
12211 operator ValueType() const
19708 template < typename ValueType, typename std::enable_if <
19709 !std::is_pointer<ValueType>::value&&
19710 !std::is_same<ValueType, detail::json_ref<basic_json>>::value&&
19711 !std::is_same<ValueType, typename string_t::value_type>::value&&
19712 !detail::is_basic_json<ValueType>::value
19713 && !std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
19714 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19715 && !std::is_same<ValueType, typename std::string_view>::value
19716 #endif
19717 && detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
19718 , int >::type = 0 >
19719 JSON_EXPLICIT operator ValueType() const
1221219720 {
1221319721 // delegate the call to get<>() const
1221419722 return get<ValueType>();
19723 }
19724
19725 /*!
19726 @return reference to the binary value
19727
19728 @throw type_error.302 if the value is not binary
19729
19730 @sa @ref is_binary() to check if the value is binary
19731
19732 @since version 3.8.0
19733 */
19734 binary_t& get_binary()
19735 {
19736 if (!is_binary())
19737 {
19738 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19739 }
19740
19741 return *get_ptr<binary_t*>();
19742 }
19743
19744 /// @copydoc get_binary()
19745 const binary_t& get_binary() const
19746 {
19747 if (!is_binary())
19748 {
19749 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19750 }
19751
19752 return *get_ptr<const binary_t*>();
1221519753 }
1221619754
1221719755 /// @}
1225419792 reference at(size_type idx)
1225519793 {
1225619794 // at only works for arrays
12257 if (JSON_LIKELY(is_array()))
19795 if (JSON_HEDLEY_LIKELY(is_array()))
1225819796 {
1225919797 JSON_TRY
1226019798 {
1226119799 return m_value.array->at(idx);
1226219800 }
12263 JSON_CATCH(std::out_of_range&)
19801 JSON_CATCH (std::out_of_range&)
1226419802 {
1226519803 // create better exception explanation
12266 JSON_THROW(out_of_range::create(401, "array index " + cpt::to_string(idx) + " is out of range"));
19804 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
1226719805 }
1226819806 }
1226919807 else
1230119839 const_reference at(size_type idx) const
1230219840 {
1230319841 // at only works for arrays
12304 if (JSON_LIKELY(is_array()))
19842 if (JSON_HEDLEY_LIKELY(is_array()))
1230519843 {
1230619844 JSON_TRY
1230719845 {
1230819846 return m_value.array->at(idx);
1230919847 }
12310 JSON_CATCH(std::out_of_range&)
19848 JSON_CATCH (std::out_of_range&)
1231119849 {
1231219850 // create better exception explanation
12313 JSON_THROW(out_of_range::create(401, "array index " + cpt::to_string(idx) + " is out of range"));
19851 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
1231419852 }
1231519853 }
1231619854 else
1235219890 reference at(const typename object_t::key_type& key)
1235319891 {
1235419892 // at only works for objects
12355 if (JSON_LIKELY(is_object()))
19893 if (JSON_HEDLEY_LIKELY(is_object()))
1235619894 {
1235719895 JSON_TRY
1235819896 {
1235919897 return m_value.object->at(key);
1236019898 }
12361 JSON_CATCH(std::out_of_range&)
19899 JSON_CATCH (std::out_of_range&)
1236219900 {
1236319901 // create better exception explanation
1236419902 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
1240319941 const_reference at(const typename object_t::key_type& key) const
1240419942 {
1240519943 // at only works for objects
12406 if (JSON_LIKELY(is_object()))
19944 if (JSON_HEDLEY_LIKELY(is_object()))
1240719945 {
1240819946 JSON_TRY
1240919947 {
1241019948 return m_value.object->at(key);
1241119949 }
12412 JSON_CATCH(std::out_of_range&)
19950 JSON_CATCH (std::out_of_range&)
1241319951 {
1241419952 // create better exception explanation
1241519953 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
1245719995 }
1245819996
1245919997 // operator[] only works for arrays
12460 if (JSON_LIKELY(is_array()))
19998 if (JSON_HEDLEY_LIKELY(is_array()))
1246119999 {
1246220000 // fill up array with null values if given idx is outside range
1246320001 if (idx >= m_value.array->size())
1246420002 {
12465 m_value.array->insert(m_value.array->end(), idx - m_value.array->size() + 1, basic_json());
20003 m_value.array->insert(m_value.array->end(),
20004 idx - m_value.array->size() + 1,
20005 basic_json());
1246620006 }
1246720007
1246820008 return m_value.array->operator[](idx);
1246920009 }
1247020010
12471 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20011 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
1247220012 }
1247320013
1247420014 /*!
1249320033 const_reference operator[](size_type idx) const
1249420034 {
1249520035 // const operator[] only works for arrays
12496 if (JSON_LIKELY(is_array()))
20036 if (JSON_HEDLEY_LIKELY(is_array()))
1249720037 {
1249820038 return m_value.array->operator[](idx);
1249920039 }
1250020040
12501 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20041 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
1250220042 }
1250320043
1250420044 /*!
1253920079 }
1254020080
1254120081 // operator[] only works for objects
12542 if (JSON_LIKELY(is_object()))
20082 if (JSON_HEDLEY_LIKELY(is_object()))
1254320083 {
1254420084 return m_value.object->operator[](key);
1254520085 }
1254620086
12547 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20087 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
1254820088 }
1254920089
1255020090 /*!
1258020120 const_reference operator[](const typename object_t::key_type& key) const
1258120121 {
1258220122 // const operator[] only works for objects
12583 if (JSON_LIKELY(is_object()))
12584 {
12585 assert(m_value.object->find(key) != m_value.object->end());
20123 if (JSON_HEDLEY_LIKELY(is_object()))
20124 {
20125 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
1258620126 return m_value.object->find(key)->second;
1258720127 }
1258820128
12589 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20129 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
1259020130 }
1259120131
1259220132 /*!
1261620156
1261720157 @since version 1.1.0
1261820158 */
12619 template <typename T>
20159 template<typename T>
20160 JSON_HEDLEY_NON_NULL(2)
1262020161 reference operator[](T* key)
1262120162 {
1262220163 // implicitly convert null to object
1262820169 }
1262920170
1263020171 // at only works for objects
12631 if (JSON_LIKELY(is_object()))
20172 if (JSON_HEDLEY_LIKELY(is_object()))
1263220173 {
1263320174 return m_value.object->operator[](key);
1263420175 }
1263520176
12636 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20177 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
1263720178 }
1263820179
1263920180 /*!
1266620207
1266720208 @since version 1.1.0
1266820209 */
12669 template <typename T>
20210 template<typename T>
20211 JSON_HEDLEY_NON_NULL(2)
1267020212 const_reference operator[](T* key) const
1267120213 {
1267220214 // at only works for objects
12673 if (JSON_LIKELY(is_object()))
12674 {
12675 assert(m_value.object->find(key) != m_value.object->end());
20215 if (JSON_HEDLEY_LIKELY(is_object()))
20216 {
20217 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
1267620218 return m_value.object->find(key)->second;
1267720219 }
1267820220
12679 JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
20221 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
1268020222 }
1268120223
1268220224 /*!
1271220254 @return copy of the element at key @a key or @a default_value if @a key
1271320255 is not found
1271420256
20257 @throw type_error.302 if @a default_value does not match the type of the
20258 value at @a key
1271520259 @throw type_error.306 if the JSON value is not an object; in that case,
1271620260 using `value()` with a key makes no sense.
1271720261
1272720271
1272820272 @since version 1.0.0
1272920273 */
12730 template <class ValueType, typename std::enable_if<std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
20274 // using std::is_convertible in a std::enable_if will fail when using explicit conversions
20275 template < class ValueType, typename std::enable_if <
20276 detail::is_getable<basic_json_t, ValueType>::value
20277 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
1273120278 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
1273220279 {
1273320280 // at only works for objects
12734 if (JSON_LIKELY(is_object()))
20281 if (JSON_HEDLEY_LIKELY(is_object()))
1273520282 {
1273620283 // if key is found, return value and given default value otherwise
1273720284 const auto it = find(key);
1273820285 if (it != end())
1273920286 {
12740 return *it;
20287 return it->template get<ValueType>();
1274120288 }
1274220289
1274320290 return default_value;
1274820295
1274920296 /*!
1275020297 @brief overload for a default value of type const char*
12751 @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const
20298 @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
1275220299 */
1275320300 string_t value(const typename object_t::key_type& key, const char* default_value) const
1275420301 {
1278420331 @return copy of the element at key @a key or @a default_value if @a key
1278520332 is not found
1278620333
12787 @throw type_error.306 if the JSON value is not an objec; in that case,
20334 @throw type_error.302 if @a default_value does not match the type of the
20335 value at @a ptr
20336 @throw type_error.306 if the JSON value is not an object; in that case,
1278820337 using `value()` with a key makes no sense.
1278920338
1279020339 @complexity Logarithmic in the size of the container.
1279620345
1279720346 @since version 2.0.2
1279820347 */
12799 template <class ValueType, typename std::enable_if<std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
20348 template<class ValueType, typename std::enable_if<
20349 detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
1280020350 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
1280120351 {
1280220352 // at only works for objects
12803 if (JSON_LIKELY(is_object()))
20353 if (JSON_HEDLEY_LIKELY(is_object()))
1280420354 {
1280520355 // if pointer resolves a value, return it or use default value
1280620356 JSON_TRY
1280720357 {
12808 return ptr.get_checked(this);
12809 }
12810 JSON_CATCH(out_of_range&)
20358 return ptr.get_checked(this).template get<ValueType>();
20359 }
20360 JSON_INTERNAL_CATCH (out_of_range&)
1281120361 {
1281220362 return default_value;
1281320363 }
1282020370 @brief overload for a default value of type const char*
1282120371 @copydoc basic_json::value(const json_pointer&, ValueType) const
1282220372 */
20373 JSON_HEDLEY_NON_NULL(3)
1282320374 string_t value(const json_pointer& ptr, const char* default_value) const
1282420375 {
1282520376 return value(ptr, string_t(default_value));
1283220383 container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
1283320384
1283420385 @return In case of a structured type (array or object), a reference to the
12835 first element is returned. In case of number, string, or boolean values, a
12836 reference to the value is returned.
20386 first element is returned. In case of number, string, boolean, or binary
20387 values, a reference to the value is returned.
1283720388
1283820389 @complexity Constant.
1283920390
1287520426 @endcode
1287620427
1287720428 @return In case of a structured type (array or object), a reference to the
12878 last element is returned. In case of number, string, or boolean values, a
12879 reference to the value is returned.
20429 last element is returned. In case of number, string, boolean, or binary
20430 values, a reference to the value is returned.
1288020431
1288120432 @complexity Constant.
1288220433
1294220493 @complexity The complexity depends on the type:
1294320494 - objects: amortized constant
1294420495 - arrays: linear in distance between @a pos and the end of the container
12945 - strings: linear in the length of the string
20496 - strings and binary: linear in the length of the member
1294620497 - other types: constant
1294720498
1294820499 @liveexample{The example shows the result of `erase()` for different JSON
1295720508
1295820509 @since version 1.0.0
1295920510 */
12960 template <class IteratorType, typename std::enable_if<std::is_same<IteratorType, typename basic_json_t::iterator>::value or
12961 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
12962 int>::type = 0>
20511 template < class IteratorType, typename std::enable_if <
20512 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20513 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20514 = 0 >
1296320515 IteratorType erase(IteratorType pos)
1296420516 {
1296520517 // make sure iterator fits the current value
12966 if (JSON_UNLIKELY(this != pos.m_object))
20518 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
1296720519 {
1296820520 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
1296920521 }
1297720529 case value_t::number_integer:
1297820530 case value_t::number_unsigned:
1297920531 case value_t::string:
12980 {
12981 if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
20532 case value_t::binary:
20533 {
20534 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
1298220535 {
1298320536 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
1298420537 }
1299020543 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
1299120544 m_value.string = nullptr;
1299220545 }
20546 else if (is_binary())
20547 {
20548 AllocatorType<binary_t> alloc;
20549 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20550 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20551 m_value.binary = nullptr;
20552 }
1299320553
1299420554 m_type = value_t::null;
1299520555 assert_invariant();
1304720607 - objects: `log(size()) + std::distance(first, last)`
1304820608 - arrays: linear in the distance between @a first and @a last, plus linear
1304920609 in the distance between @a last and end of the container
13050 - strings: linear in the length of the string
20610 - strings and binary: linear in the length of the member
1305120611 - other types: constant
1305220612
1305320613 @liveexample{The example shows the result of `erase()` for different JSON
1306120621
1306220622 @since version 1.0.0
1306320623 */
13064 template <class IteratorType, typename std::enable_if<std::is_same<IteratorType, typename basic_json_t::iterator>::value or
13065 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
13066 int>::type = 0>
20624 template < class IteratorType, typename std::enable_if <
20625 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20626 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20627 = 0 >
1306720628 IteratorType erase(IteratorType first, IteratorType last)
1306820629 {
1306920630 // make sure iterator fits the current value
13070 if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
20631 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
1307120632 {
1307220633 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
1307320634 }
1308120642 case value_t::number_integer:
1308220643 case value_t::number_unsigned:
1308320644 case value_t::string:
13084 {
13085 if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()))
20645 case value_t::binary:
20646 {
20647 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
20648 || !last.m_it.primitive_iterator.is_end()))
1308620649 {
1308720650 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
1308820651 }
1309420657 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
1309520658 m_value.string = nullptr;
1309620659 }
20660 else if (is_binary())
20661 {
20662 AllocatorType<binary_t> alloc;
20663 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20664 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20665 m_value.binary = nullptr;
20666 }
1309720667
1309820668 m_type = value_t::null;
1309920669 assert_invariant();
1310220672
1310320673 case value_t::object:
1310420674 {
13105 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator);
20675 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
20676 last.m_it.object_iterator);
1310620677 break;
1310720678 }
1310820679
1310920680 case value_t::array:
1311020681 {
13111 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator);
20682 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
20683 last.m_it.array_iterator);
1311220684 break;
1311320685 }
1311420686
1315120723 size_type erase(const typename object_t::key_type& key)
1315220724 {
1315320725 // this erase only works for objects
13154 if (JSON_LIKELY(is_object()))
20726 if (JSON_HEDLEY_LIKELY(is_object()))
1315520727 {
1315620728 return m_value.object->erase(key);
1315720729 }
1318620758 void erase(const size_type idx)
1318720759 {
1318820760 // this erase only works for arrays
13189 if (JSON_LIKELY(is_array()))
13190 {
13191 if (JSON_UNLIKELY(idx >= size()))
13192 {
13193 JSON_THROW(out_of_range::create(401, "array index " + cpt::to_string(idx) + " is out of range"));
20761 if (JSON_HEDLEY_LIKELY(is_array()))
20762 {
20763 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
20764 {
20765 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
1319420766 }
1319520767
1319620768 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
1323120803
1323220804 @liveexample{The example shows how `find()` is used.,find__key_type}
1323320805
20806 @sa @ref contains(KeyT&&) const -- checks whether a key exists
20807
1323420808 @since version 1.0.0
1323520809 */
13236 template <typename KeyT>
20810 template<typename KeyT>
1323720811 iterator find(KeyT&& key)
1323820812 {
1323920813 auto result = end();
1325020824 @brief find an element in a JSON object
1325120825 @copydoc find(KeyT&&)
1325220826 */
13253 template <typename KeyT>
20827 template<typename KeyT>
1325420828 const_iterator find(KeyT&& key) const
1325520829 {
1325620830 auto result = cend();
1328420858
1328520859 @since version 1.0.0
1328620860 */
13287 template <typename KeyT>
20861 template<typename KeyT>
1328820862 size_type count(KeyT&& key) const
1328920863 {
1329020864 // return 0 for all nonobject types
1329120865 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
20866 }
20867
20868 /*!
20869 @brief check the existence of an element in a JSON object
20870
20871 Check whether an element exists in a JSON object with key equivalent to
20872 @a key. If the element is not found or the JSON value is not an object,
20873 false is returned.
20874
20875 @note This method always returns false when executed on a JSON type
20876 that is not an object.
20877
20878 @param[in] key key value to check its existence.
20879
20880 @return true if an element with specified @a key exists. If no such
20881 element with such key is found or the JSON value is not an object,
20882 false is returned.
20883
20884 @complexity Logarithmic in the size of the JSON object.
20885
20886 @liveexample{The following code shows an example for `contains()`.,contains}
20887
20888 @sa @ref find(KeyT&&) -- returns an iterator to an object element
20889 @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
20890
20891 @since version 3.6.0
20892 */
20893 template < typename KeyT, typename std::enable_if <
20894 !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
20895 bool contains(KeyT && key) const
20896 {
20897 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
20898 }
20899
20900 /*!
20901 @brief check the existence of an element in a JSON object given a JSON pointer
20902
20903 Check whether the given JSON pointer @a ptr can be resolved in the current
20904 JSON value.
20905
20906 @note This method can be executed on any JSON value type.
20907
20908 @param[in] ptr JSON pointer to check its existence.
20909
20910 @return true if the JSON pointer can be resolved to a stored value, false
20911 otherwise.
20912
20913 @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
20914
20915 @throw parse_error.106 if an array index begins with '0'
20916 @throw parse_error.109 if an array index was not a number
20917
20918 @complexity Logarithmic in the size of the JSON object.
20919
20920 @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
20921
20922 @sa @ref contains(KeyT &&) const -- checks the existence of a key
20923
20924 @since version 3.7.0
20925 */
20926 bool contains(const json_pointer& ptr) const
20927 {
20928 return ptr.contains(this);
1329220929 }
1329320930
1329420931 /// @}
1331320950 @complexity Constant.
1331420951
1331520952 @requirement This function helps `basic_json` satisfying the
13316 [Container](http://en.cppreference.com/w/cpp/concept/Container)
20953 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1331720954 requirements:
1331820955 - The complexity is constant.
1331920956
1335220989 @complexity Constant.
1335320990
1335420991 @requirement This function helps `basic_json` satisfying the
13355 [Container](http://en.cppreference.com/w/cpp/concept/Container)
20992 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1335620993 requirements:
1335720994 - The complexity is constant.
1335820995 - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
1338421021 @complexity Constant.
1338521022
1338621023 @requirement This function helps `basic_json` satisfying the
13387 [Container](http://en.cppreference.com/w/cpp/concept/Container)
21024 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1338821025 requirements:
1338921026 - The complexity is constant.
1339021027
1342321060 @complexity Constant.
1342421061
1342521062 @requirement This function helps `basic_json` satisfying the
13426 [Container](http://en.cppreference.com/w/cpp/concept/Container)
21063 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1342721064 requirements:
1342821065 - The complexity is constant.
1342921066 - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
1345321090 @complexity Constant.
1345421091
1345521092 @requirement This function helps `basic_json` satisfying the
13456 [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
21093 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
1345721094 requirements:
1345821095 - The complexity is constant.
1345921096 - Has the semantics of `reverse_iterator(end())`.
1349021127 @complexity Constant.
1349121128
1349221129 @requirement This function helps `basic_json` satisfying the
13493 [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
21130 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
1349421131 requirements:
1349521132 - The complexity is constant.
1349621133 - Has the semantics of `reverse_iterator(begin())`.
1352721164 @complexity Constant.
1352821165
1352921166 @requirement This function helps `basic_json` satisfying the
13530 [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
21167 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
1353121168 requirements:
1353221169 - The complexity is constant.
1353321170 - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
1355621193 @complexity Constant.
1355721194
1355821195 @requirement This function helps `basic_json` satisfying the
13559 [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
21196 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
1356021197 requirements:
1356121198 - The complexity is constant.
1356221199 - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
1357421211 return const_reverse_iterator(cbegin());
1357521212 }
1357621213
13577 public:
21214 public:
1357821215 /*!
1357921216 @brief wrapper to access iterator member functions in range-based for
1358021217
1363221269 future 4.0.0 of the library. Please use @ref items() instead;
1363321270 that is, replace `json::iterator_wrapper(j)` with `j.items()`.
1363421271 */
13635 JSON_DEPRECATED
21272 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
1363621273 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
1363721274 {
1363821275 return ref.items();
1364121278 /*!
1364221279 @copydoc iterator_wrapper(reference)
1364321280 */
13644 JSON_DEPRECATED
21281 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
1364521282 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
1364621283 {
1364721284 return ref.items();
1367721314 Range-based for loop with `items()` function:
1367821315
1367921316 @code{cpp}
13680 for (auto it : j_object.items())
13681 {
13682 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21317 for (auto& el : j_object.items())
21318 {
21319 std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
21320 }
21321 @endcode
21322
21323 The `items()` function also allows to use
21324 [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
21325 (C++17):
21326
21327 @code{cpp}
21328 for (auto& [key, val] : j_object.items())
21329 {
21330 std::cout << "key: " << key << ", value:" << val << '\n';
1368321331 }
1368421332 @endcode
1368521333
1368721335 element as string (see example). For primitive types (e.g., numbers),
1368821336 `key()` returns an empty string.
1368921337
21338 @warning Using `items()` on temporary objects is dangerous. Make sure the
21339 object's lifetime exeeds the iteration. See
21340 <https://github.com/nlohmann/json/issues/2040> for more
21341 information.
21342
1369021343 @return iteration proxy object wrapping @a ref with an interface to use in
1369121344 range-based for loops
1369221345
1369721350
1369821351 @complexity Constant.
1369921352
13700 @since version 3.x.x.
21353 @since version 3.1.0, structured bindings support since 3.5.0.
1370121354 */
1370221355 iteration_proxy<iterator> items() noexcept
1370321356 {
1373521388 boolean | `false`
1373621389 string | `false`
1373721390 number | `false`
21391 binary | `false`
1373821392 object | result of function `object_t::empty()`
1373921393 array | result of function `array_t::empty()`
1374021394
1375421408 false in the case of a string.
1375521409
1375621410 @requirement This function helps `basic_json` satisfying the
13757 [Container](http://en.cppreference.com/w/cpp/concept/Container)
21411 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1375821412 requirements:
1375921413 - The complexity is constant.
1376021414 - Has the semantics of `begin() == end()`.
1380621460 boolean | `1`
1380721461 string | `1`
1380821462 number | `1`
21463 binary | `1`
1380921464 object | result of function object_t::size()
1381021465 array | result of function array_t::size()
1381121466
1382521480 the case of a string.
1382621481
1382721482 @requirement This function helps `basic_json` satisfying the
13828 [Container](http://en.cppreference.com/w/cpp/concept/Container)
21483 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1382921484 requirements:
1383021485 - The complexity is constant.
1383121486 - Has the semantics of `std::distance(begin(), end())`.
1388021535 boolean | `1` (same as `size()`)
1388121536 string | `1` (same as `size()`)
1388221537 number | `1` (same as `size()`)
21538 binary | `1` (same as `size()`)
1388321539 object | result of function `object_t::max_size()`
1388421540 array | result of function `array_t::max_size()`
1388521541
1389521551 @exceptionsafety No-throw guarantee: this function never throws exceptions.
1389621552
1389721553 @requirement This function helps `basic_json` satisfying the
13898 [Container](http://en.cppreference.com/w/cpp/concept/Container)
21554 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
1389921555 requirements:
1390021556 - The complexity is constant.
1390121557 - Has the semantics of returning `b.size()` where `b` is the largest
1395221608 boolean | `false`
1395321609 string | `""`
1395421610 number | `0`
21611 binary | An empty byte vector
1395521612 object | `{}`
1395621613 array | `[]`
1395721614
1400921666 break;
1401021667 }
1401121668
21669 case value_t::binary:
21670 {
21671 m_value.binary->clear();
21672 break;
21673 }
21674
1401221675 case value_t::array:
1401321676 {
1401421677 m_value.array->clear();
1404921712 void push_back(basic_json&& val)
1405021713 {
1405121714 // push_back only works for null objects or arrays
14052 if (JSON_UNLIKELY(not(is_null() or is_array())))
21715 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
1405321716 {
1405421717 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
1405521718 }
1406421727
1406521728 // add element to array (move semantics)
1406621729 m_value.array->push_back(std::move(val));
14067 // invalidate object
14068 val.m_type = value_t::null;
21730 // if val is moved from, basic_json move constructor marks it null so we do not call the destructor
1406921731 }
1407021732
1407121733 /*!
1408521747 void push_back(const basic_json& val)
1408621748 {
1408721749 // push_back only works for null objects or arrays
14088 if (JSON_UNLIKELY(not(is_null() or is_array())))
21750 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
1408921751 {
1409021752 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
1409121753 }
1413521797 void push_back(const typename object_t::value_type& val)
1413621798 {
1413721799 // push_back only works for null objects or objects
14138 if (JSON_UNLIKELY(not(is_null() or is_object())))
21800 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
1413921801 {
1414021802 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
1414121803 }
1418921851 */
1419021852 void push_back(initializer_list_t init)
1419121853 {
14192 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
21854 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
1419321855 {
1419421856 basic_json&& key = init.begin()->moved_or_copied();
14195 push_back(typename object_t::value_type(std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21857 push_back(typename object_t::value_type(
21858 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
1419621859 }
1419721860 else
1419821861 {
1422021883 @param[in] args arguments to forward to a constructor of @ref basic_json
1422121884 @tparam Args compatible types to create a @ref basic_json object
1422221885
21886 @return reference to the inserted element
21887
1422321888 @throw type_error.311 when called on a type other than JSON array or
1422421889 null; example: `"cannot use emplace_back() with number"`
1422521890
1422921894 elements to a JSON array. Note how the `null` value was silently converted
1423021895 to a JSON array.,emplace_back}
1423121896
14232 @since version 2.0.8
14233 */
14234 template <class... Args>
14235 void emplace_back(Args&&... args)
21897 @since version 2.0.8, returns reference since 3.7.0
21898 */
21899 template<class... Args>
21900 reference emplace_back(Args&& ... args)
1423621901 {
1423721902 // emplace_back only works for null objects or arrays
14238 if (JSON_UNLIKELY(not(is_null() or is_array())))
21903 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
1423921904 {
1424021905 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
1424121906 }
1424921914 }
1425021915
1425121916 // add element to array (perfect forwarding)
21917 #ifdef JSON_HAS_CPP_17
21918 return m_value.array->emplace_back(std::forward<Args>(args)...);
21919 #else
1425221920 m_value.array->emplace_back(std::forward<Args>(args)...);
21921 return m_value.array->back();
21922 #endif
1425321923 }
1425421924
1425521925 /*!
1427921949
1428021950 @since version 2.0.8
1428121951 */
14282 template <class... Args>
14283 std::pair<iterator, bool> emplace(Args&&... args)
21952 template<class... Args>
21953 std::pair<iterator, bool> emplace(Args&& ... args)
1428421954 {
1428521955 // emplace only works for null objects or arrays
14286 if (JSON_UNLIKELY(not(is_null() or is_object())))
21956 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
1428721957 {
1428821958 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
1428921959 }
1430621976 return {it, res.second};
1430721977 }
1430821978
21979 /// Helper for insertion of an iterator
21980 /// @note: This uses std::distance to support GCC 4.8,
21981 /// see https://github.com/nlohmann/json/pull/1257
21982 template<typename... Args>
21983 iterator insert_iterator(const_iterator pos, Args&& ... args)
21984 {
21985 iterator result(this);
21986 JSON_ASSERT(m_value.array != nullptr);
21987
21988 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
21989 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21990 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
21991
21992 // This could have been written as:
21993 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
21994 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
21995
21996 return result;
21997 }
21998
1430921999 /*!
1431022000 @brief inserts element
1431122001
1433122021 iterator insert(const_iterator pos, const basic_json& val)
1433222022 {
1433322023 // insert only works for arrays
14334 if (JSON_LIKELY(is_array()))
22024 if (JSON_HEDLEY_LIKELY(is_array()))
1433522025 {
1433622026 // check if iterator pos fits to this JSON value
14337 if (JSON_UNLIKELY(pos.m_object != this))
22027 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
1433822028 {
1433922029 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
1434022030 }
1434122031
1434222032 // insert to array and return iterator
14343 iterator result(this);
14344 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
14345 return result;
22033 return insert_iterator(pos, val);
1434622034 }
1434722035
1434822036 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
1438422072 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
1438522073 {
1438622074 // insert only works for arrays
14387 if (JSON_LIKELY(is_array()))
22075 if (JSON_HEDLEY_LIKELY(is_array()))
1438822076 {
1438922077 // check if iterator pos fits to this JSON value
14390 if (JSON_UNLIKELY(pos.m_object != this))
22078 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
1439122079 {
1439222080 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
1439322081 }
1439422082
1439522083 // insert to array and return iterator
14396 iterator result(this);
14397 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
14398 return result;
22084 return insert_iterator(pos, cnt, val);
1439922085 }
1440022086
1440122087 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
1443422120 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
1443522121 {
1443622122 // insert only works for arrays
14437 if (JSON_UNLIKELY(not is_array()))
22123 if (JSON_HEDLEY_UNLIKELY(!is_array()))
1443822124 {
1443922125 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
1444022126 }
1444122127
1444222128 // check if iterator pos fits to this JSON value
14443 if (JSON_UNLIKELY(pos.m_object != this))
22129 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
1444422130 {
1444522131 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
1444622132 }
1444722133
1444822134 // check if range iterators belong to the same JSON object
14449 if (JSON_UNLIKELY(first.m_object != last.m_object))
22135 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1445022136 {
1445122137 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
1445222138 }
1445322139
14454 if (JSON_UNLIKELY(first.m_object == this))
22140 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
1445522141 {
1445622142 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
1445722143 }
1445822144
1445922145 // insert to array and return iterator
14460 iterator result(this);
14461 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, first.m_it.array_iterator, last.m_it.array_iterator);
14462 return result;
22146 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
1446322147 }
1446422148
1446522149 /*!
1448922173 iterator insert(const_iterator pos, initializer_list_t ilist)
1449022174 {
1449122175 // insert only works for arrays
14492 if (JSON_UNLIKELY(not is_array()))
22176 if (JSON_HEDLEY_UNLIKELY(!is_array()))
1449322177 {
1449422178 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
1449522179 }
1449622180
1449722181 // check if iterator pos fits to this JSON value
14498 if (JSON_UNLIKELY(pos.m_object != this))
22182 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
1449922183 {
1450022184 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
1450122185 }
1450222186
1450322187 // insert to array and return iterator
14504 iterator result(this);
14505 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
14506 return result;
22188 return insert_iterator(pos, ilist.begin(), ilist.end());
1450722189 }
1450822190
1450922191 /*!
1453222214 void insert(const_iterator first, const_iterator last)
1453322215 {
1453422216 // insert only works for objects
14535 if (JSON_UNLIKELY(not is_object()))
22217 if (JSON_HEDLEY_UNLIKELY(!is_object()))
1453622218 {
1453722219 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
1453822220 }
1453922221
1454022222 // check if range iterators belong to the same JSON object
14541 if (JSON_UNLIKELY(first.m_object != last.m_object))
22223 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1454222224 {
1454322225 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
1454422226 }
1454522227
1454622228 // passed iterators must belong to objects
14547 if (JSON_UNLIKELY(not first.m_object->is_object()))
22229 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
1454822230 {
1454922231 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
1455022232 }
1458122263 assert_invariant();
1458222264 }
1458322265
14584 if (JSON_UNLIKELY(not is_object()))
22266 if (JSON_HEDLEY_UNLIKELY(!is_object()))
1458522267 {
1458622268 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
1458722269 }
14588 if (JSON_UNLIKELY(not j.is_object()))
22270 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
1458922271 {
1459022272 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
1459122273 }
1463222314 assert_invariant();
1463322315 }
1463422316
14635 if (JSON_UNLIKELY(not is_object()))
22317 if (JSON_HEDLEY_UNLIKELY(!is_object()))
1463622318 {
1463722319 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
1463822320 }
1463922321
1464022322 // check if range iterators belong to the same JSON object
14641 if (JSON_UNLIKELY(first.m_object != last.m_object))
22323 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1464222324 {
1464322325 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
1464422326 }
1464522327
1464622328 // passed iterators must belong to objects
14647 if (JSON_UNLIKELY(not first.m_object->is_object() or not last.m_object->is_object()))
22329 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()
22330 || !last.m_object->is_object()))
1464822331 {
1464922332 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
1465022333 }
1467222355
1467322356 @since version 1.0.0
1467422357 */
14675 void swap(reference other) noexcept(std::is_nothrow_move_constructible<value_t>::value and std::is_nothrow_move_assignable<value_t>::value and
14676 std::is_nothrow_move_constructible<json_value>::value and std::is_nothrow_move_assignable<json_value>::value)
22358 void swap(reference other) noexcept (
22359 std::is_nothrow_move_constructible<value_t>::value&&
22360 std::is_nothrow_move_assignable<value_t>::value&&
22361 std::is_nothrow_move_constructible<json_value>::value&&
22362 std::is_nothrow_move_assignable<json_value>::value
22363 )
1467722364 {
1467822365 std::swap(m_type, other.m_type);
1467922366 std::swap(m_value, other.m_value);
1468022367 assert_invariant();
22368 }
22369
22370 /*!
22371 @brief exchanges the values
22372
22373 Exchanges the contents of the JSON value from @a left with those of @a right. Does not
22374 invoke any move, copy, or swap operations on individual elements. All
22375 iterators and references remain valid. The past-the-end iterator is
22376 invalidated. implemented as a friend function callable via ADL.
22377
22378 @param[in,out] left JSON value to exchange the contents with
22379 @param[in,out] right JSON value to exchange the contents with
22380
22381 @complexity Constant.
22382
22383 @liveexample{The example below shows how JSON values can be swapped with
22384 `swap()`.,swap__reference}
22385
22386 @since version 1.0.0
22387 */
22388 friend void swap(reference left, reference right) noexcept (
22389 std::is_nothrow_move_constructible<value_t>::value&&
22390 std::is_nothrow_move_assignable<value_t>::value&&
22391 std::is_nothrow_move_constructible<json_value>::value&&
22392 std::is_nothrow_move_assignable<json_value>::value
22393 )
22394 {
22395 left.swap(right);
1468122396 }
1468222397
1468322398 /*!
1470322418 void swap(array_t& other)
1470422419 {
1470522420 // swap only works for arrays
14706 if (JSON_LIKELY(is_array()))
22421 if (JSON_HEDLEY_LIKELY(is_array()))
1470722422 {
1470822423 std::swap(*(m_value.array), other);
1470922424 }
1473622451 void swap(object_t& other)
1473722452 {
1473822453 // swap only works for objects
14739 if (JSON_LIKELY(is_object()))
22454 if (JSON_HEDLEY_LIKELY(is_object()))
1474022455 {
1474122456 std::swap(*(m_value.object), other);
1474222457 }
1476922484 void swap(string_t& other)
1477022485 {
1477122486 // swap only works for strings
14772 if (JSON_LIKELY(is_string()))
22487 if (JSON_HEDLEY_LIKELY(is_string()))
1477322488 {
1477422489 std::swap(*(m_value.string), other);
1477522490 }
1477922494 }
1478022495 }
1478122496
22497 /*!
22498 @brief exchanges the values
22499
22500 Exchanges the contents of a JSON string with those of @a other. Does not
22501 invoke any move, copy, or swap operations on individual elements. All
22502 iterators and references remain valid. The past-the-end iterator is
22503 invalidated.
22504
22505 @param[in,out] other binary to exchange the contents with
22506
22507 @throw type_error.310 when JSON value is not a string; example: `"cannot
22508 use swap() with boolean"`
22509
22510 @complexity Constant.
22511
22512 @liveexample{The example below shows how strings can be swapped with
22513 `swap()`.,swap__binary_t}
22514
22515 @since version 3.8.0
22516 */
22517 void swap(binary_t& other)
22518 {
22519 // swap only works for strings
22520 if (JSON_HEDLEY_LIKELY(is_binary()))
22521 {
22522 std::swap(*(m_value.binary), other);
22523 }
22524 else
22525 {
22526 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22527 }
22528 }
22529
22530 /// @copydoc swap(binary_t)
22531 void swap(typename binary_t::container_type& other)
22532 {
22533 // swap only works for strings
22534 if (JSON_HEDLEY_LIKELY(is_binary()))
22535 {
22536 std::swap(*(m_value.binary), other);
22537 }
22538 else
22539 {
22540 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22541 }
22542 }
22543
1478222544 /// @}
1478322545
14784 public:
22546 public:
1478522547 //////////////////////////////////////////
1478622548 // lexicographical comparison operators //
1478722549 //////////////////////////////////////////
1479722559 their stored values are the same according to their respective
1479822560 `operator==`.
1479922561 - Integer and floating-point numbers are automatically converted before
14800 comparison. Note than two NaN values are always treated as unequal.
22562 comparison. Note that two NaN values are always treated as unequal.
1480122563 - Two JSON null values are equal.
1480222564
1480322565 @note Floating-point inside JSON values numbers are compared with
1480422566 `json::number_float_t::operator==` which is `double::operator==` by
1480522567 default. To compare floating-point while respecting an epsilon, an alternative
14806 [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
22568 [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
1480722569 could be used, for instance
1480822570 @code {.cpp}
1480922571 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
1481222574 return std::abs(a - b) <= epsilon;
1481322575 }
1481422576 @endcode
22577 Or you can self-defined operator equal function like this:
22578 @code {.cpp}
22579 bool my_equal(const_reference lhs, const_reference rhs) {
22580 const auto lhs_type lhs.type();
22581 const auto rhs_type rhs.type();
22582 if (lhs_type == rhs_type) {
22583 switch(lhs_type)
22584 // self_defined case
22585 case value_t::number_float:
22586 return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
22587 // other cases remain the same with the original
22588 ...
22589 }
22590 ...
22591 }
22592 @endcode
1481522593
1481622594 @note NaN values never compare equal to themselves or to other NaN values.
1481722595
1483822616 switch (lhs_type)
1483922617 {
1484022618 case value_t::array:
14841 return (*lhs.m_value.array == *rhs.m_value.array);
22619 return *lhs.m_value.array == *rhs.m_value.array;
1484222620
1484322621 case value_t::object:
14844 return (*lhs.m_value.object == *rhs.m_value.object);
22622 return *lhs.m_value.object == *rhs.m_value.object;
1484522623
1484622624 case value_t::null:
1484722625 return true;
1484822626
1484922627 case value_t::string:
14850 return (*lhs.m_value.string == *rhs.m_value.string);
22628 return *lhs.m_value.string == *rhs.m_value.string;
1485122629
1485222630 case value_t::boolean:
14853 return (lhs.m_value.boolean == rhs.m_value.boolean);
22631 return lhs.m_value.boolean == rhs.m_value.boolean;
1485422632
1485522633 case value_t::number_integer:
14856 return (lhs.m_value.number_integer == rhs.m_value.number_integer);
22634 return lhs.m_value.number_integer == rhs.m_value.number_integer;
1485722635
1485822636 case value_t::number_unsigned:
14859 return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
22637 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
1486022638
1486122639 case value_t::number_float:
14862 return (lhs.m_value.number_float == rhs.m_value.number_float);
22640 return lhs.m_value.number_float == rhs.m_value.number_float;
22641
22642 case value_t::binary:
22643 return *lhs.m_value.binary == *rhs.m_value.binary;
1486322644
1486422645 default:
1486522646 return false;
1486622647 }
1486722648 }
14868 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
14869 {
14870 return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
14871 }
14872 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
14873 {
14874 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
14875 }
14876 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
14877 {
14878 return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
14879 }
14880 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
14881 {
14882 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
14883 }
14884 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
14885 {
14886 return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
14887 }
14888 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
14889 {
14890 return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
22649 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
22650 {
22651 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
22652 }
22653 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
22654 {
22655 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
22656 }
22657 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
22658 {
22659 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
22660 }
22661 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
22662 {
22663 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
22664 }
22665 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
22666 {
22667 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
22668 }
22669 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
22670 {
22671 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
1489122672 }
1489222673
1489322674 return false;
1489722678 @brief comparison: equal
1489822679 @copydoc operator==(const_reference, const_reference)
1489922680 */
14900 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22681 template<typename ScalarType, typename std::enable_if<
22682 std::is_scalar<ScalarType>::value, int>::type = 0>
1490122683 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
1490222684 {
14903 return (lhs == basic_json(rhs));
22685 return lhs == basic_json(rhs);
1490422686 }
1490522687
1490622688 /*!
1490722689 @brief comparison: equal
1490822690 @copydoc operator==(const_reference, const_reference)
1490922691 */
14910 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22692 template<typename ScalarType, typename std::enable_if<
22693 std::is_scalar<ScalarType>::value, int>::type = 0>
1491122694 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
1491222695 {
14913 return (basic_json(lhs) == rhs);
22696 return basic_json(lhs) == rhs;
1491422697 }
1491522698
1491622699 /*!
1493322716 */
1493422717 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
1493522718 {
14936 return not(lhs == rhs);
22719 return !(lhs == rhs);
1493722720 }
1493822721
1493922722 /*!
1494022723 @brief comparison: not equal
1494122724 @copydoc operator!=(const_reference, const_reference)
1494222725 */
14943 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22726 template<typename ScalarType, typename std::enable_if<
22727 std::is_scalar<ScalarType>::value, int>::type = 0>
1494422728 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
1494522729 {
14946 return (lhs != basic_json(rhs));
22730 return lhs != basic_json(rhs);
1494722731 }
1494822732
1494922733 /*!
1495022734 @brief comparison: not equal
1495122735 @copydoc operator!=(const_reference, const_reference)
1495222736 */
14953 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22737 template<typename ScalarType, typename std::enable_if<
22738 std::is_scalar<ScalarType>::value, int>::type = 0>
1495422739 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
1495522740 {
14956 return (basic_json(lhs) != rhs);
22741 return basic_json(lhs) != rhs;
1495722742 }
1495822743
1495922744 /*!
1499222777 switch (lhs_type)
1499322778 {
1499422779 case value_t::array:
22780 // note parentheses are necessary, see
22781 // https://github.com/nlohmann/json/issues/1530
1499522782 return (*lhs.m_value.array) < (*rhs.m_value.array);
1499622783
1499722784 case value_t::object:
14998 return *lhs.m_value.object < *rhs.m_value.object;
22785 return (*lhs.m_value.object) < (*rhs.m_value.object);
1499922786
1500022787 case value_t::null:
1500122788 return false;
1500222789
1500322790 case value_t::string:
15004 return *lhs.m_value.string < *rhs.m_value.string;
22791 return (*lhs.m_value.string) < (*rhs.m_value.string);
1500522792
1500622793 case value_t::boolean:
15007 return lhs.m_value.boolean < rhs.m_value.boolean;
22794 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
1500822795
1500922796 case value_t::number_integer:
15010 return lhs.m_value.number_integer < rhs.m_value.number_integer;
22797 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
1501122798
1501222799 case value_t::number_unsigned:
15013 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
22800 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
1501422801
1501522802 case value_t::number_float:
15016 return lhs.m_value.number_float < rhs.m_value.number_float;
22803 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
22804
22805 case value_t::binary:
22806 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
1501722807
1501822808 default:
1501922809 return false;
1502022810 }
1502122811 }
15022 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
22812 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
1502322813 {
1502422814 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
1502522815 }
15026 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
22816 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
1502722817 {
1502822818 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
1502922819 }
15030 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
22820 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
1503122821 {
1503222822 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
1503322823 }
15034 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
22824 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
1503522825 {
1503622826 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
1503722827 }
15038 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
22828 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
1503922829 {
1504022830 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
1504122831 }
15042 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
22832 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
1504322833 {
1504422834 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
1504522835 }
1505422844 @brief comparison: less than
1505522845 @copydoc operator<(const_reference, const_reference)
1505622846 */
15057 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22847 template<typename ScalarType, typename std::enable_if<
22848 std::is_scalar<ScalarType>::value, int>::type = 0>
1505822849 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
1505922850 {
15060 return (lhs < basic_json(rhs));
22851 return lhs < basic_json(rhs);
1506122852 }
1506222853
1506322854 /*!
1506422855 @brief comparison: less than
1506522856 @copydoc operator<(const_reference, const_reference)
1506622857 */
15067 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22858 template<typename ScalarType, typename std::enable_if<
22859 std::is_scalar<ScalarType>::value, int>::type = 0>
1506822860 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
1506922861 {
15070 return (basic_json(lhs) < rhs);
22862 return basic_json(lhs) < rhs;
1507122863 }
1507222864
1507322865 /*!
1509122883 */
1509222884 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
1509322885 {
15094 return not(rhs < lhs);
22886 return !(rhs < lhs);
1509522887 }
1509622888
1509722889 /*!
1509822890 @brief comparison: less than or equal
1509922891 @copydoc operator<=(const_reference, const_reference)
1510022892 */
15101 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22893 template<typename ScalarType, typename std::enable_if<
22894 std::is_scalar<ScalarType>::value, int>::type = 0>
1510222895 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
1510322896 {
15104 return (lhs <= basic_json(rhs));
22897 return lhs <= basic_json(rhs);
1510522898 }
1510622899
1510722900 /*!
1510822901 @brief comparison: less than or equal
1510922902 @copydoc operator<=(const_reference, const_reference)
1511022903 */
15111 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22904 template<typename ScalarType, typename std::enable_if<
22905 std::is_scalar<ScalarType>::value, int>::type = 0>
1511222906 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
1511322907 {
15114 return (basic_json(lhs) <= rhs);
22908 return basic_json(lhs) <= rhs;
1511522909 }
1511622910
1511722911 /*!
1513522929 */
1513622930 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
1513722931 {
15138 return not(lhs <= rhs);
22932 return !(lhs <= rhs);
1513922933 }
1514022934
1514122935 /*!
1514222936 @brief comparison: greater than
1514322937 @copydoc operator>(const_reference, const_reference)
1514422938 */
15145 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22939 template<typename ScalarType, typename std::enable_if<
22940 std::is_scalar<ScalarType>::value, int>::type = 0>
1514622941 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
1514722942 {
15148 return (lhs > basic_json(rhs));
22943 return lhs > basic_json(rhs);
1514922944 }
1515022945
1515122946 /*!
1515222947 @brief comparison: greater than
1515322948 @copydoc operator>(const_reference, const_reference)
1515422949 */
15155 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22950 template<typename ScalarType, typename std::enable_if<
22951 std::is_scalar<ScalarType>::value, int>::type = 0>
1515622952 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
1515722953 {
15158 return (basic_json(lhs) > rhs);
22954 return basic_json(lhs) > rhs;
1515922955 }
1516022956
1516122957 /*!
1517922975 */
1518022976 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
1518122977 {
15182 return not(lhs < rhs);
22978 return !(lhs < rhs);
1518322979 }
1518422980
1518522981 /*!
1518622982 @brief comparison: greater than or equal
1518722983 @copydoc operator>=(const_reference, const_reference)
1518822984 */
15189 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22985 template<typename ScalarType, typename std::enable_if<
22986 std::is_scalar<ScalarType>::value, int>::type = 0>
1519022987 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
1519122988 {
15192 return (lhs >= basic_json(rhs));
22989 return lhs >= basic_json(rhs);
1519322990 }
1519422991
1519522992 /*!
1519622993 @brief comparison: greater than or equal
1519722994 @copydoc operator>=(const_reference, const_reference)
1519822995 */
15199 template <typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
22996 template<typename ScalarType, typename std::enable_if<
22997 std::is_scalar<ScalarType>::value, int>::type = 0>
1520022998 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
1520122999 {
15202 return (basic_json(lhs) >= rhs);
23000 return basic_json(lhs) >= rhs;
1520323001 }
1520423002
1520523003 /// @}
1524523043 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
1524623044 {
1524723045 // read width member and use it as indentation parameter if nonzero
15248 const bool pretty_print = (o.width() > 0);
15249 const auto indentation = (pretty_print ? o.width() : 0);
23046 const bool pretty_print = o.width() > 0;
23047 const auto indentation = pretty_print ? o.width() : 0;
1525023048
1525123049 // reset width to 0 for subsequent calls to this stream
1525223050 o.width(0);
1526523063 instead; that is, replace calls like `j >> o;` with `o << j;`.
1526623064 @since version 1.0.0; deprecated since version 3.0.0
1526723065 */
15268 JSON_DEPRECATED
23066 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
1526923067 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
1527023068 {
1527123069 return o << j;
1528423082 /*!
1528523083 @brief deserialize from a compatible input
1528623084
15287 This function reads from a compatible input. Examples are:
15288 - an array of 1-byte values
15289 - strings with character/literal type with size of 1 byte
15290 - input streams
15291 - container with contiguous storage of 1-byte values. Compatible container
15292 types include `std::vector`, `std::string`, `std::array`,
15293 `std::valarray`, and `std::initializer_list`. Furthermore, C-style
15294 arrays can be used with `std::begin()`/`std::end()`. User-defined
15295 containers can be used as long as they implement random-access iterators
15296 and a contiguous storage.
15297
15298 @pre Each element of the container has a size of 1 byte. Violating this
15299 precondition yields undefined behavior. **This precondition is enforced
15300 with a static assertion.**
15301
15302 @pre The container storage is contiguous. Violating this precondition
15303 yields undefined behavior. **This precondition is enforced with an
15304 assertion.**
15305 @pre Each element of the container has a size of 1 byte. Violating this
15306 precondition yields undefined behavior. **This precondition is enforced
15307 with a static assertion.**
15308
15309 @warning There is no way to enforce all preconditions at compile-time. If
15310 the function is called with a noncompliant container and with
15311 assertions switched off, the behavior is undefined and will most
15312 likely yield segmentation violation.
23085 @tparam InputType A compatible input, for instance
23086 - an std::istream object
23087 - a FILE pointer
23088 - a C-style array of characters
23089 - a pointer to a null-terminated string of single byte characters
23090 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23091 iterators.
1531323092
1531423093 @param[in] i input to read from
15315 @param[in] cb a parser callback function of type @ref parser_callback_t
15316 which is used to control the deserialization by filtering unwanted values
15317 (optional)
15318
15319 @return result of the deserialization
15320
15321 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
15322 of input; expected string literal""`
15323 @throw parse_error.102 if to_unicode fails or surrogate error
15324 @throw parse_error.103 if to_unicode fails
15325
15326 @complexity Linear in the length of the input. The parser is a predictive
15327 LL(1) parser. The complexity can be higher if the parser callback function
15328 @a cb has a super-linear complexity.
15329
15330 @note A UTF-8 byte order mark is silently ignored.
15331
15332 @liveexample{The example below demonstrates the `parse()` function reading
15333 from an array.,parse__array__parser_callback_t}
15334
15335 @liveexample{The example below demonstrates the `parse()` function with
15336 and without callback function.,parse__string__parser_callback_t}
15337
15338 @liveexample{The example below demonstrates the `parse()` function with
15339 and without callback function.,parse__istream__parser_callback_t}
15340
15341 @liveexample{The example below demonstrates the `parse()` function reading
15342 from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
15343
15344 @since version 2.0.3 (contiguous containers)
15345 */
15346 static basic_json parse(detail::input_adapter i, const parser_callback_t cb = nullptr, const bool allow_exceptions = true)
15347 {
15348 basic_json result;
15349 parser(i, cb, allow_exceptions).parse(true, result);
15350 return result;
15351 }
15352
15353 /*!
15354 @copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
15355 */
15356 static basic_json parse(detail::input_adapter& i, const parser_callback_t cb = nullptr, const bool allow_exceptions = true)
15357 {
15358 basic_json result;
15359 parser(i, cb, allow_exceptions).parse(true, result);
15360 return result;
15361 }
15362
15363 static bool accept(detail::input_adapter i)
15364 {
15365 return parser(i).accept(true);
15366 }
15367
15368 static bool accept(detail::input_adapter& i)
15369 {
15370 return parser(i).accept(true);
15371 }
15372
15373 /*!
15374 @brief deserialize from an iterator range with contiguous storage
15375
15376 This function reads from an iterator range of a container with contiguous
15377 storage of 1-byte values. Compatible container types include
15378 `std::vector`, `std::string`, `std::array`, `std::valarray`, and
15379 `std::initializer_list`. Furthermore, C-style arrays can be used with
15380 `std::begin()`/`std::end()`. User-defined containers can be used as long
15381 as they implement random-access iterators and a contiguous storage.
15382
15383 @pre The iterator range is contiguous. Violating this precondition yields
15384 undefined behavior. **This precondition is enforced with an assertion.**
15385 @pre Each element in the range has a size of 1 byte. Violating this
15386 precondition yields undefined behavior. **This precondition is enforced
15387 with a static assertion.**
15388
15389 @warning There is no way to enforce all preconditions at compile-time. If
15390 the function is called with noncompliant iterators and with
15391 assertions switched off, the behavior is undefined and will most
15392 likely yield segmentation violation.
15393
15394 @tparam IteratorType iterator of container with contiguous storage
15395 @param[in] first begin of the range to parse (included)
15396 @param[in] last end of the range to parse (excluded)
1539723094 @param[in] cb a parser callback function of type @ref parser_callback_t
1539823095 which is used to control the deserialization by filtering unwanted values
1539923096 (optional)
1540023097 @param[in] allow_exceptions whether to throw exceptions in case of a
1540123098 parse error (optional, true by default)
15402
15403 @return result of the deserialization
15404
15405 @throw parse_error.101 in case of an unexpected token
23099 @param[in] ignore_comments whether comments should be ignored and treated
23100 like whitespace (true) or yield a parse error (true); (optional, false by
23101 default)
23102
23103 @return deserialized JSON value; in case of a parse error and
23104 @a allow_exceptions set to `false`, the return value will be
23105 value_t::discarded.
23106
23107 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23108 of input; expected string literal""`
1540623109 @throw parse_error.102 if to_unicode fails or surrogate error
1540723110 @throw parse_error.103 if to_unicode fails
1540823111
1540923112 @complexity Linear in the length of the input. The parser is a predictive
1541023113 LL(1) parser. The complexity can be higher if the parser callback function
15411 @a cb has a super-linear complexity.
23114 @a cb or reading from the input @a i has a super-linear complexity.
1541223115
1541323116 @note A UTF-8 byte order mark is silently ignored.
1541423117
1541523118 @liveexample{The example below demonstrates the `parse()` function reading
15416 from an iterator range.,parse__iteratortype__parser_callback_t}
15417
15418 @since version 2.0.3
15419 */
15420 template <class IteratorType,
15421 typename std::enable_if<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<IteratorType>::iterator_category>::value,
15422 int>::type = 0>
15423 static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr, const bool allow_exceptions = true)
23119 from an array.,parse__array__parser_callback_t}
23120
23121 @liveexample{The example below demonstrates the `parse()` function with
23122 and without callback function.,parse__string__parser_callback_t}
23123
23124 @liveexample{The example below demonstrates the `parse()` function with
23125 and without callback function.,parse__istream__parser_callback_t}
23126
23127 @liveexample{The example below demonstrates the `parse()` function reading
23128 from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
23129
23130 @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to
23131 ignore comments.
23132 */
23133 template<typename InputType>
23134 JSON_HEDLEY_WARN_UNUSED_RESULT
23135 static basic_json parse(InputType&& i,
23136 const parser_callback_t cb = nullptr,
23137 const bool allow_exceptions = true,
23138 const bool ignore_comments = false)
1542423139 {
1542523140 basic_json result;
15426 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
23141 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
1542723142 return result;
1542823143 }
1542923144
15430 template <class IteratorType,
15431 typename std::enable_if<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<IteratorType>::iterator_category>::value,
15432 int>::type = 0>
15433 static bool accept(IteratorType first, IteratorType last)
15434 {
15435 return parser(detail::input_adapter(first, last)).accept(true);
23145 /*!
23146 @brief deserialize from a pair of character iterators
23147
23148 The value_type of the iterator must be a integral type with size of 1, 2 or
23149 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
23150
23151 @param[in] first iterator to start of character range
23152 @param[in] last iterator to end of character range
23153 @param[in] cb a parser callback function of type @ref parser_callback_t
23154 which is used to control the deserialization by filtering unwanted values
23155 (optional)
23156 @param[in] allow_exceptions whether to throw exceptions in case of a
23157 parse error (optional, true by default)
23158 @param[in] ignore_comments whether comments should be ignored and treated
23159 like whitespace (true) or yield a parse error (true); (optional, false by
23160 default)
23161
23162 @return deserialized JSON value; in case of a parse error and
23163 @a allow_exceptions set to `false`, the return value will be
23164 value_t::discarded.
23165
23166 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23167 of input; expected string literal""`
23168 @throw parse_error.102 if to_unicode fails or surrogate error
23169 @throw parse_error.103 if to_unicode fails
23170 */
23171 template<typename IteratorType>
23172 JSON_HEDLEY_WARN_UNUSED_RESULT
23173 static basic_json parse(IteratorType first,
23174 IteratorType last,
23175 const parser_callback_t cb = nullptr,
23176 const bool allow_exceptions = true,
23177 const bool ignore_comments = false)
23178 {
23179 basic_json result;
23180 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23181 return result;
23182 }
23183
23184 JSON_HEDLEY_WARN_UNUSED_RESULT
23185 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23186 static basic_json parse(detail::span_input_adapter&& i,
23187 const parser_callback_t cb = nullptr,
23188 const bool allow_exceptions = true,
23189 const bool ignore_comments = false)
23190 {
23191 basic_json result;
23192 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23193 return result;
23194 }
23195
23196 /*!
23197 @brief check if the input is valid JSON
23198
23199 Unlike the @ref parse(InputType&&, const parser_callback_t,const bool)
23200 function, this function neither throws an exception in case of invalid JSON
23201 input (i.e., a parse error) nor creates diagnostic information.
23202
23203 @tparam InputType A compatible input, for instance
23204 - an std::istream object
23205 - a FILE pointer
23206 - a C-style array of characters
23207 - a pointer to a null-terminated string of single byte characters
23208 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23209 iterators.
23210
23211 @param[in] i input to read from
23212 @param[in] ignore_comments whether comments should be ignored and treated
23213 like whitespace (true) or yield a parse error (true); (optional, false by
23214 default)
23215
23216 @return Whether the input read from @a i is valid JSON.
23217
23218 @complexity Linear in the length of the input. The parser is a predictive
23219 LL(1) parser.
23220
23221 @note A UTF-8 byte order mark is silently ignored.
23222
23223 @liveexample{The example below demonstrates the `accept()` function reading
23224 from a string.,accept__string}
23225 */
23226 template<typename InputType>
23227 static bool accept(InputType&& i,
23228 const bool ignore_comments = false)
23229 {
23230 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23231 }
23232
23233 template<typename IteratorType>
23234 static bool accept(IteratorType first, IteratorType last,
23235 const bool ignore_comments = false)
23236 {
23237 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23238 }
23239
23240 JSON_HEDLEY_WARN_UNUSED_RESULT
23241 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23242 static bool accept(detail::span_input_adapter&& i,
23243 const bool ignore_comments = false)
23244 {
23245 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23246 }
23247
23248 /*!
23249 @brief generate SAX events
23250
23251 The SAX event lister must follow the interface of @ref json_sax.
23252
23253 This function reads from a compatible input. Examples are:
23254 - an std::istream object
23255 - a FILE pointer
23256 - a C-style array of characters
23257 - a pointer to a null-terminated string of single byte characters
23258 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23259 iterators.
23260
23261 @param[in] i input to read from
23262 @param[in,out] sax SAX event listener
23263 @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
23264 @param[in] strict whether the input has to be consumed completely
23265 @param[in] ignore_comments whether comments should be ignored and treated
23266 like whitespace (true) or yield a parse error (true); (optional, false by
23267 default); only applies to the JSON file format.
23268
23269 @return return value of the last processed SAX event
23270
23271 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23272 of input; expected string literal""`
23273 @throw parse_error.102 if to_unicode fails or surrogate error
23274 @throw parse_error.103 if to_unicode fails
23275
23276 @complexity Linear in the length of the input. The parser is a predictive
23277 LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
23278 a super-linear complexity.
23279
23280 @note A UTF-8 byte order mark is silently ignored.
23281
23282 @liveexample{The example below demonstrates the `sax_parse()` function
23283 reading from string and processing the events with a user-defined SAX
23284 event consumer.,sax_parse}
23285
23286 @since version 3.2.0
23287 */
23288 template <typename InputType, typename SAX>
23289 JSON_HEDLEY_NON_NULL(2)
23290 static bool sax_parse(InputType&& i, SAX* sax,
23291 input_format_t format = input_format_t::json,
23292 const bool strict = true,
23293 const bool ignore_comments = false)
23294 {
23295 auto ia = detail::input_adapter(std::forward<InputType>(i));
23296 return format == input_format_t::json
23297 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23298 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23299 }
23300
23301 template<class IteratorType, class SAX>
23302 JSON_HEDLEY_NON_NULL(3)
23303 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23304 input_format_t format = input_format_t::json,
23305 const bool strict = true,
23306 const bool ignore_comments = false)
23307 {
23308 auto ia = detail::input_adapter(std::move(first), std::move(last));
23309 return format == input_format_t::json
23310 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23311 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23312 }
23313
23314 template <typename SAX>
23315 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23316 JSON_HEDLEY_NON_NULL(2)
23317 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23318 input_format_t format = input_format_t::json,
23319 const bool strict = true,
23320 const bool ignore_comments = false)
23321 {
23322 auto ia = i.get();
23323 return format == input_format_t::json
23324 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23325 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
1543623326 }
1543723327
1543823328 /*!
1544323333 instead; that is, replace calls like `j << i;` with `i >> j;`.
1544423334 @since version 1.0.0; deprecated since version 3.0.0
1544523335 */
15446 JSON_DEPRECATED
23336 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
1544723337 friend std::istream& operator<<(basic_json& j, std::istream& i)
1544823338 {
1544923339 return operator>>(i, j);
1550123391 number | `"number"` (for all number types)
1550223392 object | `"object"`
1550323393 array | `"array"`
23394 binary | `"binary"`
1550423395 discarded | `"discarded"`
1550523396
1550623397 @exceptionsafety No-throw guarantee: this function never throws exceptions.
1551623407 @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
1551723408 since 3.0.0
1551823409 */
23410 JSON_HEDLEY_RETURNS_NON_NULL
1551923411 const char* type_name() const noexcept
1552023412 {
1552123413 {
1553123423 return "string";
1553223424 case value_t::boolean:
1553323425 return "boolean";
23426 case value_t::binary:
23427 return "binary";
1553423428 case value_t::discarded:
1553523429 return "discarded";
1553623430 default:
1554023434 }
1554123435
1554223436
15543 private:
23437 private:
1554423438 //////////////////////
1554523439 // member variables //
1554623440 //////////////////////
1555823452 /// @name binary serialization/deserialization support
1555923453 /// @{
1556023454
15561 public:
23455 public:
1556223456 /*!
1556323457 @brief create a CBOR serialization of a given JSON value
1556423458
1559023484 number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
1559123485 number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
1559223486 number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
15593 number_float | *any value* | Double-Precision Float | 0xFB
23487 number_float | *any value representable by a float* | Single-Precision Float | 0xFA
23488 number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB
1559423489 string | *length*: 0..23 | UTF-8 string | 0x60..0x77
1559523490 string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
1559623491 string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
1560623501 object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
1560723502 object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
1560823503 object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
23504 binary | *size*: 0..23 | byte string | 0x40..0x57
23505 binary | *size*: 23..255 | byte string (1 byte follow) | 0x58
23506 binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59
23507 binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
23508 binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
1560923509
1561023510 @note The mapping is **complete** in the sense that any JSON value type
1561123511 can be converted to a CBOR value.
1561523515 function which serializes NaN or Infinity to `null`.
1561623516
1561723517 @note The following CBOR types are not used in the conversion:
15618 - byte strings (0x40..0x5F)
1561923518 - UTF-8 strings terminated by "break" (0x7F)
1562023519 - arrays terminated by "break" (0x9F)
1562123520 - maps terminated by "break" (0xBF)
23521 - byte strings terminated by "break" (0x5F)
1562223522 - date/time (0xC0..0xC1)
1562323523 - bignum (0xC2..0xC3)
1562423524 - decimal fraction (0xC4)
1562523525 - bigfloat (0xC5)
15626 - tagged items (0xC6..0xD4, 0xD8..0xDB)
1562723526 - expected conversions (0xD5..0xD7)
1562823527 - simple values (0xE0..0xF3, 0xF8)
1562923528 - undefined (0xF7)
15630 - half and single-precision floats (0xF9-0xFA)
23529 - half-precision floats (0xF9)
1563123530 - break (0xFF)
1563223531
1563323532 @param[in] j JSON value to serialize
15634 @return MessagePack serialization as byte vector
23533 @return CBOR serialization as byte vector
1563523534
1563623535 @complexity Linear in the size of the JSON value @a j.
1563723536
1563923538 vector in CBOR format.,to_cbor}
1564023539
1564123540 @sa http://cbor.io
15642 @sa @ref from_cbor(detail::input_adapter, const bool strict) for the
23541 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
1564323542 analogous deserialization
1564423543 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
1564523544 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
1564623545 related UBJSON format
1564723546
15648 @since version 2.0.9
23547 @since version 2.0.9; compact representation of floating-point numbers
23548 since version 3.8.0
1564923549 */
1565023550 static std::vector<uint8_t> to_cbor(const basic_json& j)
1565123551 {
1569423594 number_unsigned | 256..65535 | uint 16 | 0xCD
1569523595 number_unsigned | 65536..4294967295 | uint 32 | 0xCE
1569623596 number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
15697 number_float | *any value* | float 64 | 0xCB
23597 number_float | *any value representable by a float* | float 32 | 0xCA
23598 number_float | *any value NOT representable by a float* | float 64 | 0xCB
1569823599 string | *length*: 0..31 | fixstr | 0xA0..0xBF
1569923600 string | *length*: 32..255 | str 8 | 0xD9
1570023601 string | *length*: 256..65535 | str 16 | 0xDA
1570523606 object | *size*: 0..15 | fix map | 0x80..0x8F
1570623607 object | *size*: 16..65535 | map 16 | 0xDE
1570723608 object | *size*: 65536..4294967295 | map 32 | 0xDF
23609 binary | *size*: 0..255 | bin 8 | 0xC4
23610 binary | *size*: 256..65535 | bin 16 | 0xC5
23611 binary | *size*: 65536..4294967295 | bin 32 | 0xC6
1570823612
1570923613 @note The mapping is **complete** in the sense that any JSON value type
1571023614 can be converted to a MessagePack value.
1571123615
1571223616 @note The following values can **not** be converted to a MessagePack value:
1571323617 - strings with more than 4294967295 bytes
23618 - byte strings with more than 4294967295 bytes
1571423619 - arrays with more than 4294967295 elements
1571523620 - objects with more than 4294967295 elements
15716
15717 @note The following MessagePack types are not used in the conversion:
15718 - bin 8 - bin 32 (0xC4..0xC6)
15719 - ext 8 - ext 32 (0xC7..0xC9)
15720 - float 32 (0xCA)
15721 - fixext 1 - fixext 16 (0xD4..0xD8)
1572223621
1572323622 @note Any MessagePack output created @ref to_msgpack can be successfully
1572423623 parsed by @ref from_msgpack.
1573623635 vector in MessagePack format.,to_msgpack}
1573723636
1573823637 @sa http://msgpack.org
15739 @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
15740 analogous deserialization
23638 @sa @ref from_msgpack for the analogous deserialization
1574123639 @sa @ref to_cbor(const basic_json& for the related CBOR format
1574223640 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
1574323641 related UBJSON format
1578923687 number_unsigned | 256..32767 | int16 | `I`
1579023688 number_unsigned | 32768..2147483647 | int32 | `l`
1579123689 number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
23690 number_unsigned | 2147483649..18446744073709551615 | high-precision | `H`
1579223691 number_float | *any value* | float64 | `D`
1579323692 string | *with shortest length indicator* | string | `S`
1579423693 array | *see notes on optimized format* | array | `[`
1579923698
1580023699 @note The following values can **not** be converted to a UBJSON value:
1580123700 - strings with more than 9223372036854775807 bytes (theoretical)
15802 - unsigned integer numbers above 9223372036854775807
1580323701
1580423702 @note The following markers are not used in the conversion:
1580523703 - `Z`: no-op values are not created.
1582223720 the benefit of this parameter is that the receiving side is
1582323721 immediately informed on the number of elements of the container.
1582423722
23723 @note If the JSON data contains the binary type, the value stored is a list
23724 of integers, as suggested by the UBJSON documentation. In particular,
23725 this means that serialization and the deserialization of a JSON
23726 containing binary values into UBJSON and back will result in a
23727 different JSON object.
23728
1582523729 @param[in] j JSON value to serialize
1582623730 @param[in] use_size whether to add size annotations to container types
1582723731 @param[in] use_type whether to add type annotations to container types
1583423738 vector in UBJSON format.,to_ubjson}
1583523739
1583623740 @sa http://ubjson.org
15837 @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the
23741 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
1583823742 analogous deserialization
1583923743 @sa @ref to_cbor(const basic_json& for the related CBOR format
1584023744 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
1584123745
1584223746 @since version 3.1.0
1584323747 */
15844 static std::vector<uint8_t> to_ubjson(const basic_json& j, const bool use_size = false, const bool use_type = false)
23748 static std::vector<uint8_t> to_ubjson(const basic_json& j,
23749 const bool use_size = false,
23750 const bool use_type = false)
1584523751 {
1584623752 std::vector<uint8_t> result;
1584723753 to_ubjson(j, result, use_size, use_type);
1584823754 return result;
1584923755 }
1585023756
15851 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o, const bool use_size = false, const bool use_type = false)
23757 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
23758 const bool use_size = false, const bool use_type = false)
1585223759 {
1585323760 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
1585423761 }
1585523762
15856 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, const bool use_size = false, const bool use_type = false)
23763 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23764 const bool use_size = false, const bool use_type = false)
1585723765 {
1585823766 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
1585923767 }
23768
23769
23770 /*!
23771 @brief Serializes the given JSON object `j` to BSON and returns a vector
23772 containing the corresponding BSON-representation.
23773
23774 BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
23775 stored as a single entity (a so-called document).
23776
23777 The library uses the following mapping from JSON values types to BSON types:
23778
23779 JSON value type | value/range | BSON type | marker
23780 --------------- | --------------------------------- | ----------- | ------
23781 null | `null` | null | 0x0A
23782 boolean | `true`, `false` | boolean | 0x08
23783 number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
23784 number_integer | -2147483648..2147483647 | int32 | 0x10
23785 number_integer | 2147483648..9223372036854775807 | int64 | 0x12
23786 number_unsigned | 0..2147483647 | int32 | 0x10
23787 number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
23788 number_unsigned | 9223372036854775808..18446744073709551615| -- | --
23789 number_float | *any value* | double | 0x01
23790 string | *any value* | string | 0x02
23791 array | *any value* | document | 0x04
23792 object | *any value* | document | 0x03
23793 binary | *any value* | binary | 0x05
23794
23795 @warning The mapping is **incomplete**, since only JSON-objects (and things
23796 contained therein) can be serialized to BSON.
23797 Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
23798 and the keys may not contain U+0000, since they are serialized a
23799 zero-terminated c-strings.
23800
23801 @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
23802 @throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
23803 @throw type_error.317 if `!j.is_object()`
23804
23805 @pre The input `j` is required to be an object: `j.is_object() == true`.
23806
23807 @note Any BSON output created via @ref to_bson can be successfully parsed
23808 by @ref from_bson.
23809
23810 @param[in] j JSON value to serialize
23811 @return BSON serialization as byte vector
23812
23813 @complexity Linear in the size of the JSON value @a j.
23814
23815 @liveexample{The example shows the serialization of a JSON value to a byte
23816 vector in BSON format.,to_bson}
23817
23818 @sa http://bsonspec.org/spec.html
23819 @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
23820 analogous deserialization
23821 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23822 related UBJSON format
23823 @sa @ref to_cbor(const basic_json&) for the related CBOR format
23824 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23825 */
23826 static std::vector<uint8_t> to_bson(const basic_json& j)
23827 {
23828 std::vector<uint8_t> result;
23829 to_bson(j, result);
23830 return result;
23831 }
23832
23833 /*!
23834 @brief Serializes the given JSON object `j` to BSON and forwards the
23835 corresponding BSON-representation to the given output_adapter `o`.
23836 @param j The JSON object to convert to BSON.
23837 @param o The output adapter that receives the binary BSON representation.
23838 @pre The input `j` shall be an object: `j.is_object() == true`
23839 @sa @ref to_bson(const basic_json&)
23840 */
23841 static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
23842 {
23843 binary_writer<uint8_t>(o).write_bson(j);
23844 }
23845
23846 /*!
23847 @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
23848 */
23849 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23850 {
23851 binary_writer<char>(o).write_bson(j);
23852 }
23853
1586023854
1586123855 /*!
1586223856 @brief create a JSON value from an input in CBOR format
1587823872 Negative integer | number_integer | 0x39
1587923873 Negative integer | number_integer | 0x3A
1588023874 Negative integer | number_integer | 0x3B
15881 Negative integer | number_integer | 0x40..0x57
23875 Byte string | binary | 0x40..0x57
23876 Byte string | binary | 0x58
23877 Byte string | binary | 0x59
23878 Byte string | binary | 0x5A
23879 Byte string | binary | 0x5B
1588223880 UTF-8 string | string | 0x60..0x77
1588323881 UTF-8 string | string | 0x78
1588423882 UTF-8 string | string | 0x79
1589923897 map | object | 0xBF
1590023898 False | `false` | 0xF4
1590123899 True | `true` | 0xF5
15902 Nill | `null` | 0xF6
23900 Null | `null` | 0xF6
1590323901 Half-Precision Float | number_float | 0xF9
1590423902 Single-Precision Float | number_float | 0xFA
1590523903 Double-Precision Float | number_float | 0xFB
1590723905 @warning The mapping is **incomplete** in the sense that not all CBOR
1590823906 types can be converted to a JSON value. The following CBOR types
1590923907 are not supported and will yield parse errors (parse_error.112):
15910 - byte strings (0x40..0x5F)
1591123908 - date/time (0xC0..0xC1)
1591223909 - bignum (0xC2..0xC3)
1591323910 - decimal fraction (0xC4)
1591423911 - bigfloat (0xC5)
15915 - tagged items (0xC6..0xD4, 0xD8..0xDB)
1591623912 - expected conversions (0xD5..0xD7)
1591723913 - simple values (0xE0..0xF3, 0xF8)
1591823914 - undefined (0xF7)
1592723923 @param[in] i an input in CBOR format convertible to an input adapter
1592823924 @param[in] strict whether to expect the input to be consumed until EOF
1592923925 (true by default)
15930 @return deserialized JSON value
23926 @param[in] allow_exceptions whether to throw exceptions in case of a
23927 parse error (optional, true by default)
23928 @param[in] tag_handler how to treat CBOR tags (optional, error by default)
23929
23930 @return deserialized JSON value; in case of a parse error and
23931 @a allow_exceptions set to `false`, the return value will be
23932 value_t::discarded.
1593123933
1593223934 @throw parse_error.110 if the given input ends prematurely or the end of
1593323935 file was not reached when @a strict was set to true
1594223944
1594323945 @sa http://cbor.io
1594423946 @sa @ref to_cbor(const basic_json&) for the analogous serialization
15945 @sa @ref from_msgpack(detail::input_adapter, const bool) for the
23947 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
1594623948 related MessagePack format
15947 @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
15948 UBJSON format
23949 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
23950 related UBJSON format
1594923951
1595023952 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
1595123953 consume input adapters, removed start_index parameter, and added
15952 @a strict parameter since 3.0.0
15953 */
15954 static basic_json from_cbor(detail::input_adapter i, const bool strict = true)
15955 {
15956 return binary_reader(i).parse_cbor(strict);
15957 }
15958
15959 /*!
15960 @copydoc from_cbor(detail::input_adapter, const bool)
15961 */
15962 template <typename A1, typename A2, detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
15963 static basic_json from_cbor(A1&& a1, A2&& a2, const bool strict = true)
15964 {
15965 return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
23954 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
23955 since 3.2.0; added @a tag_handler parameter since 3.9.0.
23956 */
23957 template<typename InputType>
23958 JSON_HEDLEY_WARN_UNUSED_RESULT
23959 static basic_json from_cbor(InputType&& i,
23960 const bool strict = true,
23961 const bool allow_exceptions = true,
23962 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23963 {
23964 basic_json result;
23965 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23966 auto ia = detail::input_adapter(std::forward<InputType>(i));
23967 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23968 return res ? result : basic_json(value_t::discarded);
23969 }
23970
23971 /*!
23972 @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t)
23973 */
23974 template<typename IteratorType>
23975 JSON_HEDLEY_WARN_UNUSED_RESULT
23976 static basic_json from_cbor(IteratorType first, IteratorType last,
23977 const bool strict = true,
23978 const bool allow_exceptions = true,
23979 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23980 {
23981 basic_json result;
23982 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23983 auto ia = detail::input_adapter(std::move(first), std::move(last));
23984 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23985 return res ? result : basic_json(value_t::discarded);
23986 }
23987
23988 template<typename T>
23989 JSON_HEDLEY_WARN_UNUSED_RESULT
23990 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23991 static basic_json from_cbor(const T* ptr, std::size_t len,
23992 const bool strict = true,
23993 const bool allow_exceptions = true,
23994 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23995 {
23996 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23997 }
23998
23999
24000 JSON_HEDLEY_WARN_UNUSED_RESULT
24001 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24002 static basic_json from_cbor(detail::span_input_adapter&& i,
24003 const bool strict = true,
24004 const bool allow_exceptions = true,
24005 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24006 {
24007 basic_json result;
24008 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24009 auto ia = i.get();
24010 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
24011 return res ? result : basic_json(value_t::discarded);
1596624012 }
1596724013
1596824014 /*!
1599924045 array 32 | array | 0xDD
1600024046 map 16 | object | 0xDE
1600124047 map 32 | object | 0xDF
24048 bin 8 | binary | 0xC4
24049 bin 16 | binary | 0xC5
24050 bin 32 | binary | 0xC6
24051 ext 8 | binary | 0xC7
24052 ext 16 | binary | 0xC8
24053 ext 32 | binary | 0xC9
24054 fixext 1 | binary | 0xD4
24055 fixext 2 | binary | 0xD5
24056 fixext 4 | binary | 0xD6
24057 fixext 8 | binary | 0xD7
24058 fixext 16 | binary | 0xD8
1600224059 negative fixint | number_integer | 0xE0-0xFF
16003
16004 @warning The mapping is **incomplete** in the sense that not all
16005 MessagePack types can be converted to a JSON value. The following
16006 MessagePack types are not supported and will yield parse errors:
16007 - bin 8 - bin 32 (0xC4..0xC6)
16008 - ext 8 - ext 32 (0xC7..0xC9)
16009 - fixext 1 - fixext 16 (0xD4..0xD8)
1601024060
1601124061 @note Any MessagePack output created @ref to_msgpack can be successfully
1601224062 parsed by @ref from_msgpack.
1601524065 adapter
1601624066 @param[in] strict whether to expect the input to be consumed until EOF
1601724067 (true by default)
24068 @param[in] allow_exceptions whether to throw exceptions in case of a
24069 parse error (optional, true by default)
24070
24071 @return deserialized JSON value; in case of a parse error and
24072 @a allow_exceptions set to `false`, the return value will be
24073 value_t::discarded.
1601824074
1601924075 @throw parse_error.110 if the given input ends prematurely or the end of
1602024076 file was not reached when @a strict was set to true
1602924085
1603024086 @sa http://msgpack.org
1603124087 @sa @ref to_msgpack(const basic_json&) for the analogous serialization
16032 @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
16033 format
16034 @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
16035 UBJSON format
24088 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24089 related CBOR format
24090 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
24091 the related UBJSON format
24092 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24093 the related BSON format
1603624094
1603724095 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
1603824096 consume input adapters, removed start_index parameter, and added
16039 @a strict parameter since 3.0.0
16040 */
16041 static basic_json from_msgpack(detail::input_adapter i, const bool strict = true)
16042 {
16043 return binary_reader(i).parse_msgpack(strict);
16044 }
16045
16046 /*!
16047 @copydoc from_msgpack(detail::input_adapter, const bool)
16048 */
16049 template <typename A1, typename A2, detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
16050 static basic_json from_msgpack(A1&& a1, A2&& a2, const bool strict = true)
16051 {
16052 return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
16053 }
24097 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
24098 since 3.2.0
24099 */
24100 template<typename InputType>
24101 JSON_HEDLEY_WARN_UNUSED_RESULT
24102 static basic_json from_msgpack(InputType&& i,
24103 const bool strict = true,
24104 const bool allow_exceptions = true)
24105 {
24106 basic_json result;
24107 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24108 auto ia = detail::input_adapter(std::forward<InputType>(i));
24109 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24110 return res ? result : basic_json(value_t::discarded);
24111 }
24112
24113 /*!
24114 @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
24115 */
24116 template<typename IteratorType>
24117 JSON_HEDLEY_WARN_UNUSED_RESULT
24118 static basic_json from_msgpack(IteratorType first, IteratorType last,
24119 const bool strict = true,
24120 const bool allow_exceptions = true)
24121 {
24122 basic_json result;
24123 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24124 auto ia = detail::input_adapter(std::move(first), std::move(last));
24125 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24126 return res ? result : basic_json(value_t::discarded);
24127 }
24128
24129
24130 template<typename T>
24131 JSON_HEDLEY_WARN_UNUSED_RESULT
24132 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24133 static basic_json from_msgpack(const T* ptr, std::size_t len,
24134 const bool strict = true,
24135 const bool allow_exceptions = true)
24136 {
24137 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24138 }
24139
24140 JSON_HEDLEY_WARN_UNUSED_RESULT
24141 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24142 static basic_json from_msgpack(detail::span_input_adapter&& i,
24143 const bool strict = true,
24144 const bool allow_exceptions = true)
24145 {
24146 basic_json result;
24147 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24148 auto ia = i.get();
24149 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24150 return res ? result : basic_json(value_t::discarded);
24151 }
24152
1605424153
1605524154 /*!
1605624155 @brief create a JSON value from an input in UBJSON format
1607324172 int16 | number_integer | `I`
1607424173 int32 | number_integer | `l`
1607524174 int64 | number_integer | `L`
24175 high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H'
1607624176 string | string | `S`
1607724177 char | string | `C`
1607824178 array | array (optimized values are supported) | `[`
1608424184 @param[in] i an input in UBJSON format convertible to an input adapter
1608524185 @param[in] strict whether to expect the input to be consumed until EOF
1608624186 (true by default)
24187 @param[in] allow_exceptions whether to throw exceptions in case of a
24188 parse error (optional, true by default)
24189
24190 @return deserialized JSON value; in case of a parse error and
24191 @a allow_exceptions set to `false`, the return value will be
24192 value_t::discarded.
1608724193
1608824194 @throw parse_error.110 if the given input ends prematurely or the end of
1608924195 file was not reached when @a strict was set to true
1609824204 @sa http://ubjson.org
1609924205 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
1610024206 analogous serialization
16101 @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
16102 format
16103 @sa @ref from_msgpack(detail::input_adapter, const bool) for the related
16104 MessagePack format
16105
16106 @since version 3.1.0
16107 */
16108 static basic_json from_ubjson(detail::input_adapter i, const bool strict = true)
16109 {
16110 return binary_reader(i).parse_ubjson(strict);
16111 }
16112
16113 template <typename A1, typename A2, detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
16114 static basic_json from_ubjson(A1&& a1, A2&& a2, const bool strict = true)
16115 {
16116 return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict);
16117 }
16118
24207 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24208 related CBOR format
24209 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24210 the related MessagePack format
24211 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24212 the related BSON format
24213
24214 @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
24215 */
24216 template<typename InputType>
24217 JSON_HEDLEY_WARN_UNUSED_RESULT
24218 static basic_json from_ubjson(InputType&& i,
24219 const bool strict = true,
24220 const bool allow_exceptions = true)
24221 {
24222 basic_json result;
24223 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24224 auto ia = detail::input_adapter(std::forward<InputType>(i));
24225 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24226 return res ? result : basic_json(value_t::discarded);
24227 }
24228
24229 /*!
24230 @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
24231 */
24232 template<typename IteratorType>
24233 JSON_HEDLEY_WARN_UNUSED_RESULT
24234 static basic_json from_ubjson(IteratorType first, IteratorType last,
24235 const bool strict = true,
24236 const bool allow_exceptions = true)
24237 {
24238 basic_json result;
24239 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24240 auto ia = detail::input_adapter(std::move(first), std::move(last));
24241 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24242 return res ? result : basic_json(value_t::discarded);
24243 }
24244
24245 template<typename T>
24246 JSON_HEDLEY_WARN_UNUSED_RESULT
24247 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24248 static basic_json from_ubjson(const T* ptr, std::size_t len,
24249 const bool strict = true,
24250 const bool allow_exceptions = true)
24251 {
24252 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24253 }
24254
24255 JSON_HEDLEY_WARN_UNUSED_RESULT
24256 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24257 static basic_json from_ubjson(detail::span_input_adapter&& i,
24258 const bool strict = true,
24259 const bool allow_exceptions = true)
24260 {
24261 basic_json result;
24262 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24263 auto ia = i.get();
24264 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24265 return res ? result : basic_json(value_t::discarded);
24266 }
24267
24268
24269 /*!
24270 @brief Create a JSON value from an input in BSON format
24271
24272 Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
24273 serialization format.
24274
24275 The library maps BSON record types to JSON value types as follows:
24276
24277 BSON type | BSON marker byte | JSON value type
24278 --------------- | ---------------- | ---------------------------
24279 double | 0x01 | number_float
24280 string | 0x02 | string
24281 document | 0x03 | object
24282 array | 0x04 | array
24283 binary | 0x05 | still unsupported
24284 undefined | 0x06 | still unsupported
24285 ObjectId | 0x07 | still unsupported
24286 boolean | 0x08 | boolean
24287 UTC Date-Time | 0x09 | still unsupported
24288 null | 0x0A | null
24289 Regular Expr. | 0x0B | still unsupported
24290 DB Pointer | 0x0C | still unsupported
24291 JavaScript Code | 0x0D | still unsupported
24292 Symbol | 0x0E | still unsupported
24293 JavaScript Code | 0x0F | still unsupported
24294 int32 | 0x10 | number_integer
24295 Timestamp | 0x11 | still unsupported
24296 128-bit decimal float | 0x13 | still unsupported
24297 Max Key | 0x7F | still unsupported
24298 Min Key | 0xFF | still unsupported
24299
24300 @warning The mapping is **incomplete**. The unsupported mappings
24301 are indicated in the table above.
24302
24303 @param[in] i an input in BSON format convertible to an input adapter
24304 @param[in] strict whether to expect the input to be consumed until EOF
24305 (true by default)
24306 @param[in] allow_exceptions whether to throw exceptions in case of a
24307 parse error (optional, true by default)
24308
24309 @return deserialized JSON value; in case of a parse error and
24310 @a allow_exceptions set to `false`, the return value will be
24311 value_t::discarded.
24312
24313 @throw parse_error.114 if an unsupported BSON record type is encountered
24314
24315 @complexity Linear in the size of the input @a i.
24316
24317 @liveexample{The example shows the deserialization of a byte vector in
24318 BSON format to a JSON value.,from_bson}
24319
24320 @sa http://bsonspec.org/spec.html
24321 @sa @ref to_bson(const basic_json&) for the analogous serialization
24322 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24323 related CBOR format
24324 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24325 the related MessagePack format
24326 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
24327 related UBJSON format
24328 */
24329 template<typename InputType>
24330 JSON_HEDLEY_WARN_UNUSED_RESULT
24331 static basic_json from_bson(InputType&& i,
24332 const bool strict = true,
24333 const bool allow_exceptions = true)
24334 {
24335 basic_json result;
24336 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24337 auto ia = detail::input_adapter(std::forward<InputType>(i));
24338 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24339 return res ? result : basic_json(value_t::discarded);
24340 }
24341
24342 /*!
24343 @copydoc from_bson(detail::input_adapter&&, const bool, const bool)
24344 */
24345 template<typename IteratorType>
24346 JSON_HEDLEY_WARN_UNUSED_RESULT
24347 static basic_json from_bson(IteratorType first, IteratorType last,
24348 const bool strict = true,
24349 const bool allow_exceptions = true)
24350 {
24351 basic_json result;
24352 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24353 auto ia = detail::input_adapter(std::move(first), std::move(last));
24354 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24355 return res ? result : basic_json(value_t::discarded);
24356 }
24357
24358 template<typename T>
24359 JSON_HEDLEY_WARN_UNUSED_RESULT
24360 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24361 static basic_json from_bson(const T* ptr, std::size_t len,
24362 const bool strict = true,
24363 const bool allow_exceptions = true)
24364 {
24365 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24366 }
24367
24368 JSON_HEDLEY_WARN_UNUSED_RESULT
24369 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24370 static basic_json from_bson(detail::span_input_adapter&& i,
24371 const bool strict = true,
24372 const bool allow_exceptions = true)
24373 {
24374 basic_json result;
24375 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24376 auto ia = i.get();
24377 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24378 return res ? result : basic_json(value_t::discarded);
24379 }
1611924380 /// @}
1612024381
1612124382 //////////////////////////
1616824429
1616924430 Uses a JSON pointer to retrieve a reference to the respective JSON value.
1617024431 No bound checking is performed. The function does not change the JSON
16171 value; no `null` values are created. In particular, the the special value
24432 value; no `null` values are created. In particular, the special value
1617224433 `-` yields an exception.
1617324434
1617424435 @param[in] ptr JSON pointer to the desired element
1640324664 basic_json result = *this;
1640424665
1640524666 // the valid JSON Patch operations
16406 enum class patch_operations
16407 {
16408 add,
16409 remove,
16410 replace,
16411 move,
16412 copy,
16413 test,
16414 invalid
16415 };
16416
16417 const auto get_op = [](const std::string& op) {
24667 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24668
24669 const auto get_op = [](const std::string & op)
24670 {
1641824671 if (op == "add")
1641924672 {
1642024673 return patch_operations::add;
1644424697 };
1644524698
1644624699 // wrapper for "add" operation; add value at ptr
16447 const auto operation_add = [&result](json_pointer& ptr, basic_json val) {
24700 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24701 {
1644824702 // adding to the root of the target document means replacing it
16449 if (ptr.is_root())
24703 if (ptr.empty())
1645024704 {
1645124705 result = val;
16452 }
16453 else
16454 {
16455 // make sure the top element of the pointer exists
16456 json_pointer top_pointer = ptr.top();
16457 if (top_pointer != ptr)
24706 return;
24707 }
24708
24709 // make sure the top element of the pointer exists
24710 json_pointer top_pointer = ptr.top();
24711 if (top_pointer != ptr)
24712 {
24713 result.at(top_pointer);
24714 }
24715
24716 // get reference to parent of JSON pointer ptr
24717 const auto last_path = ptr.back();
24718 ptr.pop_back();
24719 basic_json& parent = result[ptr];
24720
24721 switch (parent.m_type)
24722 {
24723 case value_t::null:
24724 case value_t::object:
1645824725 {
16459 result.at(top_pointer);
24726 // use operator[] to add value
24727 parent[last_path] = val;
24728 break;
1646024729 }
1646124730
16462 // get reference to parent of JSON pointer ptr
16463 const auto last_path = ptr.pop_back();
16464 basic_json& parent = result[ptr];
16465
16466 switch (parent.m_type)
24731 case value_t::array:
1646724732 {
16468 case value_t::null:
16469 case value_t::object:
24733 if (last_path == "-")
1647024734 {
16471 // use operator[] to add value
16472 parent[last_path] = val;
16473 break;
24735 // special case: append to back
24736 parent.push_back(val);
1647424737 }
16475
16476 case value_t::array:
24738 else
1647724739 {
16478 if (last_path == "-")
24740 const auto idx = json_pointer::array_index(last_path);
24741 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
1647924742 {
16480 // special case: append to back
16481 parent.push_back(val);
24743 // avoid undefined behavior
24744 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
1648224745 }
16483 else
16484 {
16485 const auto idx = json_pointer::array_index(last_path);
16486 if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
16487 {
16488 // avoid undefined behavior
16489 JSON_THROW(out_of_range::create(401, "array index " + cpt::to_string(idx) + " is out of range"));
16490 }
16491 else
16492 {
16493 // default case: insert add offset
16494 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
16495 }
16496 }
16497 break;
24746
24747 // default case: insert add offset
24748 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
1649824749 }
16499
16500 default:
16501 {
16502 // if there exists a parent it cannot be primitive
16503 assert(false); // LCOV_EXCL_LINE
16504 }
24750 break;
1650524751 }
24752
24753 // if there exists a parent it cannot be primitive
24754 default: // LCOV_EXCL_LINE
24755 JSON_ASSERT(false); // LCOV_EXCL_LINE
1650624756 }
1650724757 };
1650824758
1650924759 // wrapper for "remove" operation; remove value at ptr
16510 const auto operation_remove = [&result](json_pointer& ptr) {
24760 const auto operation_remove = [&result](json_pointer & ptr)
24761 {
1651124762 // get reference to parent of JSON pointer ptr
16512 const auto last_path = ptr.pop_back();
24763 const auto last_path = ptr.back();
24764 ptr.pop_back();
1651324765 basic_json& parent = result.at(ptr);
1651424766
1651524767 // remove child
1651724769 {
1651824770 // perform range check
1651924771 auto it = parent.find(last_path);
16520 if (JSON_LIKELY(it != parent.end()))
24772 if (JSON_HEDLEY_LIKELY(it != parent.end()))
1652124773 {
1652224774 parent.erase(it);
1652324775 }
1652924781 else if (parent.is_array())
1653024782 {
1653124783 // note erase performs range check
16532 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
24784 parent.erase(json_pointer::array_index(last_path));
1653324785 }
1653424786 };
1653524787
1653624788 // type check: top level value must be an array
16537 if (JSON_UNLIKELY(not json_patch.is_array()))
24789 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
1653824790 {
1653924791 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
1654024792 }
1654324795 for (const auto& val : json_patch)
1654424796 {
1654524797 // wrapper to get a value for an operation
16546 const auto get_value = [&val](const std::string& op, const std::string& member, bool string_type) -> basic_json& {
24798 const auto get_value = [&val](const std::string & op,
24799 const std::string & member,
24800 bool string_type) -> basic_json &
24801 {
1654724802 // find value
1654824803 auto it = val.m_value.object->find(member);
1654924804
1655124806 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
1655224807
1655324808 // check if desired value is present
16554 if (JSON_UNLIKELY(it == val.m_value.object->end()))
24809 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
1655524810 {
1655624811 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
1655724812 }
1655824813
1655924814 // check if result is of type string
16560 if (JSON_UNLIKELY(string_type and not it->second.is_string()))
24815 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
1656124816 {
1656224817 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
1656324818 }
1656724822 };
1656824823
1656924824 // type check: every element of the array must be an object
16570 if (JSON_UNLIKELY(not val.is_object()))
24825 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
1657124826 {
1657224827 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
1657324828 }
1657424829
1657524830 // collect mandatory members
16576 const std::string op = get_value("op", "op", true);
16577 const std::string path = get_value(op, "path", true);
24831 const auto op = get_value("op", "op", true).template get<std::string>();
24832 const auto path = get_value(op, "path", true).template get<std::string>();
1657824833 json_pointer ptr(path);
1657924834
1658024835 switch (get_op(op))
1660024855
1660124856 case patch_operations::move:
1660224857 {
16603 const std::string from_path = get_value("move", "from", true);
24858 const auto from_path = get_value("move", "from", true).template get<std::string>();
1660424859 json_pointer from_ptr(from_path);
1660524860
1660624861 // the "from" location must exist - use at()
1661724872
1661824873 case patch_operations::copy:
1661924874 {
16620 const std::string from_path = get_value("copy", "from", true);
24875 const auto from_path = get_value("copy", "from", true).template get<std::string>();
1662124876 const json_pointer from_ptr(from_path);
1662224877
1662324878 // the "from" location must exist - use at()
1663924894 // the "path" location must exist - use at()
1664024895 success = (result.at(ptr) == get_value("test", "value", false));
1664124896 }
16642 JSON_CATCH(out_of_range&)
24897 JSON_INTERNAL_CATCH (out_of_range&)
1664324898 {
1664424899 // ignore out of range errors: success remains false
1664524900 }
1664624901
1664724902 // throw an exception if test fails
16648 if (JSON_UNLIKELY(not success))
24903 if (JSON_HEDLEY_UNLIKELY(!success))
1664924904 {
1665024905 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
1665124906 }
1665324908 break;
1665424909 }
1665524910
16656 case patch_operations::invalid:
24911 default:
1665724912 {
1665824913 // op must be "add", "remove", "replace", "move", "copy", or
1665924914 // "test"
1669824953
1669924954 @since version 2.0.0
1670024955 */
16701 static basic_json diff(const basic_json& source, const basic_json& target, const std::string& path = "")
24956 JSON_HEDLEY_WARN_UNUSED_RESULT
24957 static basic_json diff(const basic_json& source, const basic_json& target,
24958 const std::string& path = "")
1670224959 {
1670324960 // the patch
1670424961 basic_json result(value_t::array);
1671224969 if (source.type() != target.type())
1671324970 {
1671424971 // different types: replace value
16715 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
16716 }
16717 else
16718 {
16719 switch (source.type())
16720 {
16721 case value_t::array:
24972 result.push_back(
24973 {
24974 {"op", "replace"}, {"path", path}, {"value", target}
24975 });
24976 return result;
24977 }
24978
24979 switch (source.type())
24980 {
24981 case value_t::array:
24982 {
24983 // first pass: traverse common elements
24984 std::size_t i = 0;
24985 while (i < source.size() && i < target.size())
1672224986 {
16723 // first pass: traverse common elements
16724 std::size_t i = 0;
16725 while (i < source.size() and i < target.size())
24987 // recursive call to compare array values at index i
24988 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
24989 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24990 ++i;
24991 }
24992
24993 // i now reached the end of at least one array
24994 // in a second pass, traverse the remaining elements
24995
24996 // remove my remaining elements
24997 const auto end_index = static_cast<difference_type>(result.size());
24998 while (i < source.size())
24999 {
25000 // add operations in reverse order to avoid invalid
25001 // indices
25002 result.insert(result.begin() + end_index, object(
1672625003 {
16727 // recursive call to compare array values at index i
16728 auto temp_diff = diff(source[i], target[i], path + "/" + cpt::to_string(i));
25004 {"op", "remove"},
25005 {"path", path + "/" + std::to_string(i)}
25006 }));
25007 ++i;
25008 }
25009
25010 // add other remaining elements
25011 while (i < target.size())
25012 {
25013 result.push_back(
25014 {
25015 {"op", "add"},
25016 {"path", path + "/-"},
25017 {"value", target[i]}
25018 });
25019 ++i;
25020 }
25021
25022 break;
25023 }
25024
25025 case value_t::object:
25026 {
25027 // first pass: traverse this object's elements
25028 for (auto it = source.cbegin(); it != source.cend(); ++it)
25029 {
25030 // escape the key name to be used in a JSON patch
25031 const auto key = json_pointer::escape(it.key());
25032
25033 if (target.find(it.key()) != target.end())
25034 {
25035 // recursive call to compare object values at key it
25036 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
1672925037 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
16730 ++i;
1673125038 }
16732
16733 // i now reached the end of at least one array
16734 // in a second pass, traverse the remaining elements
16735
16736 // remove my remaining elements
16737 const auto end_index = static_cast<difference_type>(result.size());
16738 while (i < source.size())
25039 else
1673925040 {
16740 // add operations in reverse order to avoid invalid
16741 // indices
16742 result.insert(result.begin() + end_index, object({{"op", "remove"}, {"path", path + "/" + cpt::to_string(i)}}));
16743 ++i;
25041 // found a key that is not in o -> remove it
25042 result.push_back(object(
25043 {
25044 {"op", "remove"}, {"path", path + "/" + key}
25045 }));
1674425046 }
16745
16746 // add other remaining elements
16747 while (i < target.size())
25047 }
25048
25049 // second pass: traverse other object's elements
25050 for (auto it = target.cbegin(); it != target.cend(); ++it)
25051 {
25052 if (source.find(it.key()) == source.end())
1674825053 {
16749 result.push_back({{"op", "add"}, {"path", path + "/" + cpt::to_string(i)}, {"value", target[i]}});
16750 ++i;
25054 // found a key that is not in this -> add it
25055 const auto key = json_pointer::escape(it.key());
25056 result.push_back(
25057 {
25058 {"op", "add"}, {"path", path + "/" + key},
25059 {"value", it.value()}
25060 });
1675125061 }
16752
16753 break;
1675425062 }
1675525063
16756 case value_t::object:
25064 break;
25065 }
25066
25067 default:
25068 {
25069 // both primitive type: replace value
25070 result.push_back(
1675725071 {
16758 // first pass: traverse this object's elements
16759 for (auto it = source.cbegin(); it != source.cend(); ++it)
16760 {
16761 // escape the key name to be used in a JSON patch
16762 const auto key = json_pointer::escape(it.key());
16763
16764 if (target.find(it.key()) != target.end())
16765 {
16766 // recursive call to compare object values at key it
16767 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
16768 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
16769 }
16770 else
16771 {
16772 // found a key that is not in o -> remove it
16773 result.push_back(object({{"op", "remove"}, {"path", path + "/" + key}}));
16774 }
16775 }
16776
16777 // second pass: traverse other object's elements
16778 for (auto it = target.cbegin(); it != target.cend(); ++it)
16779 {
16780 if (source.find(it.key()) == source.end())
16781 {
16782 // found a key that is not in this -> add it
16783 const auto key = json_pointer::escape(it.key());
16784 result.push_back({{"op", "add"}, {"path", path + "/" + key}, {"value", it.value()}});
16785 }
16786 }
16787
16788 break;
16789 }
16790
16791 default:
16792 {
16793 // both primitive type: replace value
16794 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
16795 break;
16796 }
25072 {"op", "replace"}, {"path", path}, {"value", target}
25073 });
25074 break;
1679725075 }
1679825076 }
1679925077
1683925117 Thereby, `Target` is the current object; that is, the patch is applied to
1684025118 the current value.
1684125119
16842 @param[in] patch the patch to apply
25120 @param[in] apply_patch the patch to apply
1684325121
1684425122 @complexity Linear in the lengths of @a patch.
1684525123
1685125129
1685225130 @since version 3.0.0
1685325131 */
16854 void merge_patch(const basic_json& patch)
16855 {
16856 if (patch.is_object())
16857 {
16858 if (not is_object())
25132 void merge_patch(const basic_json& apply_patch)
25133 {
25134 if (apply_patch.is_object())
25135 {
25136 if (!is_object())
1685925137 {
1686025138 *this = object();
1686125139 }
16862 for (auto it = patch.begin(); it != patch.end(); ++it)
25140 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
1686325141 {
1686425142 if (it.value().is_null())
1686525143 {
1687325151 }
1687425152 else
1687525153 {
16876 *this = patch;
25154 *this = apply_patch;
1687725155 }
1687825156 }
1687925157
1688025158 /// @}
1688125159 };
25160
25161 /*!
25162 @brief user-defined to_string function for JSON values
25163
25164 This function implements a user-defined to_string for JSON objects.
25165
25166 @param[in] j a JSON object
25167 @return a std::string object
25168 */
25169
25170 NLOHMANN_BASIC_JSON_TPL_DECLARATION
25171 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25172 {
25173 return j.dump();
25174 }
1688225175 } // namespace nlohmann
1688325176
1688425177 ///////////////////////
1688825181 // specialization of std::swap, and std::hash
1688925182 namespace std
1689025183 {
25184
25185 /// hash value for JSON objects
25186 template<>
25187 struct hash<nlohmann::json>
25188 {
25189 /*!
25190 @brief return a hash value for a JSON object
25191
25192 @since version 1.0.0
25193 */
25194 std::size_t operator()(const nlohmann::json& j) const
25195 {
25196 return nlohmann::detail::hash(j);
25197 }
25198 };
25199
25200 /// specialization for std::less<value_t>
25201 /// @note: do not remove the space after '<',
25202 /// see https://github.com/nlohmann/json/pull/679
25203 template<>
25204 struct less<::nlohmann::detail::value_t>
25205 {
25206 /*!
25207 @brief compare two value_t enum values
25208 @since version 3.0.0
25209 */
25210 bool operator()(nlohmann::detail::value_t lhs,
25211 nlohmann::detail::value_t rhs) const noexcept
25212 {
25213 return nlohmann::detail::operator<(lhs, rhs);
25214 }
25215 };
25216
25217 // C++20 prohibit function specialization in the std namespace.
25218 #ifndef JSON_HAS_CPP_20
25219
1689125220 /*!
1689225221 @brief exchanges the values of two JSON objects
1689325222
1689425223 @since version 1.0.0
1689525224 */
16896 template <>
16897 inline void swap(nlohmann::json& j1,
16898 nlohmann::json& j2) noexcept(is_nothrow_move_constructible<nlohmann::json>::value and is_nothrow_move_assignable<nlohmann::json>::value)
25225 template<>
25226 inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
25227 is_nothrow_move_constructible<nlohmann::json>::value&&
25228 is_nothrow_move_assignable<nlohmann::json>::value
25229 )
1689925230 {
1690025231 j1.swap(j2);
1690125232 }
1690225233
16903 /// hash value for JSON objects
16904 template <>
16905 struct hash<nlohmann::json>
16906 {
16907 /*!
16908 @brief return a hash value for a JSON object
16909
16910 @since version 1.0.0
16911 */
16912 std::size_t operator()(const nlohmann::json& j) const
16913 {
16914 // a naive hashing via the string representation
16915 const auto& h = hash<nlohmann::json::string_t>();
16916 return h(j.dump());
16917 }
16918 };
16919
16920 /// specialization for std::less<value_t>
16921 /// @note: do not remove the space after '<',
16922 /// see https://github.com/nlohmann/json/pull/679
16923 template <>
16924 struct less<::nlohmann::detail::value_t>
16925 {
16926 /*!
16927 @brief compare two value_t enum values
16928 @since version 3.0.0
16929 */
16930 bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
16931 {
16932 return nlohmann::detail::operator<(lhs, rhs);
16933 }
16934 };
25234 #endif
1693525235
1693625236 } // namespace std
1693725237
1694825248
1694925249 @since version 1.0.0
1695025250 */
16951 inline nlohmann::json operator"" _json(const char* s, std::size_t n)
25251 JSON_HEDLEY_NON_NULL(1)
25252 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
1695225253 {
1695325254 return nlohmann::json::parse(s, s + n);
1695425255 }
1696625267
1696725268 @since version 2.0.0
1696825269 */
16969 inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
25270 JSON_HEDLEY_NON_NULL(1)
25271 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
1697025272 {
1697125273 return nlohmann::json::json_pointer(std::string(s, n));
1697225274 }
1697625278
1697725279 // restore GCC/clang diagnostic settings
1697825280 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
16979 #pragma GCC diagnostic pop
25281 #pragma GCC diagnostic pop
1698025282 #endif
1698125283 #if defined(__clang__)
16982 #pragma GCC diagnostic pop
25284 #pragma GCC diagnostic pop
1698325285 #endif
1698425286
1698525287 // clean up
25288 #undef JSON_ASSERT
25289 #undef JSON_INTERNAL_CATCH
1698625290 #undef JSON_CATCH
1698725291 #undef JSON_THROW
1698825292 #undef JSON_TRY
16989 #undef JSON_LIKELY
16990 #undef JSON_UNLIKELY
16991 #undef JSON_DEPRECATED
1699225293 #undef JSON_HAS_CPP_14
1699325294 #undef JSON_HAS_CPP_17
1699425295 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
1699525296 #undef NLOHMANN_BASIC_JSON_TPL
16996 #undef NLOHMANN_JSON_HAS_HELPER
16997
16998
16999 #endif
25297 #undef JSON_EXPLICIT
25298
25299 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25300 #undef JSON_HEDLEY_ALWAYS_INLINE
25301 #undef JSON_HEDLEY_ARM_VERSION
25302 #undef JSON_HEDLEY_ARM_VERSION_CHECK
25303 #undef JSON_HEDLEY_ARRAY_PARAM
25304 #undef JSON_HEDLEY_ASSUME
25305 #undef JSON_HEDLEY_BEGIN_C_DECLS
25306 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25307 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25308 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25309 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25310 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25311 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
25312 #undef JSON_HEDLEY_CLANG_HAS_WARNING
25313 #undef JSON_HEDLEY_COMPCERT_VERSION
25314 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25315 #undef JSON_HEDLEY_CONCAT
25316 #undef JSON_HEDLEY_CONCAT3
25317 #undef JSON_HEDLEY_CONCAT3_EX
25318 #undef JSON_HEDLEY_CONCAT_EX
25319 #undef JSON_HEDLEY_CONST
25320 #undef JSON_HEDLEY_CONSTEXPR
25321 #undef JSON_HEDLEY_CONST_CAST
25322 #undef JSON_HEDLEY_CPP_CAST
25323 #undef JSON_HEDLEY_CRAY_VERSION
25324 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
25325 #undef JSON_HEDLEY_C_DECL
25326 #undef JSON_HEDLEY_DEPRECATED
25327 #undef JSON_HEDLEY_DEPRECATED_FOR
25328 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25329 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25330 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25331 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25332 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25333 #undef JSON_HEDLEY_DIAGNOSTIC_POP
25334 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25335 #undef JSON_HEDLEY_DMC_VERSION
25336 #undef JSON_HEDLEY_DMC_VERSION_CHECK
25337 #undef JSON_HEDLEY_EMPTY_BASES
25338 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25339 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25340 #undef JSON_HEDLEY_END_C_DECLS
25341 #undef JSON_HEDLEY_FLAGS
25342 #undef JSON_HEDLEY_FLAGS_CAST
25343 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25344 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
25345 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25346 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25347 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
25348 #undef JSON_HEDLEY_GCC_HAS_FEATURE
25349 #undef JSON_HEDLEY_GCC_HAS_WARNING
25350 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25351 #undef JSON_HEDLEY_GCC_VERSION
25352 #undef JSON_HEDLEY_GCC_VERSION_CHECK
25353 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25354 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25355 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25356 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25357 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25358 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
25359 #undef JSON_HEDLEY_GNUC_HAS_WARNING
25360 #undef JSON_HEDLEY_GNUC_VERSION
25361 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
25362 #undef JSON_HEDLEY_HAS_ATTRIBUTE
25363 #undef JSON_HEDLEY_HAS_BUILTIN
25364 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25365 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25366 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25367 #undef JSON_HEDLEY_HAS_EXTENSION
25368 #undef JSON_HEDLEY_HAS_FEATURE
25369 #undef JSON_HEDLEY_HAS_WARNING
25370 #undef JSON_HEDLEY_IAR_VERSION
25371 #undef JSON_HEDLEY_IAR_VERSION_CHECK
25372 #undef JSON_HEDLEY_IBM_VERSION
25373 #undef JSON_HEDLEY_IBM_VERSION_CHECK
25374 #undef JSON_HEDLEY_IMPORT
25375 #undef JSON_HEDLEY_INLINE
25376 #undef JSON_HEDLEY_INTEL_VERSION
25377 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
25378 #undef JSON_HEDLEY_IS_CONSTANT
25379 #undef JSON_HEDLEY_IS_CONSTEXPR_
25380 #undef JSON_HEDLEY_LIKELY
25381 #undef JSON_HEDLEY_MALLOC
25382 #undef JSON_HEDLEY_MESSAGE
25383 #undef JSON_HEDLEY_MSVC_VERSION
25384 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
25385 #undef JSON_HEDLEY_NEVER_INLINE
25386 #undef JSON_HEDLEY_NON_NULL
25387 #undef JSON_HEDLEY_NO_ESCAPE
25388 #undef JSON_HEDLEY_NO_RETURN
25389 #undef JSON_HEDLEY_NO_THROW
25390 #undef JSON_HEDLEY_NULL
25391 #undef JSON_HEDLEY_PELLES_VERSION
25392 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
25393 #undef JSON_HEDLEY_PGI_VERSION
25394 #undef JSON_HEDLEY_PGI_VERSION_CHECK
25395 #undef JSON_HEDLEY_PREDICT
25396 #undef JSON_HEDLEY_PRINTF_FORMAT
25397 #undef JSON_HEDLEY_PRIVATE
25398 #undef JSON_HEDLEY_PUBLIC
25399 #undef JSON_HEDLEY_PURE
25400 #undef JSON_HEDLEY_REINTERPRET_CAST
25401 #undef JSON_HEDLEY_REQUIRE
25402 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25403 #undef JSON_HEDLEY_REQUIRE_MSG
25404 #undef JSON_HEDLEY_RESTRICT
25405 #undef JSON_HEDLEY_RETURNS_NON_NULL
25406 #undef JSON_HEDLEY_SENTINEL
25407 #undef JSON_HEDLEY_STATIC_ASSERT
25408 #undef JSON_HEDLEY_STATIC_CAST
25409 #undef JSON_HEDLEY_STRINGIFY
25410 #undef JSON_HEDLEY_STRINGIFY_EX
25411 #undef JSON_HEDLEY_SUNPRO_VERSION
25412 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25413 #undef JSON_HEDLEY_TINYC_VERSION
25414 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
25415 #undef JSON_HEDLEY_TI_ARMCL_VERSION
25416 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25417 #undef JSON_HEDLEY_TI_CL2000_VERSION
25418 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25419 #undef JSON_HEDLEY_TI_CL430_VERSION
25420 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25421 #undef JSON_HEDLEY_TI_CL6X_VERSION
25422 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25423 #undef JSON_HEDLEY_TI_CL7X_VERSION
25424 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25425 #undef JSON_HEDLEY_TI_CLPRU_VERSION
25426 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25427 #undef JSON_HEDLEY_TI_VERSION
25428 #undef JSON_HEDLEY_TI_VERSION_CHECK
25429 #undef JSON_HEDLEY_UNAVAILABLE
25430 #undef JSON_HEDLEY_UNLIKELY
25431 #undef JSON_HEDLEY_UNPREDICTABLE
25432 #undef JSON_HEDLEY_UNREACHABLE
25433 #undef JSON_HEDLEY_UNREACHABLE_RETURN
25434 #undef JSON_HEDLEY_VERSION
25435 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25436 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
25437 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
25438 #undef JSON_HEDLEY_VERSION_ENCODE
25439 #undef JSON_HEDLEY_WARNING
25440 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
25441 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25442 #undef JSON_HEDLEY_FALL_THROUGH
25443
25444
25445
25446 #endif // INCLUDE_NLOHMANN_JSON_HPP_
3939
4040 uint16_t getVolume()
4141 {
42 return get("volume", 100);
42 return get("volume", static_cast<uint16_t>(100));
4343 }
4444
4545 bool isMuted()
5757 msg["muted"] = muted;
5858 }
5959 };
60 }
60 } // namespace msg
6161
6262
6363 #endif
105105 return id;
106106 }
107107 };
108 }
108 } // namespace msg
109109
110110
111111 #endif
123123 {
124124 }
125125
126 BaseMessage(message_type type_) : type(type_), id(0), refersTo(0)
126 BaseMessage(message_type type_) : type(static_cast<uint16_t>(type_)), id(0), refersTo(0)
127127 {
128128 }
129129
4949
5050 uint16_t getVolume()
5151 {
52 return get("volume", 100);
52 return get("volume", static_cast<uint16_t>(100));
5353 }
5454
5555 bool isMuted()
7979 msg["muted"] = muted;
8080 }
8181 };
82 }
82 } // namespace msg
8383
8484
8585 #endif
6666
6767 ~StreamTags() override = default;
6868 };
69 }
69 } // namespace msg
7070
7171
7272 #endif
5252 writeVal(stream, latency.usec);
5353 }
5454 };
55 }
55 } // namespace msg
5656
5757
5858 #endif
110110 return std::strtof(str, endptr);
111111 #endif
112112 }
113 }
113 } // namespace cpt
114114
115115
116116 #endif
6060 // Implementation from http://stackoverflow.com/a/26085827/2510022
6161 inline static int gettimeofday(struct timeval* tp, struct timezone* tzp)
6262 {
63 std::ignore = tzp;
6364 // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
6465 static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
6566
3636
3737 static bool exists(const std::string& filename)
3838 {
39 std::ifstream infile(filename.c_str());
40 return infile.good();
39 if (filename.empty())
40 return false;
41 #ifdef WINDOWS
42 DWORD dwAttrib = GetFileAttributes(filename.c_str());
43 return (dwAttrib != INVALID_FILE_ATTRIBUTES);
44 #else
45 struct stat buffer;
46 return (stat(filename.c_str(), &buffer) == 0);
47 #endif
4148 }
4249
4350 #ifndef WINDOWS
0 snapcast (0.23.0-1) unstable; urgency=medium
1
2 * Features
3 -Client: Add PulseAudio player backend (Issue #722)
4 -Client: Configurable buffer time for alsa and pulse players
5 -Server: If docroot is not configured, a default page is served (Issue #711)
6 -Server: airplay source supports "password" parameter (Issue #754)
7
8 * Bugfixes
9 -Server: airplay source deletes Shairport's meta pipe on exit (Issue #672)
10 -Server: alsa source will not send silece when going idle (Issue #729)
11 -Server: Fix build error on FreeBSD (Issue #752)
12 -Server: pipe source will not send silence after 3h idle (Issue #741)
13 -Client: "make install" will set correct user/group for snapclient (Issue #728)
14 -Client: Fix printing UTF-8 device names on Windows (Issue #732)
15 -Client: Fix stuttering on alsa player backend (Issue #722, #727)
16 -Client: Terminate if host is not configured and mDNS is unavailable
17
18 * General
19 -Server: Change librespot parameter "killall" default to false (Issue #746, #724)
20 -Client: Android uses performance mode "none" to allow effects (Issue #766)
21 -Snapweb: Update to v0.1.0
22 -Build: Update CMakeLists.txt to build Snapclient on Android
23
24 -- Johannes Pohl <snapcast@badaix.de> Sun, 10 Jan 2021 00:13:37 +0200
25
026 snapcast (0.22.0+dfsg1-1) UNRELEASED; urgency=medium
127
228 * New upstream release.
00 Source: snapcast
11 Section: sound
22 Priority: optional
3 Maintainer: Felix Geyer <fgeyer@debian.org>
3 Maintainer: Johannes Pohl <snapcast@badaix.de>
44 Build-Depends: debhelper (>= 10~),
55 libasound2-dev,
6 libpulse-dev,
67 libvorbis-dev,
78 libflac-dev,
89 libavahi-client-dev,
22 Each message sent with the Snapcast binary protocol is split up into two parts:
33 - A base message that provides general information like time sent/received, type of the message, message size, etc
44 - A typed message that carries the rest of the information
5
6 The protocol is using little endian.
57
68 ## Client joining process
79
1517 1. Until the server sends this, the client shouldn't play any [Wire Chunk](#wire-chunk) messages
1618 1. The server will now send [Wire Chunk](#wire-chunk) messages, which can be fed to the audio decoder.
1719 1. When it comes time for the client to disconnect, the socket can just be closed.
20 1. Client periodically sends a [Time](#time) message, carrying a sent timestamp `t_client-sent`
21 1. Receives a Time response containing the client to server time delta `latency_c2s = t_server-recv - t_client-sent + t_network-latency` and the server sent timestamp `t_server-sent`
22 1. Calculates `latency_s2c = t_client-recv - t_server-sent + t_network_latency`
23 1. Calcutates the time diff between server and client as `(latency_c2s - latency_s2c) / 2`, eliminating the network latency (assumed to be symmetric)
1824
1925 ## Messages
2026
5763 | timestamp.sec | int32 | The second value of the timestamp when this part of the stream was recorded |
5864 | timestamp.usec | int32 | The microsecond value of the timestamp when this part of the stream was recorded |
5965 | size | uint32 | Size of the following payload |
60 | payload | char[] | Buffer of data containing the codec header |
66 | payload | char[] | Buffer of data containing the encoded PCM data (a decodable chunk per message) |
6167
6268 ### Server Settings
6369
4242
4343 ```sh
4444 sudo apt-get install build-essential
45 sudo apt-get install libasound2-dev libvorbisidec-dev libvorbis-dev libopus-dev libflac-dev libsoxr-dev alsa-utils libavahi-client-dev avahi-daemon libexpat1-dev
45 sudo apt-get install libasound2-dev libpulse-dev libvorbisidec-dev libvorbis-dev libopus-dev libflac-dev libsoxr-dev alsa-utils libavahi-client-dev avahi-daemon libexpat1-dev
4646 ```
4747
4848 Compilation requires gcc 4.8 or higher, so it's highly recommended to use Debian (Raspbian) Jessie.
3737 Launches librespot and reads audio from stdout
3838
3939 ```sh
40 librespot:///<path/to/librespot>?name=<name>[&dryout_ms=2000][&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&wd_timeout=7800][&volume=100][&onevent=""][&normalize=false][&autoplay=false][&cache=""][&disable_audio_cache=false][&killall=true][&params=extra-params]
40 librespot:///<path/to/librespot>?name=<name>[&dryout_ms=2000][&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&wd_timeout=7800][&volume=100][&onevent=""][&normalize=false][&autoplay=false][&cache=""][&disable_audio_cache=false][&killall=false][&params=extra-params]
4141 ```
4242
4343 Note that you need to have the librespot binary on your machine and the sampleformat will be set to `44100:16:2`
6868 Launches [shairport-sync](https://github.com/mikebrady/shairport-sync) and reads audio from stdout
6969
7070 ```sh
71 airplay:///<path/to/shairport-sync>?name=<name>[&dryout_ms=2000][&devicename=Snapcast][&port=5000]
71 airplay:///<path/to/shairport-sync>?name=<name>[&dryout_ms=2000][&devicename=Snapcast][&port=5000][&password=<my password>]
7272 ```
7373
7474 Note that you need to have the shairport-sync binary on your machine and the sampleformat will be set to `44100:16:2`
7575
7676 #### Available parameters
77
78 Parameters used to configure the shairport-sync binary:
7779
7880 - `devicename`: Advertised name
7981 - `port`: RTSP listening port
82 - `password`: Password
83 - `params`: Optional string appended to the shairport-sync invocation. This allows for arbitrary flags to be passed to shairport-sync, for instance `params=--on-start=start.sh%20--on-stop=stop.sh`. The value has to be properly URL-encoded.
8084
8185 ### file
8286
137141 Captures audio from an alsa device
138142
139143 ```sh
140 alsa://?name=<name>&device=<alsa device>
141 ```
142
143 `device` is an alsa device name or identifier, e.g. `default` or `hw:0,0`
144 alsa://?name=<name>&device=<alsa device>[&send_silence=false][&idle_threshold=100]
145 ```
146
147 #### Available parameters
148
149 - `device`: alsa device name or identifier, e.g. `default` or `hw:0,0` or `hw:0,0,0`
150 - `idle_threshold`: switch stream state from playing to idle after receiving `idle_threshold` milliseconds of silence
151 - `send_silence`: forward silence to clients when stream state is `idle`
144152
145153 The output of any audio player that uses alsa can be redirected to Snapcast by using an alsa loopback device:
146154
220228
221229 ```sh
222230 [stream]
223 stream = alsa://?name=SomeName&sampleformat=48000:16:2&device=hw:0,1,0
231 source = alsa://?name=SomeName&sampleformat=48000:16:2&device=hw:0,1,0
224232 ```
225233
226234 ### meta
1515
1616 ### using apt 1.1 or later
1717
18 sudo apt install </path/to/snapclient_0.x.x_armhf.deb>
18 sudo apt install </path/to/snapclient_0.x.x_[arch].deb>
1919
2020 or
2121
22 sudo apt install </path/to/snapserver_0.x.x_armhf.deb>
22 sudo apt install </path/to/snapserver_0.x.x_[arch].deb>
2323
2424 ### using dpkg
2525
2626 Install the package:
2727
28 sudo dpkg -i snapclient_0.x.x_armhf.deb
28 sudo dpkg -i </path/to/snapclient_0.x.x_[arch].deb>
2929
3030 or
3131
32 sudo dpkg -i snapclient_0.x.x_amd64.deb
32 sudo dpkg -i </path/to/snapserver_0.x.x_[arch].deb>
3333
3434 Install missing dependencies:
3535
9999
100100 The client that sends a "Set" command will receive a Response, while the other connected control clients will receive a Notification "On" event.
101101 Commands can be sent in a [Batch](http://www.jsonrpc.org/specification#batch). The server will reply with a Batch and send a Batch notification to the other clients. This way the volume of multiple Snapclients can be changed with a single Batch Request.
102
103 Each JSON RPC request and response contains an identifier in the `id` field, which can be used to link responses to the request that caused them, as defined in the JSON RPC specification:
104
105 An identifier established by the Client that MUST contain a String, Number, or NULL value if included.
106 If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]
102107
103108 Clients should call `Server.GetStatus` to get the complete picture.
104109
184189 ### Client.SetVolume
185190 #### Request
186191 ```json
187 {"id":8,"jsonrpc":"2.0","method":"Client.SetVolume","params":{"id":"00:21:6a:7d:74:fc","volume":{"muted":false,"percent":74}}}
188 ```
189
190 #### Response
191 ```json
192 {"id":8,"jsonrpc":"2.0","result":{"volume":{"muted":false,"percent":74}}}
192 {"id":"8","jsonrpc":"2.0","method":"Client.SetVolume","params":{"id":"00:21:6a:7d:74:fc","volume":{"muted":false,"percent":74}}}
193 ```
194
195 #### Response
196 ```json
197 {"id":"8","jsonrpc":"2.0","result":{"volume":{"muted":false,"percent":74}}}
193198 ```
194199
195200 #### Notification
384389
385390 ### Client.OnVolumeChanged
386391 ```json
387 {"jsonrpc":"2.0","method":"Client.OnVolumeChanged","params":{"id":"00:21:6a:7d:74:fc","volume":{"muted":false,"percent":74}}}```
392 {"jsonrpc":"2.0","method":"Client.OnVolumeChanged","params":{"id":"00:21:6a:7d:74:fc","volume":{"muted":false,"percent":74}}}
388393 ```
389394
390395 ### Client.OnLatencyChanged
409414
410415 ### Group.OnNameChanged
411416 ```json
412 {"jsonrpc":"2.0","method":"GrClient.OnNameChanged","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","name":"GroundFloor"}}
417 {"jsonrpc":"2.0","method":"Group.OnNameChanged","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","name":"GroundFloor"}}
413418 ```
414419
415420 ### Stream.OnUpdate
1010
1111 ## Streams
1212
13 Snapserver can read audio from several input streams, which are configured in the `snapserver.conf` file (default location is `/etc/snapserver.conf`); the config file can be changed with the `-c` parameter.
14 Within the config file a list of input streams can be configured in the `[stream]` section:
13 Snapserver can read audio from several sources, which are configured in the `snapserver.conf` file (default location is `/etc/snapserver.conf`); the config file can be changed with the `-c` parameter.
14 Within the config file a list of pcm sources can be configured in the `[stream]` section:
1515
1616 ```ini
1717 [stream]
1818 ...
1919 # stream URI of the PCM input stream, can be configured multiple times
2020 # Format: TYPE://host/path?name=NAME[&codec=CODEC][&sampleformat=SAMPLEFORMAT]
21 stream = pipe:///tmp/snapfifo?name=default
21 source = pipe:///tmp/snapfifo?name=default
2222 ...
2323 ```
2424
3636 For example:
3737
3838 ```ini
39 stream = spotify:///librespot?name=Spotify[&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320]
39 source = spotify:///librespot?name=Spotify[&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320]
4040 ```
4141
4242 * `username` and `password` are both optional in this case. You need to specify neither or both of them.
4646 For instance, a valid usage would be:
4747
4848 ```ini
49 stream = spotify:///librespot?name=Spotify&bitrate=160
49 source = spotify:///librespot?name=Spotify&bitrate=160
5050 ```
5151
5252 ### MPD
185185
186186 ### AirPlay
187187
188 Snapserver supports [shairport-sync](https://github.com/mikebrady/shairport-sync) with the `stdout` backend.
189
190 1. Build shairport-sync (version 3.3 or later) with `stdout` backend: `./configure --with-stdout --with-avahi --with-ssl=openssl --with-metadata`
191 2. Copy the `shairport-sync` binary somewhere to your `PATH`, e.g. `/usr/local/bin/`
192 3. Configure snapserver with `stream = airplay:///shairport-sync?name=Airplay[&devicename=Snapcast][&port=5000]`
188 Snapserver supports [shairport-sync](https://github.com/mikebrady/shairport-sync) with the `stdout` backend and metadata support.
189
190 1. Install dependencies. For debian derivates: `apt-get install autoconf libpopt-dev libconfig-dev libssl-dev`
191 2. Build shairport-sync (version 3.3 or later) with `stdout` backend:
192 - `autoreconf -i -f`
193 - `./configure --with-stdout --with-avahi --with-ssl=openssl --with-metadata`
194 3. Copy the `shairport-sync` binary somewhere to your `PATH`, e.g. `/usr/local/bin/`
195 4. Configure snapserver with `source = airplay:///shairport-sync?name=Airplay[&devicename=Snapcast][&port=5000]`
193196
194197 ### Spotify
195198
196199 Snapserver supports [librespot](https://github.com/librespot-org/librespot) with the `pipe` backend.
197200
198201 1. Build and copy the `librespot` binary somewhere to your `PATH`, e.g. `/usr/local/bin/`
199 2. Configure snapserver with `stream = spotify:///librespot?name=Spotify[&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&onstart=<start command>][&onstop=<stop command>][&volume=<volume in percent>][&cache=<cache dir>][&disable_audio_cache=false][&killall=true]`
202 2. Configure snapserver with `source = spotify:///librespot?name=Spotify[&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&onstart=<start command>][&onstop=<stop command>][&volume=<volume in percent>][&cache=<cache dir>][&disable_audio_cache=false][&killall=false]`
200203 * Valid bitrates are 96, 160, 320
201204 * `start command` and `stop command` are executed by Librespot at start/stop
202205 * For example: `onstart=/usr/bin/logger -t Snapcast Starting spotify...`
203 * If `killall` is `true` (default), all running instances of Librespot will be killed. This MUST be disabled on all spotify streams by setting it to `false` if you want to use multiple spotify streams.
206 * If `killall` is `true`, all running instances of Librespot will be killed. This MUST be disabled on all spotify streams by setting it to `false` if you want to use multiple spotify streams.
204207 * If `disable_audio_cache` is `false` (default), downloaded audio files are cached in `<cache dir>`. If set to `true` audio files will not be cached on disk.
205208
206209 ### Process
207210
208211 Snapserver can start any process and read PCM data from the stdout of the process:
209212
210 Configure snapserver with `stream = process:///path/to/process?name=Process[&params=<--my list --of params>][&log_stderr=false]`
213 Configure snapserver with `source = process:///path/to/process?name=Process[&params=<--my list --of params>][&log_stderr=false]`
211214
212215 For example, you could install the minimalist **mpv** media player to pick up WebRadio from a given url ...
213216
214217 ```ini
215218 [stream]
216 stream = process:///usr/bin/mpv?name=Webradio&sampleformat=48000:16:2&params=http://129.122.92.10:88/broadwavehigh.mp3 --no-terminal --audio-display=no --audio-channels=stereo --audio-samplerate=48000 --audio-format=s16 --ao=pcm:file=/dev/stdout
219 source = process:///usr/bin/mpv?name=Webradio&sampleformat=48000:16:2&params=http://129.122.92.10:88/broadwavehigh.mp3 --no-terminal --audio-display=no --audio-channels=stereo --audio-samplerate=48000 --audio-format=s16 --ao=pcm:file=/dev/stdout
217220 ```
218221
219222 ### Line-in
3131 $(error android NDK_DIR is not set)
3232 endif
3333 ifndef ARCH
34 $(error ARCH is not set ("arm" or "aarch64" or "x86"))
34 $(error ARCH is not set ("arm" or "aarch64" or "x86" or "x86_64"))
3535 endif
3636
3737 $(eval TOOLCHAIN:=$(NDK_DIR)/toolchains/llvm/prebuilt/linux-x86_64)
3838
3939 ifeq ($(ARCH), x86)
40 $(eval CPPFLAGS:=-DLITTLE_ENDIAN=1234 -DBIG_ENDIAN=4321 -DBYTE_ORDER=LITTLE_ENDIAN)
41 $(eval TARGET:=i686-linux-android)
42 $(eval API:=16)
43 else ifeq ($(ARCH), x86_64)
4044 $(eval CPPFLAGS:=-DLITTLE_ENDIAN=1234 -DBIG_ENDIAN=4321 -DBYTE_ORDER=LITTLE_ENDIAN)
4145 $(eval TARGET:=x86_64-linux-android)
4246 $(eval API:=21)
4953 $(eval TARGET:=aarch64-linux-android)
5054 $(eval API:=21)
5155 else
52 $(error ARCH must be "arm" or "aarch64" or "x86")
56 $(error ARCH must be "arm" or "aarch64" or "x86" or "x86_64")
5357 endif
5458 $(eval CC:=$(TOOLCHAIN)/bin/$(TARGET)$(API)-clang)
5559 $(eval CXX:=$(TOOLCHAIN)/bin/$(TARGET)$(API)-clang++)
6367 export CPPFLAGS="$(CPPFLAGS)"; \
6468 ./autogen.sh; \
6569 ./configure --host=$(ARCH) --disable-ogg --prefix=$(SYSROOT)/usr/local/; \
66 make; \
70 make -j 10; \
6771 make install; \
6872 make clean;
6973
7377 export CXX="$(CXX)"; \
7478 export CPPFLAGS="$(CPPFLAGS)"; \
7579 ./autogen.sh; \
76 ./configure --host=$(ARCH) --prefix=$(SYSROOT)/usr/local/; \
77 make; \
80 ./configure --host=$(ARCH) --with-pic --prefix=$(SYSROOT)/usr/local/; \
81 make -j 10; \
7882 make install; \
7983 make clean;
8084
8589 export CPPFLAGS="$(CPPFLAGS)"; \
8690 ./autogen.sh; \
8791 ./configure --host=$(ARCH) --prefix=$(SYSROOT)/usr/local/; \
88 make; \
92 make -j 10; \
8993 make install; \
9094 make clean;
9195
9599 export CXX="$(CXX)"; \
96100 export CPPFLAGS="$(CPPFLAGS)"; \
97101 ./autogen.sh; \
98 ./configure --host=$(ARCH) --prefix=$(SYSROOT)/usr/local/ --with-ogg=$(SYSROOT)/usr/local/; \
99 make; \
102 ./configure --host=$(ARCH) --with-pic --prefix=$(SYSROOT)/usr/local/ --with-ogg=$(SYSROOT)/usr/local/; \
103 make -j 10; \
100104 make install; \
101105 make clean; \
102106 rm -rf .deps/; \
129133 mkdir build; \
130134 cd build; \
131135 cmake ..; \
132 make; \
136 make -j 10; \
133137 make DESTDIR=$(SYSROOT) install; \
134138 make clean; \
135139 cd ..; \
143147 mkdir build; \
144148 cd build; \
145149 cmake -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DWITH_OPENMP=OFF ..; \
146 make; \
150 make -j 10; \
147151 make DESTDIR=$(SYSROOT) install; \
148152 make clean; \
149153 cd ..; \
0 #!/bin/bash
1
2 root=$1
3 name=$2
4 version=$3
5 lib=$4
6 include=$5
7
8 echo "root: $root"
9 echo "name: $name"
10 echo "version: $version"
11 #echo "lib: $lib"
12 #echo "include: $include"
13
14 root=$root/$name-$version
15 libs=$root/prefab/modules/$name/libs
16
17 mkdir -p "$root/prefab/modules/$name/include"
18 mkdir -p "$libs/android.arm64-v8a"
19 mkdir -p "$libs/android.armeabi-v7a"
20 mkdir -p "$libs/android.x86"
21 mkdir -p "$libs/android.x86_64"
22
23 echo '{"abi":"arm64-v8a","api":21,"ndk":21,"stl":"c++_shared"}' > $libs/android.arm64-v8a/abi.json
24 echo '{"abi":"armeabi-v7a","api":16,"ndk":21,"stl":"c++_shared"}' > $libs/android.armeabi-v7a/abi.json
25 echo '{"abi":"x86","api":16,"ndk":21,"stl":"c++_shared"}' > $libs/android.x86/abi.json
26 echo '{"abi":"x86_64","api":21,"ndk":21,"stl":"c++_shared"}' > $libs/android.x86_64/abi.json
27
28 echo -e '{\n "export_libraries": [],\n "library_name": null,\n "android": {\n "export_libraries": [],\n "library_name": null\n }\n}' > $root/prefab/modules/$name/module.json
29
30 printf '{\n "schema_version": 1,\n "name": "%s",\n "version": "%s",\n "dependencies": []\n}' $name $version > $root/prefab/prefab.json
31
32 printf '<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.badaix.%s" android:versionCode="1" android:versionName="1.0">\n <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="29"/>\n</manifest>' $name > $root/AndroidManifest.xml
33
9393 install(TARGETS snapserver COMPONENT server DESTINATION ${CMAKE_INSTALL_BINDIR})
9494 install(FILES snapserver.1 COMPONENT server DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
9595 install(FILES etc/snapserver.conf COMPONENT server DESTINATION ${CMAKE_INSTALL_SYSCONFDIR})
96 install(FILES etc/index.html COMPONENT server DESTINATION ${CMAKE_INSTALL_DATADIR}/snapserver)
9697 install(DIRECTORY etc/snapweb/ DESTINATION ${CMAKE_INSTALL_DATADIR}/snapserver/snapweb)
9798 #install(FILES ../debian/snapserver.service DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR})
1313 # You should have received a copy of the GNU General Public License
1414 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16 VERSION = 0.22.0
16 VERSION = 0.23.0
1717 BIN = snapserver
1818
1919 ifeq ($(TARGET), FREEBSD)
124124 install -g wheel -o root -m 555 $(BIN).1 $(TARGET_DIR)/local/man/man1/$(BIN).1
125125 install -g wheel -o root -m 555 etc/$(BIN).bsd $(TARGET_DIR)/local/etc/rc.d/$(BIN)
126126 install -g wheel -o root etc/$(BIN).conf /etc/$(BIN).conf
127 install -g wheel -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
127128 for file in etc/snapweb/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
128129 for file in etc/snapweb/3rd-party/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
129130
135136 install -g wheel -o root $(BIN).1 $(TARGET_DIR)/local/share/man/man1/$(BIN).1
136137 install -g wheel -o root etc/$(BIN).plist /Library/LaunchAgents/de.badaix.snapcast.$(BIN).plist
137138 install -g wheel -o root etc/$(BIN).conf /etc/$(BIN).conf
139 install -g wheel -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
138140 for file in etc/snapweb/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
139141 for file in etc/snapweb/3rd-party/*\.*; do install -g wheel -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
140142 launchctl load /Library/LaunchAgents/de.badaix.snapcast.$(BIN).plist
162164 install -s -D -g root -o root $(BIN) $(TARGET_DIR)/bin/$(BIN)
163165 install -D -g root -o root $(BIN).1 $(TARGET_DIR)/share/man/man1/$(BIN).1
164166 install -g root -o root etc/$(BIN).conf /etc/$(BIN).conf;
167 install -g root -o root -m 644 etc/index.html -Dt /usr/share/snapserver/
165168 for file in etc/snapweb/*\.*; do install -g root -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/"; done
166169 for file in etc/snapweb/3rd-party/*\.*; do install -g root -o root -m 644 $${file} -Dt "/usr/share/snapserver/snapweb/3rd-party/"; done
167170
2929
3030
3131 static constexpr const char* HTTP_SERVER_NAME = "Snapcast";
32 static constexpr const char* UNCONFIGURED =
33 "<html><head><title>Snapcast Default Page</title></head>"
34 "<body>"
35 " <h1>Snapcast Default Page</h1>"
36 " <p>"
37 " This is the default welcome page used to test the correct operation of the Snapcast built-in webserver."
38 " </p>"
39 " <p>"
40 " This webserver is a websocket endpoint for control clients (ws://<i>host</i>:1780/jsonrpc) and streaming clients"
41 " (ws://<i>host</i>:1780/stream), but it can also host simple web pages. To serve a web page, you must configure the"
42 " document root in the snapserver configuration file <b>snapserver.conf</b>, usually located in"
43 " <b>/etc/snapserver.conf</b>"
44 " </p>"
45 " <p>"
46 " The Snapserver installation should include a copy of <a href=\"https://github.com/badaix/snapweb\">Snapweb</a>,"
47 " located in <b>/usr/share/snapserver/snapweb/</b><br>"
48 " To activate it, please configure the <b>doc_root</b> as follows, and restart Snapserver to activate the changes:"
49 " </p>"
50 " <pre>"
51 "# HTTP RPC #####################################\n"
52 "#\n"
53 "[http]\n"
54 "\n"
55 "...\n"
56 "\n"
57 "# serve a website from the doc_root location\n"
58 "doc_root = /usr/share/snapserver/snapweb/\n"
59 "\n"
60 "#\n"
61 "################################################</pre>"
62 "</body>"
63 "</html>";
3264
3365 namespace
3466 {
119151
120152 void ControlSessionHttp::start()
121153 {
122 http::async_read(socket_, buffer_, req_, boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](
123 boost::system::error_code ec, std::size_t bytes) { on_read(ec, bytes); }));
154 http::async_read(
155 socket_, buffer_, req_,
156 boost::asio::bind_executor(strand_, [this, self = shared_from_this()](boost::system::error_code ec, std::size_t bytes) { on_read(ec, bytes); }));
124157 }
125158
126159
154187 return res;
155188 };
156189
190 // Returns a configuration help
191 auto const unconfigured = [&req]() {
192 http::response<http::string_body> res{http::status::ok, req.version()};
193 res.set(http::field::server, HTTP_SERVER_NAME);
194 res.set(http::field::content_type, "text/html");
195 res.keep_alive(req.keep_alive());
196 res.body() = UNCONFIGURED;
197 res.prepare_payload();
198 return res;
199 };
200
157201 // Returns a server error response
158202 auto const server_error = [&req](boost::beast::string_view what) {
159203 http::response<http::string_body> res{http::status::internal_server_error, req.version()};
189233 if (req.target().empty() || req.target()[0] != '/' || req.target().find("..") != beast::string_view::npos)
190234 return send(bad_request("Illegal request-target"));
191235
192 if (settings_.doc_root.empty())
193 return send(not_found(req.target()));
194
195236 // Build the path to the requested file
196237 std::string path = path_cat(settings_.doc_root, req.target());
197238 if (req.target().back() == '/')
198239 path.append("index.html");
240
241 if (settings_.doc_root.empty())
242 {
243 std::string default_page = "/usr/share/snapserver/index.html";
244 struct stat buffer;
245 if (stat(default_page.c_str(), &buffer) == 0)
246 path = default_page;
247 else
248 return send(unconfigured());
249 }
199250
200251 LOG(DEBUG, LOG_TAG) << "path: " << path << "\n";
201252 // Attempt to open the file
262313 // Create a WebSocket session by transferring the socket
263314 // std::make_shared<websocket_session>(std::move(socket_), state_)->run(std::move(req_));
264315 auto ws = std::make_shared<websocket::stream<beast::tcp_stream>>(std::move(socket_));
265 ws->async_accept(req_, [ this, ws, self = shared_from_this() ](beast::error_code ec) {
316 ws->async_accept(req_, [this, ws, self = shared_from_this()](beast::error_code ec) {
266317 if (ec)
267318 {
268319 LOG(ERROR, LOG_TAG) << "Error during WebSocket handshake (control): " << ec.message() << "\n";
279330 // Create a WebSocket session by transferring the socket
280331 // std::make_shared<websocket_session>(std::move(socket_), state_)->run(std::move(req_));
281332 auto ws = std::make_shared<websocket::stream<beast::tcp_stream>>(std::move(socket_));
282 ws->async_accept(req_, [ this, ws, self = shared_from_this() ](beast::error_code ec) {
333 ws->async_accept(req_, [this, ws, self = shared_from_this()](beast::error_code ec) {
283334 if (ec)
284335 {
285336 LOG(ERROR, LOG_TAG) << "Error during WebSocket handshake (stream): " << ec.message() << "\n";
304355
305356 // Write the response
306357 http::async_write(this->socket_, *sp,
307 boost::asio::bind_executor(strand_, [ this, self = this->shared_from_this(), sp ](beast::error_code ec, std::size_t bytes) {
358 boost::asio::bind_executor(strand_, [this, self = this->shared_from_this(), sp](beast::error_code ec, std::size_t bytes) {
308359 this->on_write(ec, bytes, sp->need_eof());
309360 }));
310361 });
334385
335386 // Read another request
336387 http::async_read(socket_, buffer_, req_,
337 boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](beast::error_code ec, std::size_t bytes) { on_read(ec, bytes); }));
388 boost::asio::bind_executor(strand_, [this, self = shared_from_this()](beast::error_code ec, std::size_t bytes) { on_read(ec, bytes); }));
338389 }
339390
340391
2020
2121 #include "control_session.hpp"
2222 #include <boost/beast/core.hpp>
23 #if defined(__GNUC__) && !defined(__clang__)
24 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
2326 #include <boost/beast/websocket.hpp>
27 #pragma GCC diagnostic pop
28 #else
29 #include <boost/beast/websocket.hpp>
30 #endif
2431 #include <deque>
2532
2633 namespace beast = boost::beast; // from <boost/beast.hpp>
4444 const std::string delimiter = "\n";
4545 boost::asio::async_read_until(
4646 socket_, streambuf_, delimiter,
47 boost::asio::bind_executor(strand_, [ this, self = shared_from_this(), delimiter ](const std::error_code& ec, std::size_t bytes_transferred) {
47 boost::asio::bind_executor(strand_, [this, self = shared_from_this(), delimiter](const std::error_code& ec, std::size_t bytes_transferred) {
4848 if (ec)
4949 {
5050 LOG(ERROR, LOG_TAG) << "Error while reading from control socket: " << ec.message() << "\n";
9393
9494 void ControlSessionTcp::sendAsync(const std::string& message)
9595 {
96 strand_.post([ this, self = shared_from_this(), message ]() {
96 strand_.post([this, self = shared_from_this(), message]() {
9797 messages_.emplace_back(message + "\r\n");
9898 if (messages_.size() > 1)
9999 {
107107 void ControlSessionTcp::send_next()
108108 {
109109 boost::asio::async_write(socket_, boost::asio::buffer(messages_.front()),
110 boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](std::error_code ec, std::size_t length) {
110 boost::asio::bind_executor(strand_, [this, self = shared_from_this()](std::error_code ec, std::size_t length) {
111111 messages_.pop_front();
112112 if (ec)
113113 {
6060
6161 void ControlSessionWebsocket::sendAsync(const std::string& message)
6262 {
63 strand_.post([ this, self = shared_from_this(), msg = message ]() {
63 strand_.post([this, self = shared_from_this(), msg = message]() {
6464 messages_.push_back(std::move(msg));
6565 if (messages_.size() > 1)
6666 {
7676 {
7777 const std::string& message = messages_.front();
7878 ws_.async_write(boost::asio::buffer(message),
79 boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](std::error_code ec, std::size_t length) {
79 boost::asio::bind_executor(strand_, [this, self = shared_from_this()](std::error_code ec, std::size_t length) {
8080 messages_.pop_front();
8181 if (ec)
8282 {
9595 void ControlSessionWebsocket::do_read_ws()
9696 {
9797 // Read a message into our buffer
98 ws_.async_read(buffer_, boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](beast::error_code ec, std::size_t bytes_transferred) {
98 ws_.async_read(buffer_, boost::asio::bind_executor(strand_, [this, self = shared_from_this()](beast::error_code ec, std::size_t bytes_transferred) {
9999 on_read_ws(ec, bytes_transferred);
100100 }));
101101 }
0 <html>
1
2 <head>
3 <title>Snapcast Default Page</title>
4 <style>
5 body {
6 background: #ffffff;
7 color: rgb(0, 0, 0);
8 font-family: 'Arial', sans-serif;
9 margin: 20px;
10 font-size: 20px;
11 }
12
13 pre {
14 margin: 8px 0px 8px 0px;
15 padding: 20px;
16 border-width: 1px;
17 border-style: dotted;
18 border-color: #000000;
19 background-color: #F5F6F7;
20 font-style: italic;
21 display: inline-block;
22 }
23
24 h1 {
25 margin: 15px 0px 0px 50px;
26 font-size: 180%;
27 font-weight: bold;
28 }
29 </style>
30 </head>
31
32 <body>
33 <h1>Snapcast Default Page</h1>
34 <p>
35 This is the default welcome page used to test the correct operation of the Snapcast built-in webserver.
36 </p>
37 <p>
38 This webserver is a websocket endpoint for control clients (ws://<i>host</i>:1780/jsonrpc) and streaming clients
39 (ws://<i>host</i>:1780/stream), but it can also host simple web pages. To serve a web page, you must configure the
40 document root in the snapserver configuration file <b>snapserver.conf</b>, usually located in
41 <b>/etc/snapserver.conf</b>
42 </p>
43 <p>
44 The Snapserver installation should include a copy of <a href="https://github.com/badaix/snapweb">Snapweb</a>,
45 located in
46 <b>/usr/share/snapserver/snapweb/</b><br>
47 To activate it, please configure the <b>doc_root</b> as follows, and restart Snapserver to activate the changes:
48 </p>
49 <pre>
50 # HTTP RPC #####################################
51 #
52 [http]
53
54 ...
55
56 # serve a website from the doc_root location
57 doc_root = /usr/share/snapserver/snapweb/
58
59 #
60 ################################################</pre>
61 </body>
62
63 </html>
+0
-582
server/etc/interface.html less more
0 <html>
1
2 <head>
3 <title>Snapcast Interface</title>
4 Taken from <a href="https://github.com/derglaus/snapcast-websockets-ui">derglaus/snapcast-websockets-ui</a> for
5 testing purposes
6 <script>
7
8 var connection = new WebSocket('ws://' + window.location.hostname + ':1780/jsonrpc');
9
10 var server;
11
12 connection.onmessage = function (e) {
13 var recv = e.data
14 // console.log(recv);
15 var answer = JSON.parse(recv);
16 console.log(answer)
17 if (answer.id == 1) {
18 server = answer.result;
19 } else if (Array.isArray(answer)) {
20 for (let i = 0; i < answer.length; i++) {
21 action(answer[i]);
22 }
23 } else {
24 action(answer);
25
26 }
27
28 show()
29 }
30
31 connection.onopen = function () {
32 send('{"id":1,"jsonrpc":"2.0","method":"Server.GetStatus"}')
33 }
34
35 connection.onerror = function () {
36 alert("error");
37 }
38
39 function action(answer) {
40 switch (answer.method) {
41 case 'Client.OnVolumeChanged':
42 case 'Client.OnLatencyChanged':
43 case 'Client.OnNameChanged':
44 clientChange(answer.params);
45 break;
46 case 'Client.OnConnect':
47 case 'Client.OnDisconnect':
48 clientConnect(answer.params);
49 break;
50 case 'Group.OnMute':
51 groupMute(answer.params);
52 break;
53 case 'Group.OnStremChanged':
54 groupStream(answer.params);
55 break;
56 case 'Stream.OnUpdate':
57 streamUpdate(answer.params);
58 break;
59 case 'Server.OnUpdate':
60 server = answer.params;
61 break;
62 default:
63 break;
64 }
65 }
66
67 function send(str) {
68 var buf = new ArrayBuffer(str.length);
69 var bufView = new Uint8Array(buf);
70 for (var i = 0, strLen = str.length; i < strLen; i++) {
71 bufView[i] = str.charCodeAt(i);
72 }
73
74 // console.log(buf);
75 var recv = String.fromCharCode.apply(null, new Uint8Array(buf));
76 // console.log(recv);
77
78 connection.send(buf)
79
80 }
81
82 function clientChange(params) {
83 // Update the client configuration with one from params
84 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
85 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
86 if (server.server.groups[i_group].clients[i_client].id == params.id) {
87 server.server.groups[i_group].clients[i_client].config = Object.assign(server.server.groups[i_group].clients[i_client].config, params);
88 }
89 }
90 }
91 }
92
93 function clientConnect(params) {
94 // Update all client info
95 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
96 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
97 if (server.server.groups[i_group].clients[i_client].id == params.client.id) {
98 server.server.groups[i_group].clients[i_client] = params.client;
99 // console.log(server.server.groups[i_group].clients[i_client]);
100 }
101 }
102 }
103 }
104
105 function groupMute(params) {
106 // Set group mute boolean
107 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
108 if (server.server.groups[i_group].id == params.id) {
109 server.server.groups[i_group].muted = params.mute;
110 }
111 }
112 }
113
114 function groupStream(params) {
115 // Set group stream id
116 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
117 if (server.server.groups[i_group].id == params.id) {
118 server.server.groups[i_group].stream_id = params.stream_id;
119 }
120 }
121 }
122
123 function streamUpdate(params) {
124 // Update all stream inforamtion
125 for (let i_stream = 0; i_stream < server.server.streams.length;) {
126 if (server.server.streams[i_stream].id == params.id) {
127 server.server.streams[i_stream] = params.stream;
128 // console.log(server.server.streams[i_stream]);
129 }
130
131 }
132 }
133
134 function show() {
135 // Render the page
136 var content = "";
137
138 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
139 // Set mute variables
140 var classgroup;
141 var unmuted;
142 var mutetext;
143 if (server.server.groups[i_group].muted == true) {
144 classgroup = 'groupmuted';
145 unmuted = 'false';
146 mutetext = '&#x1F507';
147 } else {
148 classgroup = 'group';
149 unmuted = 'true';
150 mutetext = '&#128266';
151 }
152
153 // Start group div
154 content += "<div id='g_" + server.server.groups[i_group].id + "' class='" + classgroup + "'>";
155
156 // Create stream selection dropdown
157 var streamselect = "<select id='stream_" + server.server.groups[i_group].id + "' onchange='setStream(\"" + server.server.groups[i_group].id + "\")' class='stream'>"
158 for (let i_stream = 0; i_stream < server.server.streams.length; i_stream++) {
159 var streamselected = "";
160 if (server.server.groups[i_group].stream_id == server.server.streams[i_stream].id) {
161 streamselected = 'selected'
162 }
163 streamselect += "<option value='" + server.server.streams[i_stream].id + "' " + streamselected + ">" + server.server.streams[i_stream].id + ": " + server.server.streams[i_stream].status + "</option>";
164 }
165
166 streamselect += "</select>";
167 content += streamselect;
168
169 // Group mute and refresh button
170 content += " <a href=\"javascript:setMuteGroup('" + server.server.groups[i_group].id + "','" + unmuted + "');\" class='mutebuttongroup'>" + mutetext + "</a>";
171 content += "<input type='button' value='Refresh' class='refreshbutton' onclick='javascript: location.reload()'>";
172 content += "<br/>";
173
174 // Create clients in group
175 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
176 var sv = server.server.groups[i_group].clients[i_client];
177
178 // Set name and connection state vars, start client div
179 var name;
180 var clas = 'client'
181 if (sv.config.name != "") {
182 name = sv.config.name;
183 } else {
184 name = sv.host.name;
185 }
186 if (sv.connected == false) {
187 clas = 'disconnected';
188 }
189 content = content + "<div id='c_" + sv.id + "' class='" + clas + "'>";
190
191 // Client mute status vars
192 var unmuted;
193 var mutetextclient;
194 var sliderclass;
195 if (sv.config.volume.muted == true) {
196 unmuted = 'false';
197 sliderclass = 'slidermute';
198 mutetext = '&#128263';
199 } else {
200 sliderclass = 'slider'
201 unmuted = 'true';
202 mutetext = '&#128266';
203 }
204
205 // Client group selection vars
206 var groupselect = "<select id='group_" + sv.id + "' onchange='setGroup(\"" + sv.id + "\")'>";
207 for (let o_group = 0; o_group < server.server.groups.length; o_group++) {
208 var groupselected = "";
209 if (o_group == i_group) {
210 groupselected = 'selected'
211 }
212 groupselect = groupselect + "<option value='" + server.server.groups[o_group].id + "' " + groupselected + ">Group " + o_group + " (" + server.server.groups[o_group].clients.length + " Clients)</option>";
213 }
214
215 groupselect = groupselect + "<option value='new'>new</option>";
216 groupselect = groupselect + "</select>"
217
218 // Populate client div
219 content = content + " <a href=\"javascript:setVolume('" + sv.id + "','" + unmuted + "');\" class='mutebutton'>" + mutetext + "</a>";
220 content = content + "<div class='sliders'><div class='sliderdiv'><input type='range' min=0 max=100 step=1 id='vol_" + sv.id + "' onchange='javascript:setVolume(\"" + sv.id + "\",\"" + sv.config.volume.muted + "\")' value=" + sv.config.volume.percent + " class='" + sliderclass + "' orient='vertical'></div>";
221 content = content + "<div class='finebg'>++<br>+<br>0<br>-<br>--</div><div class='sliderdiv_fine'><input type='range' min=0 max=10 step=1 id='vol_fine_" + sv.id + "' onchange='javascript:setVolume(\"" + sv.id + "\",\"" + sv.config.volume.muted + "\")' value=5 class='" + sliderclass + "_fine' orient='vertical'></div></div>";
222 content = content + " <a href=\"javascript:setName('" + sv.id + "');\" class='edit'>&#9998</a>";
223 content = content + name;
224 content = content + groupselect;
225 content = content + "</div>";
226 }
227
228 content = content + "</div>"
229 }
230
231 // Pad then update page
232 content = content + "<br><br>";
233 document.getElementById('show').innerHTML = content;
234 }
235
236 function setVolume(id, mute) {
237 percent = document.getElementById('vol_' + id).value;
238 percent_fine = document.getElementById('vol_fine_' + id).value;
239
240 // Take away 5 as it's the default of the fine slider. Only relevant if it
241 // has changed
242 percent = Number(percent) + Number(percent_fine) - 5;
243
244 if (percent < 0) {
245 percent = 0
246 }
247 else if (percent > 100) {
248 percent = 100
249 }
250
251 // Request changes
252 send('{"id":8,"jsonrpc":"2.0","method":"Client.SetVolume","params":{"id":"' + id + '","volume":{"muted":' + mute + ',"percent":' + percent + '}}}')
253
254 // Make updates to server info and refresh content
255 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
256 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
257 var sv = server.server.groups[i_group].clients[i_client];
258 if (sv.id == id) {
259 if (mute == 'true') {
260 sv.config.volume.muted = true;
261 }
262 if (mute == 'false') {
263 sv.config.volume.muted = false;
264 }
265 sv.config.volume.percent = percent;
266 }
267 }
268 }
269 show()
270 }
271
272 function setMuteGroup(id, what) {
273 send('{"id":"MuteGroup_' + id + '","jsonrpc":"2.0","method":"Group.SetMute","params":{"id":"' + id + '","mute":' + what + '}}')
274
275 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
276 if (server.server.groups[i_group].id == id) {
277 if (what == 'true') {
278 server.server.groups[i_group].muted = true;
279 }
280 if (what == 'false') {
281 server.server.groups[i_group].muted = false;
282 }
283 // console.log(server.server.groups[i_group]);
284 }
285 }
286 show()
287 }
288
289 function setStream(id) {
290 send('{"id":4,"jsonrpc":"2.0","method":"Group.SetStream","params":{"id":"' + id + '","stream_id":"' + document.getElementById('stream_' + id).value + '"}}')
291
292 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
293 if (server.server.groups[i_group].id == id) {
294 server.server.groups[i_group].stream_id = document.getElementById('stream_' + id).value;
295 // console.log(server.server.groups[i_group]);
296 }
297 }
298 show()
299 }
300
301 function setGroup(id) {
302 group = document.getElementById('group_' + id).value;
303
304 // Get client group id
305 var current_group;
306 groups:
307 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
308 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
309 if (id == server.server.groups[i_group].clients[i_client].id) {
310 current_group = server.server.groups[i_group].id;
311 break groups;
312 }
313 }
314 }
315
316 // Get
317 // List of target group's clients
318 // OR
319 // List of current group's other clients
320 var send_clients = [];
321 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
322 if (server.server.groups[i_group].id == group || (group == "new" && server.server.groups[i_group].id == current_group)) {
323 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
324 if (group == "new" && server.server.groups[i_group].clients[i_client].id == id) { }
325 else {
326 send_clients[send_clients.length] = server.server.groups[i_group].clients[i_client].id;
327 }
328 }
329 }
330 }
331
332 if (group == "new") {
333 group = current_group
334 }
335 else {
336 send_clients[send_clients.length] = id;
337 }
338
339 var send_clients_string = JSON.stringify(send_clients);
340 send('{"id":1,"jsonrpc":"2.0","method":"Group.SetClients","params":{"clients":' + send_clients_string + ',"id":"' + group + '"}}')
341 }
342
343 function setName(id) {
344 // Get current name and lacency
345 var current_name;
346 var current_latency;
347 groups:
348 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
349 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
350 var sv = server.server.groups[i_group].clients[i_client];
351 if (sv.id == id) {
352 if (sv.config.name != "") {
353 current_name = sv.config.name;
354 } else {
355 current_name = sv.host.name;
356 }
357 current_latency = sv.config.latency;
358 break groups;
359 }
360 }
361 }
362
363 var newName = window.prompt("New Name", current_name);
364 var newLatency = window.prompt("New Latency", current_latency);
365
366 // Don't change anything if user cancel's
367 if (newName != null) {
368 send('{"id":6,"jsonrpc":"2.0","method":"Client.SetName","params":{"id":"' + id + '","name":"' + newName + '"}}')
369 } else {
370 newName = current_name
371 }
372 if (newLatency != null) {
373 send('{"id":7,"jsonrpc":"2.0","method":"Client.SetLatency","params":{"id":"' + id + '","latency":' + newLatency + '}}')
374 } else {
375 newLatency = current_latency
376 }
377
378 for (let i_group = 0; i_group < server.server.groups.length; i_group++) {
379 for (let i_client = 0; i_client < server.server.groups[i_group].clients.length; i_client++) {
380 var sv = server.server.groups[i_group].clients[i_client];
381 if (sv.id == id) {
382 sv.config.name = newName;
383 sv.config.latency = newLatency;
384 }
385 }
386 }
387 show()
388 }
389
390 </script>
391 <style>
392 body {
393 background: #1f1f1f;
394 color: rgb(255, 255, 255);
395 font-family: 'Arial', sans-serif;
396 width: 100%;
397 margin: 0;
398 font-size: 20px;
399 }
400
401 /* width */
402 ::-webkit-scrollbar {
403 width: 10px;
404 }
405
406 /* Track */
407 ::-webkit-scrollbar-track {
408 background: #1f1f1f;
409 }
410
411 /* Handle */
412 ::-webkit-scrollbar-thumb {
413 background: #333;
414 }
415
416 /* Handle on hover */
417 ::-webkit-scrollbar-thumb:hover {
418 background: #555;
419 }
420
421 .group {
422 float: none;
423 clear: both;
424 margin: 20px 15px 10px 15px;
425 border: 2px solid #5f5f5f;
426 overflow: auto;
427 }
428
429 .groupmuted {
430 float: none;
431 clear: both;
432 margin: 20px 15px 10px 15px;
433 border: 2px solid #5f5f5f;
434 overflow: auto;
435 opacity: 0.27;
436 }
437
438 .client {
439 text-align: center;
440 background: rgb(61, 61, 61);
441 margin: 10px;
442 width: 160px;
443 height: 360px;
444 float: left;
445 }
446
447 .disconnected {
448 text-align: center;
449 background: rgb(61, 61, 61);
450 margin: 10px;
451 width: 160px;
452 height: 360px;
453 float: left;
454 opacity: 0.27;
455 }
456
457 .slider {
458 writing-mode: bt-lr;
459 /* IE */
460 -webkit-appearance: slider-vertical;
461 /* WebKit */
462 height: 240px;
463 width: 15px;
464 }
465
466 .slidermute {
467 writing-mode: bt-lr;
468 /* IE */
469 -webkit-appearance: slider-vertical;
470 /* WebKit */
471 opacity: 0.27;
472 height: 240px;
473 width: 15px;
474 }
475
476 .slider_fine {
477 writing-mode: bt-lr;
478 /* IE */
479 -webkit-appearance: slider-vertical;
480 /* WebKit */
481 height: 240px;
482 width: 15px;
483 }
484
485 .slidermute_fine {
486 writing-mode: bt-lr;
487 /* IE */
488 -webkit-appearance: slider-vertical;
489 /* WebKit */
490 height: 240px;
491 width: 15px;
492 opacity: 0.27;
493 }
494
495 .sliders {
496 text-align: left;
497 vertical-align: middle;
498 height: 250px;
499 padding-top: 10px;
500 clear: both;
501 float: none;
502 }
503
504 .sliderdiv {
505 display: inline-block;
506 padding-left: 40px;
507 text-align: left;
508 width: 20px;
509 }
510
511 .sliderdiv_fine {
512 display: inline-block;
513 text-align: left;
514 width: 20px;
515 position: relative;
516 top: 0px;
517 left: 13px;
518 opacity: 0.01;
519 }
520
521 .finebg {
522 display: inline-block;
523 text-align: center;
524 font-size: 35px;
525 width: 40px;
526 position: relative;
527 top: -27px;
528 left: 40px;
529 color: #999;
530 }
531
532 select {
533 background-color: rgb(61, 61, 61);
534 width: 150px;
535 font-size: 20px;
536 color: #e3e3e3;
537 border: 1px solid #555555;
538 -moz-appearance: none;
539 -webkit-appearance: none;
540 appearance: none;
541 }
542
543 .stream {
544 margin-left: 20px;
545 width: 200px;
546 padding-left: 5px;
547 }
548
549 .refreshbutton {
550 background-color: rgb(61, 61, 61);
551 font-size: 20px;
552 color: #e3e3e3;
553 border: 1px solid #555555;
554 margin-left: 100px;
555 }
556
557 .mutebutton {
558 color: #e3e3e3;
559 font-size: 30px;
560 display: block;
561 text-decoration: none;
562 }
563
564 .mutebuttongroup {
565 font-size: 30px;
566 color: #e3e3e3;
567 text-decoration: none;
568 }
569
570 .edit {
571 color: #e3e3e3;
572 text-decoration: none;
573 }
574 </style>
575 </head>
576
577 <body>
578 <div id="show"></div>
579 </body>
580
581 </html>
114114 # Non blocking sources support the dryout_ms parameter: when no new data is read from the source, send silence to the clients
115115 # Available types are:
116116 # pipe: pipe:///<path/to/pipe>?name=<name>[&mode=create][&dryout_ms=2000], mode can be "create" or "read"
117 # librespot: librespot:///<path/to/librespot>?name=<name>[&dryout_ms=2000][&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&wd_timeout=7800][&volume=100][&onevent=""][&nomalize=false][&autoplay=false]
117 # librespot: librespot:///<path/to/librespot>?name=<name>[&dryout_ms=2000][&username=<my username>&password=<my password>][&devicename=Snapcast][&bitrate=320][&wd_timeout=7800][&volume=100][&onevent=""][&nomalize=false][&autoplay=false][&params=<generic librepsot process arguments>]
118118 # note that you need to have the librespot binary on your machine
119119 # sampleformat will be set to "44100:16:2"
120120 # file: file:///<path/to/PCM/file>?name=<name>
124124 # sampleformat will be set to "44100:16:2"
125125 # tcp server: tcp://<listen IP, e.g. 127.0.0.1>:<port>?name=<name>[&mode=server]
126126 # tcp client: tcp://<server IP, e.g. 127.0.0.1>:<port>?name=<name>&mode=client
127 # alsa: alsa://?name=<name>&device=<alsa device>
127 # alsa: alsa://?name=<name>&device=<alsa device>[&send_silence=false][&idle_threshold=100]
128128 # meta: meta:///<name of source#1>/<name of source#2>/.../<name of source#N>?name=<name>
129129 source = pipe:///tmp/snapfifo?name=default
130130 #source = tcp://127.0.0.1?name=mopidy_tcp
802802 inline Json Error::to_json() const
803803 {
804804 Json j = {
805 {"code", code_}, {"message", message_},
805 {"code", code_},
806 {"message", message_},
806807 };
807808
808809 if (!data_.is_null())
10641065 inline Json Response::to_json() const
10651066 {
10661067 Json j = {
1067 {"jsonrpc", "2.0"}, {"id", id_.to_json()},
1068 {"jsonrpc", "2.0"},
1069 {"id", id_.to_json()},
10681070 };
10691071
10701072 if (error_)
11281130 inline Json Notification::to_json() const
11291131 {
11301132 Json json = {
1131 {"jsonrpc", "2.0"}, {"method", method_},
1133 {"jsonrpc", "2.0"},
1134 {"method", method_},
11321135 };
11331136
11341137 if (params_)
221221
222222 case AVAHI_CLIENT_S_COLLISION:
223223
224 /// Let's drop our registered services. When the server is back
225 /// in AVAHI_SERVER_RUNNING state we will register them again with the new host name.
224 /// Let's drop our registered services. When the server is back
225 /// in AVAHI_SERVER_RUNNING state we will register them again with the new host name.
226226
227227 case AVAHI_CLIENT_S_REGISTERING:
228228
2323
2424 static constexpr auto LOG_TAG = "Bonjour";
2525
26 typedef union {
26 typedef union
27 {
2728 unsigned char b[2];
2829 unsigned short NotAnInteger;
2930 } Opaque16;
326326 exitcode = EXIT_FAILURE;
327327 }
328328 Config::instance().save();
329 LOG(NOTICE) << "daemon terminated." << endl;
329 LOG(NOTICE) << "Snapserver terminated." << endl;
330330 exit(exitcode);
331331 }
5151 {
5252 auto& buffer = messages_.front();
5353 buffer.on_air = true;
54 strand_.post([ this, self = shared_from_this(), buffer ]() {
54 strand_.post([this, self = shared_from_this(), buffer]() {
5555 sendAsync(buffer, [this](boost::system::error_code ec, std::size_t length) {
5656 messages_.pop_front();
5757 if (ec)
6969
7070 void StreamSession::send(shared_const_buffer const_buf)
7171 {
72 strand_.post([ this, self = shared_from_this(), const_buf ]() {
72 strand_.post([this, self = shared_from_this(), const_buf]() {
7373 // delete PCM chunks that are older than the overall buffer duration
7474 messages_.erase(std::remove_if(messages_.begin(), messages_.end(),
7575 [this](const shared_const_buffer& buffer) {
8080 void StreamSessionTcp::read_next()
8181 {
8282 boost::asio::async_read(socket_, boost::asio::buffer(buffer_, base_msg_size_),
83 boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](boost::system::error_code ec, std::size_t length) mutable {
83 boost::asio::bind_executor(strand_, [this, self = shared_from_this()](boost::system::error_code ec, std::size_t length) mutable {
8484 if (ec)
8585 {
8686 LOG(ERROR, LOG_TAG) << "Error reading message header of length " << length << ": " << ec.message() << "\n";
130130 void StreamSessionTcp::sendAsync(const shared_const_buffer& buffer, const WriteHandler& handler)
131131 {
132132 boost::asio::async_write(socket_, buffer,
133 boost::asio::bind_executor(strand_, [ self = shared_from_this(), buffer, handler ](boost::system::error_code ec,
134 std::size_t length) { handler(ec, length); }));
133 boost::asio::bind_executor(strand_, [self = shared_from_this(), buffer, handler](boost::system::error_code ec,
134 std::size_t length) { handler(ec, length); }));
135135 }
7676 void StreamSessionWebsocket::sendAsync(const shared_const_buffer& buffer, const WriteHandler& handler)
7777 {
7878 LOG(TRACE, LOG_TAG) << "sendAsync: " << buffer.message().type << "\n";
79 ws_.async_write(buffer, boost::asio::bind_executor(strand_, [ self = shared_from_this(), buffer, handler ](boost::system::error_code ec,
80 std::size_t length) { handler(ec, length); }));
79 ws_.async_write(buffer, boost::asio::bind_executor(strand_, [self = shared_from_this(), buffer, handler](boost::system::error_code ec, std::size_t length) {
80 handler(ec, length);
81 }));
8182 }
8283
8384
8485 void StreamSessionWebsocket::do_read_ws()
8586 {
8687 // Read a message into our buffer
87 ws_.async_read(buffer_, boost::asio::bind_executor(strand_, [ this, self = shared_from_this() ](beast::error_code ec, std::size_t bytes_transferred) {
88 ws_.async_read(buffer_, boost::asio::bind_executor(strand_, [this, self = shared_from_this()](beast::error_code ec, std::size_t bytes_transferred) {
8889 on_read_ws(ec, bytes_transferred);
8990 }));
9091 }
2020 #include "common/aixlog.hpp"
2121 #include "common/snap_exception.hpp"
2222 #include "common/utils.hpp"
23 #include "common/utils/file_utils.hpp"
2324 #include "common/utils/string_utils.hpp"
2425
2526 using namespace std;
5152 logStderr_ = true;
5253
5354 string devicename = uri_.getQuery("devicename", "Snapcast");
54 params_wo_port_ = "\"--name=" + devicename + "\" --output=stdout --use-stderr --get-coverart";
55 string password = uri_.getQuery("password", "");
56
57 params_wo_port_ = "--name=\"" + devicename + "\" --output=stdout --use-stderr --get-coverart";
58 if (!password.empty())
59 params_wo_port_ += " --password \"" + password + "\"";
60 if (!params_.empty())
61 params_wo_port_ += " " + params_;
5562
5663 port_ = cpt::stoul(uri_.getQuery("port", "5000"));
5764 setParamsAndPipePathFromPort();
205212 {
206213 ProcessStream::do_connect();
207214 pipeReadLine();
215 }
216
217
218 void AirplayStream::do_disconnect()
219 {
220 ProcessStream::do_disconnect();
221 // Shairpot-sync created but does not remove the pipe
222 if (utils::file::exists(pipePath_) && (remove(pipePath_.c_str()) != 0))
223 LOG(INFO, LOG_TAG) << "Failed to remove metadata pipe \"" << pipePath_ << "\": " << errno << "\n";
208224 }
209225
210226
235251 {
236252 // For some reason, EOF is returned until the first metadata is written to the pipe.
237253 // If shairport-sync has not finished setting up the pipe, bad file descriptor is returned.
238 LOG(INFO, LOG_TAG) << "Waiting for metadata, retrying in 2500ms"
239 << "\n";
254 LOG(INFO, LOG_TAG) << "Waiting for metadata, retrying in 2500ms\n";
240255 wait(pipe_open_timer_, 2500ms, [this] { pipeReadLine(); });
241256 }
242257 else
8282 void setParamsAndPipePathFromPort();
8383
8484 void do_connect() override;
85 void do_disconnect() override;
8586 void onStderrMsg(const std::string& line) override;
8687 void initExeAndPath(const std::string& filename) override;
8788
6868 : PcmStream(pcmListener, ioc, uri), handle_(nullptr), read_timer_(ioc), silence_(0ms)
6969 {
7070 device_ = uri_.getQuery("device", "hw:0");
71 send_silence_ = (uri_.getQuery("send_silence", "false") == "true");
72 idle_threshold_ = std::chrono::milliseconds(std::max(cpt::stoi(uri_.getQuery("idle_threshold", "100")), 10));
7173 LOG(DEBUG, LOG_TAG) << "Device: " << device_ << "\n";
7274 }
7375
7981 // idle_bytes_ = 0;
8082 // max_idle_bytes_ = sampleFormat_.rate() * sampleFormat_.frameSize() * dryout_ms_ / 1000;
8183
84 initAlsa();
8285 chunk_ = std::make_unique<msg::PcmChunk>(sampleFormat_, chunk_ms_);
8386 silent_chunk_ = std::vector<char>(chunk_->payloadSize, 0);
8487 LOG(DEBUG, LOG_TAG) << "Chunk duration: " << chunk_->durationMs() << " ms, frames: " << chunk_->getFrameCount() << ", size: " << chunk_->payloadSize
8588 << "\n";
8689 first_ = true;
8790 tvEncodedChunk_ = std::chrono::steady_clock::now();
88 initAlsa();
8991 PcmStream::start();
9092 // wait(read_timer_, std::chrono::milliseconds(chunk_ms_), [this] { do_read(); });
9193 do_read();
132134 throw SnapException("Can't set sample format: " + string(snd_strerror(err)));
133135
134136 if ((err = snd_pcm_hw_params_set_rate_near(handle_, hw_params, &rate, 0)) < 0)
137 {
135138 throw SnapException("Can't set rate: " + string(snd_strerror(err)));
139 }
140 else
141 {
142 if (rate != sampleFormat_.rate())
143 {
144 LOG(WARNING, LOG_TAG) << "Rate is not accurate (requested: " << sampleFormat_.rate() << ", got: " << rate << "), using: " << rate << "\n";
145 sampleFormat_.setFormat(rate, sampleFormat_.bits(), sampleFormat_.channels());
146 }
147 }
136148
137149 if ((err = snd_pcm_hw_params_set_channels(handle_, hw_params, sampleFormat_.channels())) < 0)
138150 throw SnapException("Can't set channel count: " + string(snd_strerror(err)));
204216 if (std::memcmp(chunk_->payload, silent_chunk_.data(), silent_chunk_.size()) == 0)
205217 {
206218 silence_ += chunk_->duration<std::chrono::microseconds>();
207 if (silence_ > 100ms)
219 if (silence_ > idle_threshold_)
208220 {
209221 setState(ReaderState::kIdle);
210222 }
212224 else
213225 {
214226 silence_ = 0ms;
227 if ((state_ == ReaderState::kIdle) && !send_silence_)
228 first_ = true;
215229 setState(ReaderState::kPlaying);
216230 }
217231
223237 tvEncodedChunk_ = std::chrono::steady_clock::now() - duration;
224238 }
225239
226 chunkRead(*chunk_);
240 if ((state_ == ReaderState::kPlaying) || ((state_ == ReaderState::kIdle) && send_silence_))
241 {
242 chunkRead(*chunk_);
243 }
227244
228245 nextTick_ += duration;
229246 auto currentTick = std::chrono::steady_clock::now();
5555 std::vector<char> silent_chunk_;
5656 std::chrono::microseconds silence_;
5757 std::string lastException_;
58
59 /// send silent chunks to clients
60 bool send_silence_;
61 /// silence duration before switching the stream to idle
62 std::chrono::milliseconds idle_threshold_;
5863 };
5964
6065 } // namespace streamreader
4545 string onevent = uri_.getQuery("onevent", "");
4646 bool normalize = (uri_.getQuery("normalize", "false") == "true");
4747 bool autoplay = (uri_.getQuery("autoplay", "false") == "true");
48 killall_ = (uri_.getQuery("killall", "true") == "true");
48 killall_ = (uri_.getQuery("killall", "false") == "true");
4949
5050 if (username.empty() != password.empty())
5151 throw SnapException("missing parameter \"username\" or \"password\" (must provide both, or neither)");
4141 continue;
4242
4343 bool found = false;
44 for (const auto stream : streams)
44 for (const auto& stream : streams)
4545 {
4646 if (stream->getName() == component)
4747 {
9595 {
9696 LOG(DEBUG, LOG_TAG) << "onStateChanged: " << pcmStream->getName() << ", state: " << static_cast<int>(state) << "\n";
9797 std::lock_guard<std::mutex> lock(mutex_);
98 for (const auto stream : streams_)
98 for (const auto& stream : streams_)
9999 {
100100 if (stream->getState() == ReaderState::kPlaying)
101101 {
191191 state = "disabled";
192192
193193 json j = {
194 {"uri", uri_.toJson()}, {"id", getId()}, {"status", state},
194 {"uri", uri_.toJson()},
195 {"id", getId()},
196 {"status", state},
195197 };
196198
197199 if (meta_)
5656 {
5757 int fd = open(uri_.path.c_str(), O_RDONLY | O_NONBLOCK);
5858 int pipe_size = -1;
59 #if !defined(MACOS)
59 #if !defined(MACOS) && !defined(FREEBSD)
6060 pipe_size = fcntl(fd, F_GETPIPE_SZ);
6161 #endif
6262 LOG(TRACE, LOG_TAG) << "Stream: " << name_ << ", connect to pipe: " << uri_.path << ", fd: " << fd << ", pipe size: " << pipe_size << "\n";
9595 {
9696 // no data available, fill with silence
9797 memset(chunk_->payload + len, 0, toRead - len);
98 idle_bytes_ += toRead - len;
98
99 // avoid overflow after 186min 24s silence (at 48000:16:2)
100 if (idle_bytes_ <= max_idle_bytes_)
101 idle_bytes_ += toRead - len;
99102 break;
100103 }
101104 else if (count == 0)
152152 if (streams_.empty())
153153 return nullptr;
154154
155 for (const auto stream : streams_)
155 for (const auto& stream : streams_)
156156 {
157157 if (stream->getCodec() != "null")
158158 return stream;
146146 return iter->second;
147147 return def;
148148 }
149 }
149 } // namespace streamreader