Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthurSonzogni <sonzogniarthur@gmail.com>2022-09-25 15:57:52 +0300
committerArthurSonzogni <sonzogniarthur@gmail.com>2022-09-25 15:57:52 +0300
commit4a0e5870a08a36fc41a95255bd1f85d73dd4cf94 (patch)
tree3694c31977b5d1a1762a9ee5aa00c1df57ac3cb9
parent13132dd361c8c5b5753983d5186cf54f689d90f9 (diff)
Upstream release v3.11.0v3.11.0
-rw-r--r--CMakeLists.txt49
-rw-r--r--README.md2
-rw-r--r--cmake/download_test_data.cmake2
-rw-r--r--cmake/test.cmake273
-rw-r--r--meson.build2
-rw-r--r--single_include/nlohmann/json.hpp4866
-rw-r--r--single_include/nlohmann/json_fwd.hpp16
7 files changed, 3879 insertions, 1331 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b93c6e4..fd5c2bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1)
## PROJECT
## name and version
##
-project(nlohmann_json VERSION 3.10.5 LANGUAGES CXX)
+project(nlohmann_json VERSION 3.11.0 LANGUAGES CXX)
##
## MAIN_PROJECT CHECK
@@ -19,6 +19,7 @@ endif()
## INCLUDE
##
##
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
include(ExternalProject)
##
@@ -30,16 +31,25 @@ if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif ()
-option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${MAIN_PROJECT})
-option(JSON_CI "Enable CI build targets." OFF)
-option(JSON_Diagnostics "Use extended diagnostic messages." OFF)
-option(JSON_ImplicitConversions "Enable implicit conversions." ON)
-option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
-option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
-option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
+# VERSION_GREATER_EQUAL is not available in CMake 3.1
+if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13))
+ set(JSON_BuildTests_INIT ON)
+else()
+ set(JSON_BuildTests_INIT OFF)
+endif()
+option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${JSON_BuildTests_INIT})
+option(JSON_CI "Enable CI build targets." OFF)
+option(JSON_Diagnostics "Use extended diagnostic messages." OFF)
+option(JSON_GlobalUDLs "Place use-defined string literals in the global namespace." ON)
+option(JSON_ImplicitConversions "Enable implicit conversions." ON)
+option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF)
+option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF)
+option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
+option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
+option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
if (JSON_CI)
- include(cmake/ci.cmake)
+ include(ci)
endif ()
##
@@ -48,7 +58,7 @@ endif ()
include(GNUInstallDirs)
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
-set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "")
+set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
@@ -56,7 +66,7 @@ set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
-set(NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+set(NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig")
if (JSON_MultipleHeaders)
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
@@ -70,6 +80,14 @@ if (NOT JSON_ImplicitConversions)
message(STATUS "Implicit conversions are disabled")
endif()
+if (JSON_DisableEnumSerialization)
+ message(STATUS "Enum integer serialization is disabled")
+endif()
+
+if (JSON_LegacyDiscardedValueComparison)
+ message(STATUS "Legacy discarded value comparison enabled")
+endif()
+
if (JSON_Diagnostics)
message(STATUS "Diagnostics enabled")
endif()
@@ -93,8 +111,11 @@ endif()
target_compile_definitions(
${NLOHMANN_JSON_TARGET_NAME}
INTERFACE
- JSON_USE_IMPLICIT_CONVERSIONS=$<BOOL:${JSON_ImplicitConversions}>
- JSON_DIAGNOSTICS=$<BOOL:${JSON_Diagnostics}>
+ $<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:JSON_USE_GLOBAL_UDLS=0>
+ $<$<NOT:$<BOOL:${JSON_ImplicitConversions}>>:JSON_USE_IMPLICIT_CONVERSIONS=0>
+ $<$<BOOL:${JSON_DisableEnumSerialization}>:JSON_DISABLE_ENUM_SERIALIZATION=1>
+ $<$<BOOL:${JSON_Diagnostics}>:JSON_DIAGNOSTICS=1>
+ $<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
)
target_include_directories(
@@ -129,7 +150,7 @@ CONFIGURE_FILE(
if (JSON_BuildTests)
include(CTest)
enable_testing()
- add_subdirectory(test)
+ add_subdirectory(tests)
endif()
##
diff --git a/README.md b/README.md
index 82e83cc..7ea8a82 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ FetchContent_Declare(json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
GIT_PROGRESS TRUE
GIT_SHALLOW TRUE
- GIT_TAG v3.10.5)
+ GIT_TAG v3.11.0)
FetchContent_MakeAvailable(json)
diff --git a/cmake/download_test_data.cmake b/cmake/download_test_data.cmake
index f516a7c..1bb998d 100644
--- a/cmake/download_test_data.cmake
+++ b/cmake/download_test_data.cmake
@@ -1,5 +1,5 @@
set(JSON_TEST_DATA_URL https://github.com/nlohmann/json_test_data)
-set(JSON_TEST_DATA_VERSION 3.0.0)
+set(JSON_TEST_DATA_VERSION 3.1.0)
# if variable is set, use test data from given directory rather than downloading them
if(JSON_TestDataDirectory)
diff --git a/cmake/test.cmake b/cmake/test.cmake
new file mode 100644
index 0000000..bb840c6
--- /dev/null
+++ b/cmake/test.cmake
@@ -0,0 +1,273 @@
+set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE})
+
+#############################################################################
+# download test data
+#############################################################################
+
+include(download_test_data)
+
+# test fixture to download test data
+add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
+ --target download_test_data
+)
+set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA)
+
+if(JSON_Valgrind)
+ find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
+ message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
+ set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
+ separate_arguments(memcheck_command)
+endif()
+
+#############################################################################
+# detect standard support
+#############################################################################
+
+# C++11 is the minimum required
+set(compiler_supports_cpp_11 TRUE)
+
+foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
+ if (${feature} STREQUAL cxx_std_14)
+ set(compiler_supports_cpp_14 TRUE)
+ elseif (${feature} STREQUAL cxx_std_17)
+ set(compiler_supports_cpp_17 TRUE)
+ elseif (${feature} STREQUAL cxx_std_20)
+ set(compiler_supports_cpp_20 TRUE)
+ elseif (${feature} STREQUAL cxx_std_23)
+ set(compiler_supports_cpp_23 TRUE)
+ endif()
+endforeach()
+
+#############################################################################
+# test functions
+#############################################################################
+
+#############################################################################
+# json_test_set_test_options(
+# all|<tests>
+# [CXX_STANDARDS all|<args>...]
+# [COMPILE_DEFINITIONS <args>...]
+# [COMPILE_FEATURES <args>...]
+# [COMPILE_OPTIONS <args>...]
+# [LINK_LIBRARIES <args>...]
+# [LINK_OPTIONS <args>...]
+# [TEST_PROPERTIES <args>...])
+#
+# Supply test- and standard-specific build settings and/or test properties.
+# Specify multiple tests using a list e.g., "test-foo;test-bar".
+#
+# Must be called BEFORE the test is created.
+#############################################################################
+
+function(json_test_set_test_options tests)
+ cmake_parse_arguments(args "" ""
+ "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES"
+ ${ARGN})
+
+ if(NOT args_CXX_STANDARDS)
+ set(args_CXX_STANDARDS "all")
+ endif()
+
+ foreach(test ${tests})
+ if("${test}" STREQUAL "all")
+ set(test "")
+ endif()
+
+ foreach(cxx_standard ${args_CXX_STANDARDS})
+ if("${cxx_standard}" STREQUAL "all")
+ if("${test}" STREQUAL "")
+ message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}")
+ endif()
+ set(test_interface _json_test_interface_${test})
+ else()
+ set(test_interface _json_test_interface_${test}_cpp_${cxx_standard})
+ endif()
+
+ if(NOT TARGET ${test_interface})
+ add_library(${test_interface} INTERFACE)
+ endif()
+
+ target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS})
+ target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES})
+ target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS})
+ target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES})
+ target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS})
+ #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}")
+ set_property(DIRECTORY PROPERTY
+ ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}"
+ )
+ endforeach()
+ endforeach()
+endfunction()
+
+# for internal use by _json_test_add_test()
+function(_json_test_apply_test_properties test_target properties_target)
+ #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES)
+ get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES)
+ if(test_properties)
+ set_tests_properties(${test_target} PROPERTIES ${test_properties})
+ endif()
+endfunction()
+
+# for internal use by json_test_add_test_for()
+function(_json_test_add_test test_name file main cxx_standard)
+ set(test_target ${test_name}_cpp${cxx_standard})
+
+ if(TARGET ${test_target})
+ message(FATAL_ERROR "Target ${test_target} has already been added.")
+ endif()
+
+ add_executable(${test_target} ${file})
+ target_link_libraries(${test_target} PRIVATE ${main})
+
+ # set and require C++ standard
+ set_target_properties(${test_target} PROPERTIES
+ CXX_STANDARD ${cxx_standard}
+ CXX_STANDARD_REQUIRED ON
+ )
+
+ # apply standard-specific build settings
+ if(TARGET _json_test_interface__cpp_${cxx_standard})
+ target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard})
+ endif()
+
+ # apply test-specific build settings
+ if(TARGET _json_test_interface_${test_name})
+ target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name})
+ endif()
+
+ # apply test- and standard-specific build settings
+ if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
+ target_link_libraries(${test_target} PRIVATE
+ _json_test_interface_${test_name}_cpp_${cxx_standard}
+ )
+ endif()
+
+ if (JSON_FastTests)
+ add_test(NAME ${test_target}
+ COMMAND ${test_target} ${DOCTEST_TEST_FILTER}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+ else()
+ add_test(NAME ${test_target}
+ COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+ endif()
+ set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
+
+ # apply standard-specific test properties
+ if(TARGET _json_test_interface__cpp_${cxx_standard})
+ _json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard})
+ endif()
+
+ # apply test-specific test properties
+ if(TARGET _json_test_interface_${test_name})
+ _json_test_apply_test_properties(${test_target} _json_test_interface_${test_name})
+ endif()
+
+ # apply test- and standard-specific test properties
+ if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
+ _json_test_apply_test_properties(${test_target}
+ _json_test_interface_${test_name}_cpp_${cxx_standard}
+ )
+ endif()
+
+ if(JSON_Valgrind)
+ add_test(NAME ${test_target}_valgrind
+ COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+ set_tests_properties(${test_target}_valgrind PROPERTIES
+ LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
+ )
+ endif()
+endfunction()
+
+#############################################################################
+# json_test_add_test_for(
+# <file>
+# [NAME <name>]
+# MAIN <main>
+# [CXX_STANDARDS <version_number>...] [FORCE])
+#
+# Given a <file> unit-foo.cpp, produces
+#
+# test-foo_cpp<version_number>
+#
+# if C++ standard <version_number> is supported by the compiler and the
+# source file contains JSON_HAS_CPP_<version_number>.
+# Use NAME <name> to override the filename-derived test name.
+# Use FORCE to create the test regardless of the file containing
+# JSON_HAS_CPP_<version_number>.
+# Test targets are linked against <main>.
+# CXX_STANDARDS defaults to "11".
+#############################################################################
+
+function(json_test_add_test_for file)
+ cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN})
+
+ if("${args_MAIN}" STREQUAL "")
+ message(FATAL_ERROR "Required argument MAIN <main> missing.")
+ endif()
+
+ if("${args_NAME}" STREQUAL "")
+ get_filename_component(file_basename ${file} NAME_WE)
+ string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename})
+ else()
+ set(test_name ${args_NAME})
+ if(NOT test_name MATCHES "test-[^$]+")
+ message(FATAL_ERROR "Test name must start with 'test-'.")
+ endif()
+ endif()
+
+ if("${args_CXX_STANDARDS}" STREQUAL "")
+ set(args_CXX_STANDARDS 11)
+ endif()
+
+ file(READ ${file} file_content)
+ foreach(cxx_standard ${args_CXX_STANDARDS})
+ if(NOT compiler_supports_cpp_${cxx_standard})
+ continue()
+ endif()
+
+ # add unconditionally if C++11 (default) or forced
+ if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE))
+ string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found)
+ if(${has_cpp_found} EQUAL -1)
+ continue()
+ endif()
+ endif()
+
+ _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard})
+ endforeach()
+endfunction()
+
+#############################################################################
+# json_test_should_build_32bit_test(
+# <build_32bit_var> <build_32bit_only_var> <input>)
+#
+# Check if the 32bit unit test should be built based on the value of <input>
+# and store the result in the variables <build_32bit_var> and
+# <build_32bit_only_var>.
+#############################################################################
+
+function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input)
+ set(${build_32bit_only_var} OFF PARENT_SCOPE)
+ string(TOUPPER "${input}" ${build_32bit_var})
+ if("${${build_32bit_var}}" STREQUAL AUTO)
+ # check if compiler is targeting 32bit by default
+ include(CheckTypeSize)
+ check_type_size("size_t" sizeof_size_t LANGUAGE CXX)
+ if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4)
+ message(STATUS "Auto-enabling 32bit unit test.")
+ set(${build_32bit_var} ON)
+ else()
+ set(${build_32bit_var} OFF)
+ endif()
+ elseif("${${build_32bit_var}}" STREQUAL ONLY)
+ set(${build_32bit_only_var} ON PARENT_SCOPE)
+ endif()
+
+ set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE)
+endfunction()
diff --git a/meson.build b/meson.build
index d61dc25..3cd7dc8 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
project('nlohmann_json',
'cpp',
- version : '3.10.5',
+ version : '3.11.0',
license : 'MIT',
)
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index cb27e05..8a8a0a0 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -1,31 +1,10 @@
-/*
- __ _____ _____ _____
- __| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 3.10.5
-|_____|_____|_____|_|___| https://github.com/nlohmann/json
-
-Licensed under the MIT License <http://opensource.org/licenses/MIT>.
-SPDX-License-Identifier: MIT
-Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
/****************************************************************************\
* Note on documentation: The source files contain links to the online *
@@ -33,16 +12,12 @@ SOFTWARE.
* contains the most recent documentation and should also be applicable to *
* previous versions; documentation for deprecated functions is not *
* removed, but marked deprecated. See "Generate documentation" section in *
- * file doc/README.md. *
+ * file docs/README.md. *
\****************************************************************************/
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
#define INCLUDE_NLOHMANN_JSON_HPP_
-#define NLOHMANN_JSON_VERSION_MAJOR 3
-#define NLOHMANN_JSON_VERSION_MINOR 10
-#define NLOHMANN_JSON_VERSION_PATCH 5
-
#include <algorithm> // all_of, find, for_each
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
#include <functional> // hash, less
@@ -58,12 +33,108 @@ SOFTWARE.
#include <vector> // vector
// #include <nlohmann/adl_serializer.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
-#include <type_traits>
#include <utility>
+// #include <nlohmann/detail/abi_macros.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// This file contains all macro definitions affecting or depending on the ABI
+
+#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
+ #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
+ #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 0
+ #warning "Already included a different version of the library!"
+ #endif
+ #endif
+#endif
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
+#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
+#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
+
+#ifndef JSON_DIAGNOSTICS
+ #define JSON_DIAGNOSTICS 0
+#endif
+
+#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+ #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
+#endif
+
+#if JSON_DIAGNOSTICS
+ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
+#else
+ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
+#endif
+
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+ #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
+#else
+ #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
+#endif
+
+#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \
+ json_v ## major ## _ ## minor ## _ ## patch
+#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \
+ NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch)
+
+#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c
+#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \
+ NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c)
+
+#define NLOHMANN_JSON_ABI_STRING \
+ NLOHMANN_JSON_ABI_CONCAT( \
+ NLOHMANN_JSON_ABI_PREFIX( \
+ NLOHMANN_JSON_VERSION_MAJOR, \
+ NLOHMANN_JSON_VERSION_MINOR, \
+ NLOHMANN_JSON_VERSION_PATCH), \
+ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
+ NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
+
+#ifndef NLOHMANN_JSON_NAMESPACE
+ #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING
+#endif
+
+#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
+#define NLOHMANN_JSON_NAMESPACE_BEGIN \
+ namespace nlohmann \
+ { \
+ inline namespace NLOHMANN_JSON_ABI_STRING \
+ {
+#endif
+
+#ifndef NLOHMANN_JSON_NAMESPACE_END
+#define NLOHMANN_JSON_NAMESPACE_END \
+ } /* namespace (abi_string) */ \
+ } /* namespace nlohmann */
+#endif
+
// #include <nlohmann/detail/conversions/from_json.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // transform
@@ -79,14 +150,31 @@ SOFTWARE.
#include <valarray> // valarray
// #include <nlohmann/detail/exceptions.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#include <cstddef> // nullptr_t
#include <exception> // exception
#include <stdexcept> // runtime_error
#include <string> // to_string
#include <vector> // vector
// #include <nlohmann/detail/value_t.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <array> // array
@@ -94,102 +182,130 @@ SOFTWARE.
#include <cstdint> // uint8_t
#include <string> // string
-namespace nlohmann
-{
+// #include <nlohmann/detail/macro_scope.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <utility> // declval, pair
+// #include <nlohmann/detail/meta/detected.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
-///////////////////////////
-// JSON type enumeration //
-///////////////////////////
-/*!
-@brief the JSON type enumeration
+template<typename ...Ts> struct make_void
+{
+ using type = void;
+};
+template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
-This enumeration collects the different JSON types. It is internally used to
-distinguish the stored values, and the functions @ref basic_json::is_null(),
-@ref basic_json::is_object(), @ref basic_json::is_array(),
-@ref basic_json::is_string(), @ref basic_json::is_boolean(),
-@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
-@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
-@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
-@ref basic_json::is_structured() rely on it.
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
-@note There are three enumeration entries (number_integer, number_unsigned, and
-number_float), because the library distinguishes these three types for numbers:
-@ref basic_json::number_unsigned_t is used for unsigned integers,
-@ref basic_json::number_integer_t is used for signed integers, and
-@ref basic_json::number_float_t is used for floating-point numbers or to
-approximate integers which do not fit in the limits of their respective type.
-@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
-value with the default value for a given type
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
-@since version 1.0.0
-*/
-enum class value_t : std::uint8_t
+// https://en.cppreference.com/w/cpp/experimental/is_detected
+struct nonesuch
{
- null, ///< null value
- object, ///< object (unordered set of name/value pairs)
- array, ///< array (ordered collection of values)
- string, ///< string value
- boolean, ///< boolean value
- number_integer, ///< number value (signed integer)
- number_unsigned, ///< number value (unsigned integer)
- number_float, ///< number value (floating-point)
- binary, ///< binary array (ordered collection of bytes)
- discarded ///< discarded by the parser callback function
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ nonesuch(nonesuch const&&) = delete;
+ void operator=(nonesuch const&) = delete;
+ void operator=(nonesuch&&) = delete;
};
-/*!
-@brief comparison operator for JSON types
-
-Returns an ordering that is similar to Python:
-- order: null < boolean < number < object < array < string < binary
-- furthermore, each type is not smaller than itself
-- discarded values are not comparable
-- binary is represented as a b"" string in python and directly comparable to a
- string; however, making a binary array directly comparable with a string would
- be surprising behavior in a JSON file.
+template<class Default,
+ class AlwaysVoid,
+ template<class...> class Op,
+ class... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
-@since version 1.0.0
-*/
-inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+template<class Default, template<class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
- static constexpr std::array<std::uint8_t, 9> order = {{
- 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
- 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
- 6 /* binary */
- }
- };
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
- const auto l_index = static_cast<std::size_t>(lhs);
- const auto r_index = static_cast<std::size_t>(rhs);
- return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
-}
-} // namespace detail
-} // namespace nlohmann
+template<template<class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
-// #include <nlohmann/detail/string_escape.hpp>
+template<template<class...> class Op, class... Args>
+struct is_detected_lazy : is_detected<Op, Args...> { };
+template<template<class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
-#include <string>
-// #include <nlohmann/detail/macro_scope.hpp>
+template<class Default, template<class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+template<class Expected, template<class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template<class To, template<class...> class Op, class... Args>
+using is_detected_convertible =
+ std::is_convertible<detected_t<Op, Args...>, To>;
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
-#include <utility> // declval, pair
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
+// SPDX-License-Identifier: MIT
+
/* Hedley - https://nemequ.github.io/hedley
* Created by Evan Nemerson <evan@nemerson.com>
- *
- * To the extent possible under law, the author(s) have dedicated all
- * copyright and related and neighboring rights to this software to
- * the public domain worldwide. This software is distributed without
- * any warranty.
- *
- * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
- * SPDX-License-Identifier: CC0-1.0
*/
#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
@@ -2223,86 +2339,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP
#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
-// #include <nlohmann/detail/meta/detected.hpp>
-
-
-#include <type_traits>
-
-// #include <nlohmann/detail/meta/void_t.hpp>
-
-
-namespace nlohmann
-{
-namespace detail
-{
-template<typename ...Ts> struct make_void
-{
- using type = void;
-};
-template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
-} // namespace detail
-} // namespace nlohmann
-
-
-// https://en.cppreference.com/w/cpp/experimental/is_detected
-namespace nlohmann
-{
-namespace detail
-{
-struct nonesuch
-{
- nonesuch() = delete;
- ~nonesuch() = delete;
- nonesuch(nonesuch const&) = delete;
- nonesuch(nonesuch const&&) = delete;
- void operator=(nonesuch const&) = delete;
- void operator=(nonesuch&&) = delete;
-};
-
-template<class Default,
- class AlwaysVoid,
- template<class...> class Op,
- class... Args>
-struct detector
-{
- using value_t = std::false_type;
- using type = Default;
-};
-
-template<class Default, template<class...> class Op, class... Args>
-struct detector<Default, void_t<Op<Args...>>, Op, Args...>
-{
- using value_t = std::true_type;
- using type = Op<Args...>;
-};
-
-template<template<class...> class Op, class... Args>
-using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
-
-template<template<class...> class Op, class... Args>
-struct is_detected_lazy : is_detected<Op, Args...> { };
-
-template<template<class...> class Op, class... Args>
-using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
-
-template<class Default, template<class...> class Op, class... Args>
-using detected_or = detector<Default, void, Op, Args...>;
-
-template<class Default, template<class...> class Op, class... Args>
-using detected_or_t = typename detected_or<Default, Op, Args...>::type;
-template<class Expected, template<class...> class Op, class... Args>
-using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
-
-template<class To, template<class...> class Op, class... Args>
-using is_detected_convertible =
- std::is_convertible<detected_t<Op, Args...>, To>;
-} // namespace detail
-} // namespace nlohmann
+// This file contains all internal macro definitions (except those affecting ABI)
+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
+// #include <nlohmann/detail/abi_macros.hpp>
-// This file contains all internal macro definitions
-// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
// exclude unsupported compilers
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
@@ -2334,6 +2376,12 @@ using is_detected_convertible =
#define JSON_HAS_CPP_11
#endif
+#ifdef __has_include
+ #if __has_include(<version>)
+ #include <version>
+ #endif
+#endif
+
#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
#ifdef JSON_HAS_CPP_17
#if defined(__cpp_lib_filesystem)
@@ -2367,7 +2415,7 @@ using is_detected_convertible =
#endif
// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
- #if defined(_MSC_VER) && _MSC_VER < 1940
+ #if defined(_MSC_VER) && _MSC_VER < 1914
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
@@ -2394,6 +2442,38 @@ using is_detected_convertible =
#define JSON_HAS_FILESYSTEM 0
#endif
+#ifndef JSON_HAS_THREE_WAY_COMPARISON
+ #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
+ && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
+ #define JSON_HAS_THREE_WAY_COMPARISON 1
+ #else
+ #define JSON_HAS_THREE_WAY_COMPARISON 0
+ #endif
+#endif
+
+#ifndef JSON_HAS_RANGES
+ // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
+ #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
+ #define JSON_HAS_RANGES 0
+ #elif defined(__cpp_lib_ranges)
+ #define JSON_HAS_RANGES 1
+ #else
+ #define JSON_HAS_RANGES 0
+ #endif
+#endif
+
+#ifdef JSON_HAS_CPP_17
+ #define JSON_INLINE_VARIABLE inline
+#else
+ #define JSON_INLINE_VARIABLE
+#endif
+
+#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
+ #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+ #define JSON_NO_UNIQUE_ADDRESS
+#endif
+
// disable documentation warnings on clang
#if defined(__clang__)
#pragma clang diagnostic push
@@ -2631,6 +2711,7 @@ using is_detected_convertible =
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
+#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
/*!
@brief macro
@@ -2641,6 +2722,10 @@ using is_detected_convertible =
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__)) } \
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__)) }
+#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
+ 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__)) } \
+ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
+
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@@ -2650,6 +2735,10 @@ using is_detected_convertible =
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__)) } \
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__)) }
+#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
+ 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__)) } \
+ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
+
// inspired from https://stackoverflow.com/a/26745591
// allows to call any std function as if (e.g. with begin):
@@ -2699,13 +2788,132 @@ using is_detected_convertible =
#define JSON_EXPLICIT explicit
#endif
-#ifndef JSON_DIAGNOSTICS
- #define JSON_DIAGNOSTICS 0
+#ifndef JSON_DISABLE_ENUM_SERIALIZATION
+ #define JSON_DISABLE_ENUM_SERIALIZATION 0
+#endif
+
+#ifndef JSON_USE_GLOBAL_UDLS
+ #define JSON_USE_GLOBAL_UDLS 0
+#endif
+
+#if JSON_HAS_THREE_WAY_COMPARISON
+ #include <compare> // partial_ordering
+#endif
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
+@since version 1.0.0
+*/
+enum class value_t : std::uint8_t
+{
+ null, ///< null value
+ object, ///< object (unordered set of name/value pairs)
+ array, ///< array (ordered collection of values)
+ string, ///< string value
+ boolean, ///< boolean value
+ number_integer, ///< number value (signed integer)
+ number_unsigned, ///< number value (unsigned integer)
+ number_float, ///< number value (floating-point)
+ binary, ///< binary array (ordered collection of bytes)
+ discarded ///< discarded by the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string < binary
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+- binary is represented as a b"" string in python and directly comparable to a
+ string; however, making a binary array directly comparable with a string would
+ be surprising behavior in a JSON file.
+
+@since version 1.0.0
+*/
+#if JSON_HAS_THREE_WAY_COMPARISON
+ inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
+#else
+ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
#endif
+{
+ static constexpr std::array<std::uint8_t, 9> order = {{
+ 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+ 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
+ 6 /* binary */
+ }
+ };
+ const auto l_index = static_cast<std::size_t>(lhs);
+ const auto r_index = static_cast<std::size_t>(rhs);
+#if JSON_HAS_THREE_WAY_COMPARISON
+ if (l_index < order.size() && r_index < order.size())
+ {
+ return order[l_index] <=> order[r_index]; // *NOPAD*
+ }
+ return std::partial_ordering::unordered;
+#else
+ return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
+#endif
+}
-namespace nlohmann
+// GCC selects the built-in operator< over an operator rewritten from
+// a user-defined spaceship operator
+// Clang, MSVC, and ICC select the rewritten candidate
+// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
+#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
{
+ return std::is_lt(lhs <=> rhs); // *NOPAD*
+}
+#endif
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/string_escape.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -2722,12 +2930,13 @@ enforced with an assertion.**
@since version 2.0.0
*/
-inline void replace_substring(std::string& s, const std::string& f,
- const std::string& t)
+template<typename StringType>
+inline void replace_substring(StringType& s, const StringType& f,
+ const StringType& t)
{
JSON_ASSERT(!f.empty());
for (auto pos = s.find(f); // find first occurrence of f
- pos != std::string::npos; // make sure f was found
+ pos != StringType::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t, and
pos = s.find(f, pos + t.size())) // find next occurrence of f
{}
@@ -2740,10 +2949,11 @@ inline void replace_substring(std::string& s, const std::string& f,
*
* Note the order of escaping "~" to "~0" and "/" to "~1" is important.
*/
-inline std::string escape(std::string s)
+template<typename StringType>
+inline StringType escape(StringType s)
{
- replace_substring(s, "~", "~0");
- replace_substring(s, "/", "~1");
+ replace_substring(s, StringType{"~"}, StringType{"~0"});
+ replace_substring(s, StringType{"/"}, StringType{"~1"});
return s;
}
@@ -2754,24 +2964,36 @@ inline std::string escape(std::string s)
*
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
*/
-static void unescape(std::string& s)
+template<typename StringType>
+static void unescape(StringType& s)
{
- replace_substring(s, "~1", "/");
- replace_substring(s, "~0", "~");
+ replace_substring(s, StringType{"~1"}, StringType{"/"});
+ replace_substring(s, StringType{"~0"}, StringType{"~"});
}
-} // namespace detail
-} // namespace nlohmann
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/input/position_t.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstddef> // size_t
-namespace nlohmann
-{
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
/// struct to capture the start position of the current token
struct position_t
{
@@ -2789,240 +3011,21 @@ struct position_t
}
};
-} // namespace detail
-} // namespace nlohmann
-
-// #include <nlohmann/detail/macro_scope.hpp>
-
-
-namespace nlohmann
-{
-namespace detail
-{
-////////////////
-// exceptions //
-////////////////
-
-/// @brief general exception of the @ref basic_json class
-/// @sa https://json.nlohmann.me/api/basic_json/exception/
-class exception : public std::exception
-{
- public:
- /// returns the explanatory string
- const char* what() const noexcept override
- {
- return m.what();
- }
-
- /// the id of the exception
- const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
-
- protected:
- JSON_HEDLEY_NON_NULL(3)
- exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
-
- static std::string name(const std::string& ename, int id_)
- {
- return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
- }
-
- template<typename BasicJsonType>
- static std::string diagnostics(const BasicJsonType& leaf_element)
- {
-#if JSON_DIAGNOSTICS
- std::vector<std::string> tokens;
- for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
- {
- switch (current->m_parent->type())
- {
- case value_t::array:
- {
- for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
- {
- if (&current->m_parent->m_value.array->operator[](i) == current)
- {
- tokens.emplace_back(std::to_string(i));
- break;
- }
- }
- break;
- }
-
- case value_t::object:
- {
- for (const auto& element : *current->m_parent->m_value.object)
- {
- if (&element.second == current)
- {
- tokens.emplace_back(element.first.c_str());
- break;
- }
- }
- break;
- }
-
- case value_t::null: // LCOV_EXCL_LINE
- case value_t::string: // LCOV_EXCL_LINE
- case value_t::boolean: // LCOV_EXCL_LINE
- case value_t::number_integer: // LCOV_EXCL_LINE
- case value_t::number_unsigned: // LCOV_EXCL_LINE
- case value_t::number_float: // LCOV_EXCL_LINE
- case value_t::binary: // LCOV_EXCL_LINE
- case value_t::discarded: // LCOV_EXCL_LINE
- default: // LCOV_EXCL_LINE
- break; // LCOV_EXCL_LINE
- }
- }
-
- if (tokens.empty())
- {
- return "";
- }
-
- return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
- [](const std::string & a, const std::string & b)
- {
- return a + "/" + detail::escape(b);
- }) + ") ";
-#else
- static_cast<void>(leaf_element);
- return "";
-#endif
- }
-
- private:
- /// an exception object as storage for error messages
- std::runtime_error m;
-};
-
-/// @brief exception indicating a parse error
-/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
-class parse_error : public exception
-{
- public:
- /*!
- @brief create a parse error exception
- @param[in] id_ the id of the exception
- @param[in] pos the position where the error occurred (or with
- chars_read_total=0 if the position cannot be
- determined)
- @param[in] what_arg the explanatory string
- @return parse_error object
- */
- template<typename BasicJsonType>
- static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("parse_error", id_) + "parse error" +
- position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
- return {id_, pos.chars_read_total, w.c_str()};
- }
-
- template<typename BasicJsonType>
- static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("parse_error", id_) + "parse error" +
- (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
- ": " + exception::diagnostics(context) + what_arg;
- return {id_, byte_, w.c_str()};
- }
-
- /*!
- @brief byte index of the parse error
-
- The byte index of the last read character in the input file.
-
- @note For an input with n bytes, 1 is the index of the first character and
- n+1 is the index of the terminating null byte or the end of file.
- This also holds true when reading a byte vector (CBOR or MessagePack).
- */
- const std::size_t byte;
-
- private:
- parse_error(int id_, std::size_t byte_, const char* what_arg)
- : exception(id_, what_arg), byte(byte_) {}
-
- static std::string position_string(const position_t& pos)
- {
- return " at line " + std::to_string(pos.lines_read + 1) +
- ", column " + std::to_string(pos.chars_read_current_line);
- }
-};
-
-/// @brief exception indicating errors with iterators
-/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
-class invalid_iterator : public exception
-{
- public:
- template<typename BasicJsonType>
- static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
- return {id_, w.c_str()};
- }
-
- private:
- JSON_HEDLEY_NON_NULL(3)
- invalid_iterator(int id_, const char* what_arg)
- : exception(id_, what_arg) {}
-};
-
-/// @brief exception indicating executing a member function with a wrong type
-/// @sa https://json.nlohmann.me/api/basic_json/type_error/
-class type_error : public exception
-{
- public:
- template<typename BasicJsonType>
- static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
- return {id_, w.c_str()};
- }
-
- private:
- JSON_HEDLEY_NON_NULL(3)
- type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
-};
-
-/// @brief exception indicating access out of the defined range
-/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
-class out_of_range : public exception
-{
- public:
- template<typename BasicJsonType>
- static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
- return {id_, w.c_str()};
- }
-
- private:
- JSON_HEDLEY_NON_NULL(3)
- out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
-};
-
-/// @brief exception indicating other library errors
-/// @sa https://json.nlohmann.me/api/basic_json/other_error/
-class other_error : public exception
-{
- public:
- template<typename BasicJsonType>
- static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
- {
- std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
- return {id_, w.c_str()};
- }
-
- private:
- JSON_HEDLEY_NON_NULL(3)
- other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
-};
-
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-FileCopyrightText: 2018 The Abseil Authors
+// SPDX-License-Identifier: MIT
+
#include <cstddef> // size_t
@@ -3032,8 +3035,7 @@ class other_error : public exception
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -3173,25 +3175,25 @@ struct static_const
static constexpr T value{};
};
-template<typename T>
-constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
+#ifndef JSON_HAS_CPP_17
-} // namespace detail
-} // namespace nlohmann
-
-// #include <nlohmann/detail/meta/identity_tag.hpp>
+ template<typename T>
+ constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
+#endif
-namespace nlohmann
-{
-namespace detail
-{
-// dispatching helper struct
-template <class T> struct identity_tag {};
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/type_traits.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <limits> // numeric_limits
@@ -3199,23 +3201,30 @@ template <class T> struct identity_tag {};
#include <utility> // declval
#include <tuple> // tuple
-// #include <nlohmann/detail/macro_scope.hpp>
-
-
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <iterator> // random_access_iterator_tag
+// #include <nlohmann/detail/abi_macros.hpp>
+
// #include <nlohmann/detail/meta/void_t.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
template<typename It, typename = void>
struct iterator_types {};
@@ -3254,104 +3263,135 @@ struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
using pointer = T*;
using reference = T&;
};
-} // namespace detail
-} // namespace nlohmann
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/call_std/begin.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
-} // namespace nlohmann
+
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/call_std/end.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
-} // namespace nlohmann
+
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/meta/detected.hpp>
// #include <nlohmann/json_fwd.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
-#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+ #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
-#include <cstdint> // int64_t, uint64_t
-#include <map> // map
-#include <memory> // allocator
-#include <string> // string
-#include <vector> // vector
+ #include <cstdint> // int64_t, uint64_t
+ #include <map> // map
+ #include <memory> // allocator
+ #include <string> // string
+ #include <vector> // vector
-/*!
-@brief namespace for Niels Lohmann
-@see https://github.com/nlohmann
-@since version 1.0.0
-*/
-namespace nlohmann
-{
-/*!
-@brief default JSONSerializer template argument
+ // #include <nlohmann/detail/abi_macros.hpp>
-This serializer ignores the template arguments and uses ADL
-([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
-for serialization.
-*/
-template<typename T = void, typename SFINAE = void>
-struct adl_serializer;
-
-/// a class to store JSON values
-/// @sa https://json.nlohmann.me/api/basic_json/
-template<template<typename U, typename V, typename... Args> class ObjectType =
- std::map,
- template<typename U, typename... Args> class ArrayType = std::vector,
- class StringType = std::string, class BooleanType = bool,
- class NumberIntegerType = std::int64_t,
- class NumberUnsignedType = std::uint64_t,
- class NumberFloatType = double,
- template<typename U> class AllocatorType = std::allocator,
- template<typename T, typename SFINAE = void> class JSONSerializer =
- adl_serializer,
- class BinaryType = std::vector<std::uint8_t>>
-class basic_json;
-/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
-/// @sa https://json.nlohmann.me/api/json_pointer/
-template<typename BasicJsonType>
-class json_pointer;
+ /*!
+ @brief namespace for Niels Lohmann
+ @see https://github.com/nlohmann
+ @since version 1.0.0
+ */
+ NLOHMANN_JSON_NAMESPACE_BEGIN
-/*!
-@brief default specialization
-@sa https://json.nlohmann.me/api/json/
-*/
-using json = basic_json<>;
+ /*!
+ @brief default JSONSerializer template argument
-/// @brief a minimal map-like container that preserves insertion order
-/// @sa https://json.nlohmann.me/api/ordered_map/
-template<class Key, class T, class IgnoredLess, class Allocator>
-struct ordered_map;
+ This serializer ignores the template arguments and uses ADL
+ ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+ for serialization.
+ */
+ template<typename T = void, typename SFINAE = void>
+ struct adl_serializer;
+
+ /// a class to store JSON values
+ /// @sa https://json.nlohmann.me/api/basic_json/
+ template<template<typename U, typename V, typename... Args> class ObjectType =
+ std::map,
+ template<typename U, typename... Args> class ArrayType = std::vector,
+ class StringType = std::string, class BooleanType = bool,
+ class NumberIntegerType = std::int64_t,
+ class NumberUnsignedType = std::uint64_t,
+ class NumberFloatType = double,
+ template<typename U> class AllocatorType = std::allocator,
+ template<typename T, typename SFINAE = void> class JSONSerializer =
+ adl_serializer,
+ class BinaryType = std::vector<std::uint8_t>>
+ class basic_json;
+
+ /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
+ /// @sa https://json.nlohmann.me/api/json_pointer/
+ template<typename BasicJsonType>
+ class json_pointer;
+
+ /*!
+ @brief default specialization
+ @sa https://json.nlohmann.me/api/json/
+ */
+ using json = basic_json<>;
-/// @brief specialization that maintains the insertion order of object keys
-/// @sa https://json.nlohmann.me/api/ordered_json/
-using ordered_json = basic_json<nlohmann::ordered_map>;
+ /// @brief a minimal map-like container that preserves insertion order
+ /// @sa https://json.nlohmann.me/api/ordered_map/
+ template<class Key, class T, class IgnoredLess, class Allocator>
+ struct ordered_map;
-} // namespace nlohmann
+ /// @brief specialization that maintains the insertion order of object keys
+ /// @sa https://json.nlohmann.me/api/ordered_json/
+ using ordered_json = basic_json<nlohmann::ordered_map>;
+
+ NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief detail namespace with internal helper functions
@@ -3362,6 +3402,7 @@ implementations of some @ref basic_json methods, and meta-programming helpers.
*/
namespace detail
{
+
/////////////
// helpers //
/////////////
@@ -3380,6 +3421,16 @@ template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+// used by exceptions create() member functions
+// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
+// false_type otherwise
+template<typename BasicJsonContext>
+struct is_basic_json_context :
+ std::integral_constant < bool,
+ is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
+ || std::is_same<BasicJsonContext, std::nullptr_t>::value >
+{};
+
//////////////////////
// json_ref helpers //
//////////////////////
@@ -3481,6 +3532,24 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
T>::value;
};
+template<typename T>
+using detect_key_compare = typename T::key_compare;
+
+template<typename T>
+struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
+
+// obtains the actual object key comparator
+template<typename BasicJsonType>
+struct actual_object_comparator
+{
+ using object_t = typename BasicJsonType::object_t;
+ using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
+ using type = typename std::conditional < has_key_compare<object_t>::value,
+ typename object_t::key_compare, object_comparator_t>::type;
+};
+
+template<typename BasicJsonType>
+using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
///////////////////
// is_ functions //
@@ -3488,10 +3557,10 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
// https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct conjunction : std::true_type { };
-template<class B1> struct conjunction<B1> : B1 { };
-template<class B1, class... Bn>
-struct conjunction<B1, Bn...>
-: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+template<class B> struct conjunction<B> : B { };
+template<class B, class... Bn>
+struct conjunction<B, Bn...>
+: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
// https://en.cppreference.com/w/cpp/types/negation
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
@@ -3655,9 +3724,18 @@ struct is_compatible_string_type
template<typename BasicJsonType, typename ConstructibleStringType>
struct is_constructible_string_type
{
+ // launder type through decltype() to fix compilation failure on ICPC
+#ifdef __INTEL_COMPILER
+ using laundered_type = decltype(std::declval<ConstructibleStringType>());
+#else
+ using laundered_type = ConstructibleStringType;
+#endif
+
static constexpr auto value =
- is_constructible<ConstructibleStringType,
- typename BasicJsonType::string_t>::value;
+ conjunction <
+ is_constructible<laundered_type, typename BasicJsonType::string_t>,
+ is_detected_exact<typename BasicJsonType::string_t::value_type,
+ value_type_t, laundered_type >>::value;
};
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
@@ -3775,6 +3853,81 @@ struct is_constructible_tuple : std::false_type {};
template<typename T1, typename... Args>
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
+template<typename BasicJsonType, typename T>
+struct is_json_iterator_of : std::false_type {};
+
+template<typename BasicJsonType>
+struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
+
+template<typename BasicJsonType>
+struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
+{};
+
+// checks if a given type T is a template specialization of Primary
+template<template <typename...> class Primary, typename T>
+struct is_specialization_of : std::false_type {};
+
+template<template <typename...> class Primary, typename... Args>
+struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
+
+template<typename T>
+using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
+
+// checks if A and B are comparable using Compare functor
+template<typename Compare, typename A, typename B, typename = void>
+struct is_comparable : std::false_type {};
+
+template<typename Compare, typename A, typename B>
+struct is_comparable<Compare, A, B, void_t<
+decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
+decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
+>> : std::true_type {};
+
+template<typename T>
+using detect_is_transparent = typename T::is_transparent;
+
+// type trait to check if KeyType can be used as object key (without a BasicJsonType)
+// see is_usable_as_basic_json_key_type below
+template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
+ bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
+using is_usable_as_key_type = typename std::conditional <
+ is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
+ && !(ExcludeObjectKeyType && std::is_same<KeyType,
+ ObjectKeyType>::value)
+ && (!RequireTransparentComparator
+ || is_detected <detect_is_transparent, Comparator>::value)
+ && !is_json_pointer<KeyType>::value,
+ std::true_type,
+ std::false_type >::type;
+
+// type trait to check if KeyType can be used as object key
+// true if:
+// - KeyType is comparable with BasicJsonType::object_t::key_type
+// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
+// - the comparator is transparent or RequireTransparentComparator is false
+// - KeyType is not a JSON iterator or json_pointer
+template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
+ bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
+using is_usable_as_basic_json_key_type = typename std::conditional <
+ is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
+ typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
+ RequireTransparentComparator, ExcludeObjectKeyType>::value
+ && !is_json_iterator_of<BasicJsonType, KeyType>::value,
+ std::true_type,
+ std::false_type >::type;
+
+template<typename ObjectType, typename KeyType>
+using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
+
+// type trait to check if object_t has an erase() member functions accepting KeyType
+template<typename BasicJsonType, typename KeyType>
+using has_erase_with_key_type = typename std::conditional <
+ is_detected <
+ detect_erase_with_key_type,
+ typename BasicJsonType::object_t, KeyType >::value,
+ std::true_type,
+ std::false_type >::type;
+
// a naive helper to check if a type is an ordered_map (exploits the fact that
// ordered_map inherits capacity() from std::vector)
template <typename T>
@@ -3806,36 +3959,564 @@ T conditional_static_cast(U value)
return value;
}
+template<typename... Types>
+using all_integral = conjunction<std::is_integral<Types>...>;
+
+template<typename... Types>
+using all_signed = conjunction<std::is_signed<Types>...>;
+
+template<typename... Types>
+using all_unsigned = conjunction<std::is_unsigned<Types>...>;
+
+// there's a disjunction trait in another PR; replace when merged
+template<typename... Types>
+using same_sign = std::integral_constant < bool,
+ all_signed<Types...>::value || all_unsigned<Types...>::value >;
+
+template<typename OfType, typename T>
+using never_out_of_range = std::integral_constant < bool,
+ (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
+ || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
+
+template<typename OfType, typename T,
+ bool OfTypeSigned = std::is_signed<OfType>::value,
+ bool TSigned = std::is_signed<T>::value>
+struct value_in_range_of_impl2;
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, false, false>
+{
+ static constexpr bool test(T val)
+ {
+ using CommonType = typename std::common_type<OfType, T>::type;
+ return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+ }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, true, false>
+{
+ static constexpr bool test(T val)
+ {
+ using CommonType = typename std::common_type<OfType, T>::type;
+ return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+ }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, false, true>
+{
+ static constexpr bool test(T val)
+ {
+ using CommonType = typename std::common_type<OfType, T>::type;
+ return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+ }
+};
+
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl2<OfType, T, true, true>
+{
+ static constexpr bool test(T val)
+ {
+ using CommonType = typename std::common_type<OfType, T>::type;
+ return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
+ && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
+ }
+};
+
+template<typename OfType, typename T,
+ bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
+ typename = detail::enable_if_t<all_integral<OfType, T>::value>>
+struct value_in_range_of_impl1;
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl1<OfType, T, false>
+{
+ static constexpr bool test(T val)
+ {
+ return value_in_range_of_impl2<OfType, T>::test(val);
+ }
+};
+
+template<typename OfType, typename T>
+struct value_in_range_of_impl1<OfType, T, true>
+{
+ static constexpr bool test(T /*val*/)
+ {
+ return true;
+ }
+};
+
+template<typename OfType, typename T>
+inline constexpr bool value_in_range_of(T val)
+{
+ return value_in_range_of_impl1<OfType, T>::test(val);
+}
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
-// #include <nlohmann/detail/value_t.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+#include <cstring> // strlen
+#include <string> // string
+#include <utility> // forward
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+inline std::size_t concat_length()
+{
+ return 0;
+}
+
+template<typename... Args>
+inline std::size_t concat_length(const char* cstr, Args&& ... rest);
+
+template<typename StringType, typename... Args>
+inline std::size_t concat_length(const StringType& str, Args&& ... rest);
+
+template<typename... Args>
+inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
+{
+ return 1 + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename... Args>
+inline std::size_t concat_length(const char* cstr, Args&& ... rest)
+{
+ // cppcheck-suppress ignoredReturnValue
+ return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename StringType, typename... Args>
+inline std::size_t concat_length(const StringType& str, Args&& ... rest)
+{
+ return str.size() + concat_length(std::forward<Args>(rest)...);
+}
+
+template<typename OutStringType>
+inline void concat_into(OutStringType& /*out*/)
+{}
+
+template<typename StringType, typename Arg>
+using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
+
+template<typename StringType, typename Arg>
+using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
+
+template<typename StringType, typename Arg>
+using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && !detect_string_can_append_op<OutStringType, Arg>::value
+ && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && !detect_string_can_append_op<OutStringType, Arg>::value
+ && !detect_string_can_append_iter<OutStringType, Arg>::value
+ && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template<typename OutStringType, typename Arg, typename... Args,
+ enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
+{
+ out.append(std::forward<Arg>(arg));
+ concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && detect_string_can_append_op<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
+{
+ out += std::forward<Arg>(arg);
+ concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && !detect_string_can_append_op<OutStringType, Arg>::value
+ && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+ out.append(arg.begin(), arg.end());
+ concat_into(out, std::forward<Args>(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
+ && !detect_string_can_append_op<OutStringType, Arg>::value
+ && !detect_string_can_append_iter<OutStringType, Arg>::value
+ && detect_string_can_append_data<OutStringType, Arg>::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+ out.append(arg.data(), arg.size());
+ concat_into(out, std::forward<Args>(rest)...);
+}
+
+template<typename OutStringType = std::string, typename... Args>
+inline OutStringType concat(Args && ... args)
+{
+ OutStringType str;
+ str.reserve(concat_length(std::forward<Args>(args)...));
+ concat_into(str, std::forward<Args>(args)...);
+ return str;
+}
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+////////////////
+// exceptions //
+////////////////
+
+/// @brief general exception of the @ref basic_json class
+/// @sa https://json.nlohmann.me/api/basic_json/exception/
+class exception : public std::exception
+{
+ public:
+ /// returns the explanatory string
+ const char* what() const noexcept override
+ {
+ return m.what();
+ }
+
+ /// the id of the exception
+ const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
+
+ protected:
+ JSON_HEDLEY_NON_NULL(3)
+ exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
+
+ static std::string name(const std::string& ename, int id_)
+ {
+ return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
+ }
+
+ static std::string diagnostics(std::nullptr_t /*leaf_element*/)
+ {
+ return "";
+ }
+
+ template<typename BasicJsonType>
+ static std::string diagnostics(const BasicJsonType* leaf_element)
+ {
+#if JSON_DIAGNOSTICS
+ std::vector<std::string> tokens;
+ for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
+ {
+ switch (current->m_parent->type())
+ {
+ case value_t::array:
+ {
+ for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
+ {
+ if (&current->m_parent->m_value.array->operator[](i) == current)
+ {
+ tokens.emplace_back(std::to_string(i));
+ break;
+ }
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ for (const auto& element : *current->m_parent->m_value.object)
+ {
+ if (&element.second == current)
+ {
+ tokens.emplace_back(element.first.c_str());
+ break;
+ }
+ }
+ break;
+ }
+
+ case value_t::null: // LCOV_EXCL_LINE
+ case value_t::string: // LCOV_EXCL_LINE
+ case value_t::boolean: // LCOV_EXCL_LINE
+ case value_t::number_integer: // LCOV_EXCL_LINE
+ case value_t::number_unsigned: // LCOV_EXCL_LINE
+ case value_t::number_float: // LCOV_EXCL_LINE
+ case value_t::binary: // LCOV_EXCL_LINE
+ case value_t::discarded: // LCOV_EXCL_LINE
+ default: // LCOV_EXCL_LINE
+ break; // LCOV_EXCL_LINE
+ }
+ }
+
+ if (tokens.empty())
+ {
+ return "";
+ }
+
+ auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
+ [](const std::string & a, const std::string & b)
+ {
+ return concat(a, '/', detail::escape(b));
+ });
+ return concat('(', str, ") ");
+#else
+ static_cast<void>(leaf_element);
+ return "";
+#endif
+ }
+
+ private:
+ /// an exception object as storage for error messages
+ std::runtime_error m;
+};
+
+/// @brief exception indicating a parse error
+/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
+class parse_error : public exception
+{
+ public:
+ /*!
+ @brief create a parse error exception
+ @param[in] id_ the id of the exception
+ @param[in] pos the position where the error occurred (or with
+ chars_read_total=0 if the position cannot be
+ determined)
+ @param[in] what_arg the explanatory string
+ @return parse_error object
+ */
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("parse_error", id_), "parse error",
+ position_string(pos), ": ", exception::diagnostics(context), what_arg);
+ return {id_, pos.chars_read_total, w.c_str()};
+ }
+
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("parse_error", id_), "parse error",
+ (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
+ ": ", exception::diagnostics(context), what_arg);
+ return {id_, byte_, w.c_str()};
+ }
+
+ /*!
+ @brief byte index of the parse error
+
+ The byte index of the last read character in the input file.
+
+ @note For an input with n bytes, 1 is the index of the first character and
+ n+1 is the index of the terminating null byte or the end of file.
+ This also holds true when reading a byte vector (CBOR or MessagePack).
+ */
+ const std::size_t byte;
+
+ private:
+ parse_error(int id_, std::size_t byte_, const char* what_arg)
+ : exception(id_, what_arg), byte(byte_) {}
+
+ static std::string position_string(const position_t& pos)
+ {
+ return concat(" at line ", std::to_string(pos.lines_read + 1),
+ ", column ", std::to_string(pos.chars_read_current_line));
+ }
+};
+
+/// @brief exception indicating errors with iterators
+/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
+class invalid_iterator : public exception
+{
+ public:
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ invalid_iterator(int id_, const char* what_arg)
+ : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating executing a member function with a wrong type
+/// @sa https://json.nlohmann.me/api/basic_json/type_error/
+class type_error : public exception
+{
+ public:
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating access out of the defined range
+/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
+class out_of_range : public exception
+{
+ public:
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/// @brief exception indicating other library errors
+/// @sa https://json.nlohmann.me/api/basic_json/other_error/
+class other_error : public exception
+{
+ public:
+ template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
+ static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
+ {
+ std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
+{
+
+// dispatching helper struct
+template <class T> struct identity_tag {};
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
+
+// #include <nlohmann/detail/meta/std_fs.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
#include <experimental/filesystem>
-namespace nlohmann::detail
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
{
namespace std_fs = std::experimental::filesystem;
-} // namespace nlohmann::detail
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
#elif JSON_HAS_FILESYSTEM
#include <filesystem>
-namespace nlohmann::detail
+NLOHMANN_JSON_NAMESPACE_BEGIN
+namespace detail
{
namespace std_fs = std::filesystem;
-} // namespace nlohmann::detail
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
#endif
-namespace nlohmann
-{
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/string_concat.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{
- JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
}
n = nullptr;
}
@@ -3873,82 +4554,84 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{
- JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
}
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template <
- typename BasicJsonType, typename ConstructibleStringType,
+ typename BasicJsonType, typename StringType,
enable_if_t <
- is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
- !std::is_same<typename BasicJsonType::string_t,
- ConstructibleStringType>::value,
- int > = 0 >
-void from_json(const BasicJsonType& j, ConstructibleStringType& s)
+ std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
+ && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
+ && !std::is_same<typename BasicJsonType::string_t, StringType>::value
+ && !is_json_ref<StringType>::value, int > = 0 >
+inline void from_json(const BasicJsonType& j, StringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
get_arithmetic_value(j, val);
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
{
get_arithmetic_value(j, val);
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
{
get_arithmetic_value(j, val);
}
+#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
-void from_json(const BasicJsonType& j, EnumType& e)
+inline void from_json(const BasicJsonType& j, EnumType& e)
{
typename std::underlying_type<EnumType>::type val;
get_arithmetic_value(j, val);
e = static_cast<EnumType>(val);
}
+#endif // JSON_DISABLE_ENUM_SERIALIZATION
// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
-void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
@@ -3961,11 +4644,11 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
// valarray doesn't have an insert method
template<typename BasicJsonType, typename T,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
-void from_json(const BasicJsonType& j, std::valarray<T>& l)
+inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l),
@@ -3986,7 +4669,7 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines
}
template<typename BasicJsonType>
-void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
+inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
@@ -4030,8 +4713,8 @@ template<typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t<
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
int> = 0>
-void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
- priority_tag<0> /*unused*/)
+inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
+ priority_tag<0> /*unused*/)
{
using std::end;
@@ -4062,7 +4745,7 @@ void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
from_json_array_impl(j, arr, priority_tag<3> {});
@@ -4081,18 +4764,18 @@ auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
}
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
+inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
}
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
@@ -4100,11 +4783,11 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
template<typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
-void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
+inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
- JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
}
ConstructibleObjectType ret;
@@ -4132,7 +4815,7 @@ template < typename BasicJsonType, typename ArithmeticType,
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
-void from_json(const BasicJsonType& j, ArithmeticType& val)
+inline void from_json(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
{
@@ -4164,7 +4847,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}
@@ -4182,7 +4865,7 @@ std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair
}
template<typename BasicJsonType, typename A1, typename A2>
-void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
+inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
{
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
}
@@ -4194,7 +4877,7 @@ std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tu
}
template<typename BasicJsonType, typename... Args>
-void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
+inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
{
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
@@ -4205,7 +4888,7 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
@@ -4214,18 +4897,18 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
-void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
@@ -4234,18 +4917,18 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
-void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
@@ -4253,11 +4936,11 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
template<typename BasicJsonType>
-void from_json(const BasicJsonType& j, std_fs::path& p)
+inline void from_json(const BasicJsonType& j, std_fs::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
@@ -4273,18 +4956,33 @@ struct from_json_fn
return from_json(j, std::forward<T>(val));
}
};
+
} // namespace detail
+#ifndef JSON_HAS_CPP_17
/// namespace to hold default `from_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
-constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
-} // namespace
-} // namespace nlohmann
+#endif
+JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
+ detail::static_const<detail::from_json_fn>::value;
+#ifndef JSON_HAS_CPP_17
+} // namespace
+#endif
+
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/conversions/to_json.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // copy
@@ -4296,9 +4994,15 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
#include <valarray> // valarray
#include <vector> // vector
-// #include <nlohmann/detail/macro_scope.hpp>
-
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstddef> // size_t
@@ -4307,15 +5011,21 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
#include <tuple> // tuple_size, get, tuple_element
#include <utility> // move
+#if JSON_HAS_RANGES
+ #include <ranges> // enable_borrowed_range
+#endif
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
template<typename string_type>
void int_to_string( string_type& target, std::size_t value )
{
@@ -4328,14 +5038,14 @@ template<typename IteratorType> class iteration_proxy_value
public:
using difference_type = std::ptrdiff_t;
using value_type = iteration_proxy_value;
- using pointer = value_type * ;
- using reference = value_type & ;
+ using pointer = value_type *;
+ using reference = value_type &;
using iterator_category = std::input_iterator_tag;
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
private:
/// the iterator
- IteratorType anchor;
+ IteratorType anchor{};
/// an index for arrays (used to create key names)
std::size_t array_index = 0;
/// last stringified array index
@@ -4343,15 +5053,30 @@ template<typename IteratorType> class iteration_proxy_value
/// a string representation of the array index
mutable string_type array_index_str = "0";
/// an empty string (to return a reference for primitive values)
- const string_type empty_str{};
+ string_type empty_str{};
public:
- explicit iteration_proxy_value(IteratorType it) noexcept
+ explicit iteration_proxy_value() = default;
+ explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
+ noexcept(std::is_nothrow_move_constructible<IteratorType>::value
+ && std::is_nothrow_default_constructible<string_type>::value)
: anchor(std::move(it))
+ , array_index(array_index_)
{}
+ iteration_proxy_value(iteration_proxy_value const&) = default;
+ iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
+ // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
+ iteration_proxy_value(iteration_proxy_value&&)
+ noexcept(std::is_nothrow_move_constructible<IteratorType>::value
+ && std::is_nothrow_move_constructible<string_type>::value) = default;
+ iteration_proxy_value& operator=(iteration_proxy_value&&)
+ noexcept(std::is_nothrow_move_assignable<IteratorType>::value
+ && std::is_nothrow_move_assignable<string_type>::value) = default;
+ ~iteration_proxy_value() = default;
+
/// dereference operator (needed for range-based for)
- iteration_proxy_value& operator*()
+ const iteration_proxy_value& operator*() const
{
return *this;
}
@@ -4365,6 +5090,14 @@ template<typename IteratorType> class iteration_proxy_value
return *this;
}
+ iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
+ {
+ auto tmp = iteration_proxy_value(anchor, array_index);
+ ++anchor;
+ ++array_index;
+ return tmp;
+ }
+
/// equality operator (needed for InputIterator)
bool operator==(const iteration_proxy_value& o) const
{
@@ -4425,25 +5158,34 @@ template<typename IteratorType> class iteration_proxy
{
private:
/// the container to iterate
- typename IteratorType::reference container;
+ typename IteratorType::pointer container = nullptr;
public:
+ explicit iteration_proxy() = default;
+
/// construct iteration proxy from a container
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
- : container(cont) {}
+ : container(&cont) {}
+
+ iteration_proxy(iteration_proxy const&) = default;
+ iteration_proxy& operator=(iteration_proxy const&) = default;
+ iteration_proxy(iteration_proxy&&) noexcept = default;
+ iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
+ ~iteration_proxy() = default;
/// return iterator begin (needed for range-based for)
- iteration_proxy_value<IteratorType> begin() noexcept
+ iteration_proxy_value<IteratorType> begin() const noexcept
{
- return iteration_proxy_value<IteratorType>(container.begin());
+ return iteration_proxy_value<IteratorType>(container->begin());
}
/// return iterator end (needed for range-based for)
- iteration_proxy_value<IteratorType> end() noexcept
+ iteration_proxy_value<IteratorType> end() const noexcept
{
- return iteration_proxy_value<IteratorType>(container.end());
+ return iteration_proxy_value<IteratorType>(container->end());
}
};
+
// Structured Bindings Support
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
// And see https://github.com/nlohmann/json/pull/1391
@@ -4460,8 +5202,9 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
{
return i.value();
}
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// The Addition to the STD Namespace is required to add
// Structured Bindings Support to the iteration_proxy_value class
@@ -4469,6 +5212,7 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
// And see https://github.com/nlohmann/json/pull/1391
namespace std
{
+
#if defined(__clang__)
// Fix: https://github.com/nlohmann/json/issues/1401
#pragma clang diagnostic push
@@ -4489,33 +5233,29 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
-} // namespace std
+
+} // namespace std
+
+#if JSON_HAS_RANGES
+ template <typename IteratorType>
+ inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
+#endif
+
+// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
+// #include <nlohmann/detail/meta/std_fs.hpp>
+
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
-#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
-#include <experimental/filesystem>
-namespace nlohmann::detail
-{
-namespace std_fs = std::experimental::filesystem;
-} // namespace nlohmann::detail
-#elif JSON_HAS_FILESYSTEM
-#include <filesystem>
-namespace nlohmann::detail
-{
-namespace std_fs = std::filesystem;
-} // namespace nlohmann::detail
-#endif
-
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
//////////////////
// constructors //
//////////////////
@@ -4750,55 +5490,64 @@ struct external_constructor<value_t::object>
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
-void to_json(BasicJsonType& j, T b) noexcept
+inline void to_json(BasicJsonType& j, T b) noexcept
{
external_constructor<value_t::boolean>::construct(j, b);
}
+template<typename BasicJsonType,
+ enable_if_t<std::is_convertible<const std::vector<bool>::reference&, typename BasicJsonType::boolean_t>::value, int> = 0>
+inline void to_json(BasicJsonType& j, const std::vector<bool>::reference& b) noexcept
+{
+ external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
+}
+
template<typename BasicJsonType, typename CompatibleString,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
-void to_json(BasicJsonType& j, const CompatibleString& s)
+inline void to_json(BasicJsonType& j, const CompatibleString& s)
{
external_constructor<value_t::string>::construct(j, s);
}
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
{
external_constructor<value_t::string>::construct(j, std::move(s));
}
template<typename BasicJsonType, typename FloatType,
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
-void to_json(BasicJsonType& j, FloatType val) noexcept
+inline void to_json(BasicJsonType& j, FloatType val) noexcept
{
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
}
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
-void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
{
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
}
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
-void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
{
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
}
+#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
-void to_json(BasicJsonType& j, EnumType e) noexcept
+inline void to_json(BasicJsonType& j, EnumType e) noexcept
{
using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
}
+#endif // JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, const std::vector<bool>& e)
+inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
{
external_constructor<value_t::array>::construct(j, e);
}
@@ -4811,39 +5560,39 @@ template < typename BasicJsonType, typename CompatibleArrayType,
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
!is_basic_json<CompatibleArrayType>::value,
int > = 0 >
-void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
{
external_constructor<value_t::array>::construct(j, arr);
}
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
+inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
{
external_constructor<value_t::binary>::construct(j, bin);
}
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
-void to_json(BasicJsonType& j, const std::valarray<T>& arr)
+inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
-void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{
external_constructor<value_t::object>::construct(j, std::move(obj));
}
@@ -4853,13 +5602,13 @@ template <
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
int > = 0 >
-void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{
external_constructor<value_t::array>::construct(j, arr);
}
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
-void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
+inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
{
j = { p.first, p.second };
}
@@ -4867,26 +5616,26 @@ void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
// for https://github.com/nlohmann/json/pull/1134
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
-void to_json(BasicJsonType& j, const T& b)
+inline void to_json(BasicJsonType& j, const T& b)
{
j = { {b.key(), b.value()} };
}
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
-void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
+inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
{
j = { std::get<Idx>(t)... };
}
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
-void to_json(BasicJsonType& j, const T& t)
+inline void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
template<typename BasicJsonType>
-void to_json(BasicJsonType& j, const std_fs::path& p)
+inline void to_json(BasicJsonType& j, const std_fs::path& p)
{
j = p.string();
}
@@ -4903,22 +5652,25 @@ struct to_json_fn
};
} // namespace detail
+#ifndef JSON_HAS_CPP_17
/// namespace to hold default `to_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
-constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
-} // namespace
-} // namespace nlohmann
+#endif
+JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
+ detail::static_const<detail::to_json_fn>::value;
+#ifndef JSON_HAS_CPP_17
+} // namespace
+#endif
-// #include <nlohmann/detail/meta/identity_tag.hpp>
+NLOHMANN_JSON_NAMESPACE_END
-// #include <nlohmann/detail/meta/type_traits.hpp>
+// #include <nlohmann/detail/meta/identity_tag.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
/// @sa https://json.nlohmann.me/api/adl_serializer/
template<typename ValueType, typename>
@@ -4954,17 +5706,28 @@ struct adl_serializer
::nlohmann::to_json(j, std::forward<TargetType>(val));
}
};
-} // namespace nlohmann
+
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/byte_container_with_subtype.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstdint> // uint8_t, uint64_t
#include <tuple> // tie
#include <utility> // move
-namespace nlohmann
-{
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
/// @brief an internal type for a backed binary type
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
@@ -5050,7 +5813,7 @@ class byte_container_with_subtype : public BinaryType
bool m_has_subtype = false;
};
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/conversions/from_json.hpp>
@@ -5059,19 +5822,26 @@ class byte_container_with_subtype : public BinaryType
// #include <nlohmann/detail/exceptions.hpp>
// #include <nlohmann/detail/hash.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstdint> // uint8_t
#include <cstddef> // size_t
#include <functional> // hash
-// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/abi_macros.hpp>
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -5182,9 +5952,17 @@ std::size_t hash(const BasicJsonType& j)
}
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/input/binary_reader.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // generate_n
@@ -5199,10 +5977,19 @@ std::size_t hash(const BasicJsonType& j)
#include <string> // char_traits, string
#include <utility> // make_pair, move
#include <vector> // vector
+#include <map> // map
// #include <nlohmann/detail/exceptions.hpp>
// #include <nlohmann/detail/input/input_adapters.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <array> // array
@@ -5225,12 +6012,12 @@ std::size_t hash(const BasicJsonType& j)
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
/// the supported input formats
-enum class input_format_t { json, cbor, msgpack, ubjson, bson };
+enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
////////////////////
// input adapters //
@@ -5249,7 +6036,9 @@ class file_input_adapter
JSON_HEDLEY_NON_NULL(2)
explicit file_input_adapter(std::FILE* f) noexcept
: m_file(f)
- {}
+ {
+ JSON_ASSERT(m_file != nullptr);
+ }
// make class move-only
file_input_adapter(const file_input_adapter&) = delete;
@@ -5607,7 +6396,7 @@ struct container_input_adapter_factory< ContainerType,
}
};
-} // namespace container_input_adapter_factory_impl
+} // namespace container_input_adapter_factory_impl
template<typename ContainerType>
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
@@ -5686,10 +6475,19 @@ class span_input_adapter
private:
contiguous_bytes_input_adapter ia;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/input/json_sax.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstddef>
@@ -5701,9 +6499,10 @@ class span_input_adapter
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
-namespace nlohmann
-{
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief SAX interface
@@ -5918,7 +6717,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -5926,6 +6725,9 @@ class json_sax_dom_parser
bool key(string_t& val)
{
+ JSON_ASSERT(!ref_stack.empty());
+ JSON_ASSERT(ref_stack.back()->is_object());
+
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
return true;
@@ -5933,6 +6735,9 @@ class json_sax_dom_parser
bool end_object()
{
+ JSON_ASSERT(!ref_stack.empty());
+ JSON_ASSERT(ref_stack.back()->is_object());
+
ref_stack.back()->set_parents();
ref_stack.pop_back();
return true;
@@ -5944,7 +6749,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -5952,6 +6757,9 @@ class json_sax_dom_parser
bool end_array()
{
+ JSON_ASSERT(!ref_stack.empty());
+ JSON_ASSERT(ref_stack.back()->is_array());
+
ref_stack.back()->set_parents();
ref_stack.pop_back();
return true;
@@ -6099,7 +6907,7 @@ class json_sax_dom_callback_parser
// check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -6169,7 +6977,7 @@ class json_sax_dom_callback_parser
// check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -6400,11 +7208,19 @@ class json_sax_acceptor
return false;
}
};
-} // namespace detail
-} // namespace nlohmann
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/input/lexer.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <array> // array
@@ -6424,10 +7240,10 @@ class json_sax_acceptor
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
///////////
// lexer //
///////////
@@ -8029,27 +8845,38 @@ scan_number_done:
/// the decimal point
const char_int_type decimal_point_char = '.';
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/is_sax.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
+// #include <nlohmann/detail/abi_macros.hpp>
+
// #include <nlohmann/detail/meta/detected.hpp>
// #include <nlohmann/detail/meta/type_traits.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
template<typename T>
using null_function_t = decltype(std::declval<T&>().null());
@@ -8184,16 +9011,18 @@ struct is_sax_static_asserts
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/type_traits.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -8243,7 +9072,7 @@ class binary_reader
@param[in] adapter input adapter to read from
*/
- explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
+ explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
}
@@ -8287,6 +9116,7 @@ class binary_reader
break;
case input_format_t::ubjson:
+ case input_format_t::bjdata:
result = parse_ubjson_internal();
break;
@@ -8298,7 +9128,7 @@ class binary_reader
// strict mode: next byte must be EOF
if (result && strict)
{
- if (format == input_format_t::ubjson)
+ if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
{
get_ignore_noop();
}
@@ -8309,8 +9139,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
{
- return sax->parse_error(chars_read, get_token_string(),
- parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
+ exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
}
}
@@ -8386,7 +9216,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(len < 1))
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
}
return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
@@ -8407,7 +9238,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(len < 0))
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
}
// All BSON binary values have a subtype
@@ -8489,7 +9321,9 @@ class binary_reader
{
std::array<char, 3> cr{{}};
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
- 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()), BasicJsonType()));
+ std::string cr_str{cr.data()};
+ return sax->parse_error(element_type_parse_position, cr_str,
+ parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
}
}
}
@@ -8781,7 +9615,8 @@ class binary_reader
case 0x95:
case 0x96:
case 0x97:
- return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+ return get_cbor_array(
+ conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
case 0x98: // array (one-byte uint8_t for n follows)
{
@@ -8798,13 +9633,13 @@ class binary_reader
case 0x9A: // array (four-byte uint32_t for n follow)
{
std::uint32_t len{};
- return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+ return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
std::uint64_t len{};
- return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+ return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
}
case 0x9F: // array (indefinite length)
@@ -8835,7 +9670,7 @@ class binary_reader
case 0xB5:
case 0xB6:
case 0xB7:
- return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+ return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
case 0xB8: // map (one-byte uint8_t for n follows)
{
@@ -8852,13 +9687,13 @@ class binary_reader
case 0xBA: // map (four-byte uint32_t for n follow)
{
std::uint32_t len{};
- return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+ return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
std::uint64_t len{};
- return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+ return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
}
case 0xBF: // map (indefinite length)
@@ -8889,7 +9724,8 @@ class binary_reader
case cbor_tag_handler_t::error:
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
case cbor_tag_handler_t::ignore:
@@ -9046,7 +9882,8 @@ class binary_reader
default: // anything else (0xFF is handled inside the other types)
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
}
}
@@ -9141,7 +9978,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
}
}
}
@@ -9240,7 +10078,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
}
}
}
@@ -9501,7 +10340,7 @@ class binary_reader
case 0x8D:
case 0x8E:
case 0x8F:
- return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+ return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixarray
case 0x90:
@@ -9520,7 +10359,7 @@ class binary_reader
case 0x9D:
case 0x9E:
case 0x9F:
- return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+ return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixstr
case 0xA0:
@@ -9657,7 +10496,7 @@ class binary_reader
case 0xDD: // array 32
{
std::uint32_t len{};
- return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+ return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
}
case 0xDE: // map 16
@@ -9669,7 +10508,7 @@ class binary_reader
case 0xDF: // map 32
{
std::uint32_t len{};
- return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+ return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
}
// negative fixint
@@ -9710,7 +10549,8 @@ class binary_reader
default: // anything else
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
}
}
@@ -9792,7 +10632,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
}
}
}
@@ -10003,7 +10844,7 @@ class binary_reader
get(); // TODO(niels): may we ignore N here?
}
- if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
{
return false;
}
@@ -10013,51 +10854,162 @@ class binary_reader
case 'U':
{
std::uint8_t len{};
- return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ return get_number(input_format, len) && get_string(input_format, len, result);
}
case 'i':
{
std::int8_t len{};
- return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ return get_number(input_format, len) && get_string(input_format, len, result);
}
case 'I':
{
std::int16_t len{};
- return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ return get_number(input_format, len) && get_string(input_format, len, result);
}
case 'l':
{
std::int32_t len{};
- return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ return get_number(input_format, len) && get_string(input_format, len, result);
}
case 'L':
{
std::int64_t len{};
- return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ return get_number(input_format, len) && get_string(input_format, len, result);
+ }
+
+ case 'u':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint16_t len{};
+ return get_number(input_format, len) && get_string(input_format, len, result);
+ }
+
+ case 'm':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint32_t len{};
+ return get_number(input_format, len) && get_string(input_format, len, result);
+ }
+
+ case 'M':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint64_t len{};
+ return get_number(input_format, len) && get_string(input_format, len, result);
}
default:
- auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ break;
+ }
+ auto last_token = get_token_string();
+ std::string message;
+
+ if (input_format != input_format_t::bjdata)
+ {
+ message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
}
+ else
+ {
+ message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
+ }
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
+ }
+
+ /*!
+ @param[out] dim an integer vector storing the ND array dimensions
+ @return whether reading ND array size vector is successful
+ */
+ bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
+ {
+ std::pair<std::size_t, char_int_type> size_and_type;
+ size_t dimlen = 0;
+ bool no_ndarray = true;
+
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
+ {
+ return false;
+ }
+
+ if (size_and_type.first != string_t::npos)
+ {
+ if (size_and_type.second != 0)
+ {
+ if (size_and_type.second != 'N')
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
+ {
+ return false;
+ }
+ dim.push_back(dimlen);
+ }
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
+ {
+ return false;
+ }
+ dim.push_back(dimlen);
+ }
+ }
+ }
+ else
+ {
+ while (current != ']')
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
+ {
+ return false;
+ }
+ dim.push_back(dimlen);
+ get_ignore_noop();
+ }
+ }
+ return true;
}
/*!
@param[out] result determined size
+ @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
+ or ndarray dimension is not allowed; `false` means ndarray
+ is allowed; for output, `true` means an ndarray is found;
+ is_ndarray can only return `true` when its initial value
+ is `false`
+ @param[in] prefix type marker if already read, otherwise set to 0
+
@return whether size determination completed
*/
- bool get_ubjson_size_value(std::size_t& result)
+ bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
{
- switch (get_ignore_noop())
+ if (prefix == 0)
+ {
+ prefix = get_ignore_noop();
+ }
+
+ switch (prefix)
{
case 'U':
{
std::uint8_t number{};
- if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
{
return false;
}
@@ -10068,10 +11020,15 @@ class binary_reader
case 'i':
{
std::int8_t number{};
- if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
{
return false;
}
+ if (number < 0)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+ exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+ }
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
return true;
}
@@ -10079,10 +11036,15 @@ class binary_reader
case 'I':
{
std::int16_t number{};
- if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
{
return false;
}
+ if (number < 0)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+ exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+ }
result = static_cast<std::size_t>(number);
return true;
}
@@ -10090,10 +11052,15 @@ class binary_reader
case 'l':
{
std::int32_t number{};
- if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
{
return false;
}
+ if (number < 0)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+ exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+ }
result = static_cast<std::size_t>(number);
return true;
}
@@ -10101,20 +11068,145 @@ class binary_reader
case 'L':
{
std::int64_t number{};
- if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
{
return false;
}
+ if (number < 0)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
+ exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
+ }
+ if (!value_in_range_of<std::size_t>(number))
+ {
+ return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
+ exception_message(input_format, "integer value overflow", "size"), nullptr));
+ }
result = static_cast<std::size_t>(number);
return true;
}
- default:
+ case 'u':
{
- auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint16_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
}
+
+ case 'm':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint32_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+ {
+ return false;
+ }
+ result = conditional_static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'M':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint64_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
+ {
+ return false;
+ }
+ if (!value_in_range_of<std::size_t>(number))
+ {
+ return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
+ exception_message(input_format, "integer value overflow", "size"), nullptr));
+ }
+ result = detail::conditional_static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case '[':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr));
+ }
+ std::vector<size_t> dim;
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
+ {
+ return false;
+ }
+ if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
+ {
+ result = dim.at(dim.size() - 1);
+ return true;
+ }
+ if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
+ {
+ for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
+ {
+ if ( i == 0 )
+ {
+ result = 0;
+ return true;
+ }
+ }
+
+ string_t key = "_ArraySize_";
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
+ {
+ return false;
+ }
+ result = 1;
+ for (auto i : dim)
+ {
+ result *= i;
+ if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type()
+ {
+ return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
+ }
+ if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
+ {
+ return false;
+ }
+ }
+ is_ndarray = true;
+ return sax->end_array();
+ }
+ result = 0;
+ return true;
+ }
+
+ default:
+ break;
}
+ auto last_token = get_token_string();
+ std::string message;
+
+ if (input_format != input_format_t::bjdata)
+ {
+ message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
+ }
+ else
+ {
+ message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
+ }
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
}
/*!
@@ -10124,20 +11216,31 @@ class binary_reader
for a more compact representation.
@param[out] result pair of the size and the type
+ @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
@return whether pair creation completed
*/
- bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
+ bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
{
result.first = string_t::npos; // size
result.second = 0; // type
+ bool is_ndarray = false;
get_ignore_noop();
if (current == '$')
{
+ std::vector<char_int_type> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
+
result.second = get(); // must not ignore 'N', because 'N' maybe the type
- if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
+ if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() ))
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
{
return false;
}
@@ -10145,20 +11248,37 @@ class binary_reader
get_ignore_noop();
if (JSON_HEDLEY_UNLIKELY(current != '#'))
{
- if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
{
return false;
}
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
}
- return get_ubjson_size_value(result.first);
+ bool is_error = get_ubjson_size_value(result.first, is_ndarray);
+ if (input_format == input_format_t::bjdata && is_ndarray)
+ {
+ if (inside_ndarray)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
+ exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
+ }
+ result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
+ }
+ return is_error;
}
if (current == '#')
{
- return get_ubjson_size_value(result.first);
+ bool is_error = get_ubjson_size_value(result.first, is_ndarray);
+ if (input_format == input_format_t::bjdata && is_ndarray)
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
+ exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
+ }
+ return is_error;
}
return true;
@@ -10173,7 +11293,7 @@ class binary_reader
switch (prefix)
{
case std::char_traits<char_type>::eof(): // EOF
- return unexpect_eof(input_format_t::ubjson, "value");
+ return unexpect_eof(input_format, "value");
case 'T': // true
return sax->boolean(true);
@@ -10186,43 +11306,125 @@ class binary_reader
case 'U':
{
std::uint8_t number{};
- return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
+ return get_number(input_format, number) && sax->number_unsigned(number);
}
case 'i':
{
std::int8_t number{};
- return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ return get_number(input_format, number) && sax->number_integer(number);
}
case 'I':
{
std::int16_t number{};
- return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ return get_number(input_format, number) && sax->number_integer(number);
}
case 'l':
{
std::int32_t number{};
- return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ return get_number(input_format, number) && sax->number_integer(number);
}
case 'L':
{
std::int64_t number{};
- return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ return get_number(input_format, number) && sax->number_integer(number);
+ }
+
+ case 'u':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint16_t number{};
+ return get_number(input_format, number) && sax->number_unsigned(number);
+ }
+
+ case 'm':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint32_t number{};
+ return get_number(input_format, number) && sax->number_unsigned(number);
+ }
+
+ case 'M':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ std::uint64_t number{};
+ return get_number(input_format, number) && sax->number_unsigned(number);
+ }
+
+ case 'h':
+ {
+ if (input_format != input_format_t::bjdata)
+ {
+ break;
+ }
+ const auto byte1_raw = get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
+ {
+ return false;
+ }
+ const auto byte2_raw = get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
+ {
+ return false;
+ }
+
+ const auto byte1 = static_cast<unsigned char>(byte1_raw);
+ const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+ // code from RFC 7049, Appendix D, Figure 3:
+ // As half-precision floating-point numbers were only added
+ // to IEEE 754 in 2008, today's programming platforms often
+ // still only have limited support for them. It is very
+ // easy to include at least decoding support for them even
+ // without such support. An example of a small decoder for
+ // half-precision floating-point numbers in the C language
+ // is shown in Fig. 3.
+ const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
+ const double val = [&half]
+ {
+ const int exp = (half >> 10u) & 0x1Fu;
+ const unsigned int mant = half & 0x3FFu;
+ JSON_ASSERT(0 <= exp&& exp <= 32);
+ JSON_ASSERT(mant <= 1024);
+ switch (exp)
+ {
+ case 0:
+ return std::ldexp(mant, -24);
+ case 31:
+ return (mant == 0)
+ ? std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::quiet_NaN();
+ default:
+ return std::ldexp(mant + 1024, exp - 25);
+ }
+ }();
+ return sax->number_float((half & 0x8000u) != 0
+ ? static_cast<number_float_t>(-val)
+ : static_cast<number_float_t>(val), "");
}
case 'd':
{
float number{};
- return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
}
case 'D':
{
double number{};
- return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
}
case 'H':
@@ -10233,14 +11435,15 @@ class binary_reader
case 'C': // char
{
get();
- if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
{
return false;
}
if (JSON_HEDLEY_UNLIKELY(current > 127))
{
auto last_token = get_token_string();
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
}
string_t s(1, static_cast<typename string_t::value_type>(current));
return sax->string(s);
@@ -10259,11 +11462,10 @@ class binary_reader
return get_ubjson_object();
default: // anything else
- {
- auto last_token = get_token_string();
- 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"), BasicJsonType()));
- }
+ break;
}
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
}
/*!
@@ -10277,6 +11479,52 @@ class binary_reader
return false;
}
+ // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
+ // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
+
+ if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
+ {
+ std::map<char_int_type, string_t> bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"},
+ {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"}
+ };
+
+ size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
+
+ string_t key = "_ArrayType_";
+ if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0))
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) ))
+ {
+ return false;
+ }
+
+ if (size_and_type.second == 'C')
+ {
+ size_and_type.second = 'U';
+ }
+
+ key = "_ArrayData_";
+ if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
+ {
+ return false;
+ }
+
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ }
+
+ return (sax->end_array() && sax->end_object());
+ }
+
if (size_and_type.first != string_t::npos)
{
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
@@ -10339,6 +11587,14 @@ class binary_reader
return false;
}
+ // do not accept ND-array size in objects in BJData
+ if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
+ }
+
string_t key;
if (size_and_type.first != string_t::npos)
{
@@ -10410,7 +11666,8 @@ class binary_reader
{
// get size of following number string
std::size_t size{};
- auto res = get_ubjson_size_value(size);
+ bool no_ndarray = true;
+ auto res = get_ubjson_size_value(size, no_ndarray);
if (JSON_HEDLEY_UNLIKELY(!res))
{
return res;
@@ -10421,7 +11678,7 @@ class binary_reader
for (std::size_t i = 0; i < size; ++i)
{
get();
- if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
{
return false;
}
@@ -10439,7 +11696,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
{
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+ exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
}
switch (result_number)
@@ -10465,7 +11723,8 @@ class binary_reader
case token_type::end_of_input:
case token_type::literal_or_value:
default:
- 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"), BasicJsonType()));
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+ exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
}
}
@@ -10514,6 +11773,8 @@ class binary_reader
@note This function needs to respect the system's endianness, because
bytes in CBOR, MessagePack, and UBJSON are stored in network order
(big endian) and therefore need reordering on little endian systems.
+ On the other hand, BSON and BJData use little endian and should reorder
+ on big endian systems.
*/
template<typename NumberType, bool InputIsLittleEndian = false>
bool get_number(const input_format_t format, NumberType& result)
@@ -10529,7 +11790,7 @@ class binary_reader
}
// reverse byte order prior to conversion if necessary
- if (is_little_endian != InputIsLittleEndian)
+ if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
{
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
}
@@ -10621,7 +11882,7 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
{
return sax->parse_error(chars_read, "<end of file>",
- parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
+ parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
}
return true;
}
@@ -10666,12 +11927,16 @@ class binary_reader
error_msg += "BSON";
break;
+ case input_format_t::bjdata:
+ error_msg += "BJData";
+ break;
+
case input_format_t::json: // LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
- return error_msg + " " + context + ": " + detail;
+ return concat(error_msg, ' ', context, ": ", detail);
}
private:
@@ -10687,17 +11952,29 @@ class binary_reader
/// whether we can assume little endianness
const bool is_little_endian = little_endianness();
+ /// input format
+ const input_format_t input_format = input_format_t::json;
+
/// the SAX parser
json_sax_t* sax = nullptr;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/input/input_adapters.hpp>
// #include <nlohmann/detail/input/lexer.hpp>
// #include <nlohmann/detail/input/parser.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cmath> // isfinite
@@ -10719,11 +11996,12 @@ class binary_reader
// #include <nlohmann/detail/meta/is_sax.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
////////////
@@ -10802,7 +12080,7 @@ class parser
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
- exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ exception_message(token_type::end_of_input, "value"), nullptr));
}
// in case of an error, return discarded value
@@ -10829,7 +12107,7 @@ class parser
{
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
}
// in case of an error, return discarded value
@@ -10867,7 +12145,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
}
return result;
@@ -10913,7 +12191,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
{
@@ -10925,7 +12203,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// remember we are now inside an object
@@ -10968,7 +12246,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
+ out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
@@ -11038,7 +12316,7 @@ class parser
// using "uninitialized" to avoid "expected" message
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
}
case token_type::uninitialized:
@@ -11052,7 +12330,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
}
}
}
@@ -11098,7 +12376,7 @@ class parser
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
}
// states.back() is false -> object
@@ -11111,7 +12389,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
@@ -11124,7 +12402,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// parse values
@@ -11152,7 +12430,7 @@ class parser
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
}
}
@@ -11168,24 +12446,24 @@ class parser
if (!context.empty())
{
- error_msg += "while parsing " + context + " ";
+ error_msg += concat("while parsing ", context, ' ');
}
error_msg += "- ";
if (last_token == token_type::parse_error)
{
- error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
- m_lexer.get_token_string() + "'";
+ error_msg += concat(m_lexer.get_error_message(), "; last read: '",
+ m_lexer.get_token_string(), '\'');
}
else
{
- error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+ error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
}
if (expected != token_type::uninitialized)
{
- error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+ error_msg += concat("; expected ", lexer_t::token_type_name(expected));
}
return error_msg;
@@ -11203,12 +12481,30 @@ class parser
};
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+// #include <nlohmann/detail/abi_macros.hpp>
+
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstddef> // ptrdiff_t
@@ -11217,10 +12513,10 @@ class parser
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
/*
@brief an iterator for primitive JSON types
@@ -11299,7 +12595,7 @@ class primitive_iterator_t
return *this;
}
- primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
+ primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
++m_it;
@@ -11312,7 +12608,7 @@ class primitive_iterator_t
return *this;
}
- primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
+ primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
--m_it;
@@ -11331,14 +12627,15 @@ class primitive_iterator_t
return *this;
}
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
/*!
@brief an iterator value
@@ -11354,10 +12651,19 @@ template<typename BasicJsonType> struct internal_iterator
/// generic iterator for all other types
primitive_iterator_t primitive_iterator {};
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/iterators/iter_impl.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
@@ -11378,10 +12684,10 @@ template<typename BasicJsonType> struct internal_iterator
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
// forward declare, to be able to friend it later on
template<typename IteratorType> class iteration_proxy;
template<typename IteratorType> class iteration_proxy_value;
@@ -11418,9 +12724,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
// make sure BasicJsonType is basic_json or const basic_json
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
"iter_impl only accepts (const) basic_json");
+ // superficial check for the LegacyBidirectionalIterator named requirement
+ static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
+ && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
+ "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
public:
-
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
/// A user-defined iterator should provide publicly accessible typedefs named
@@ -11652,7 +12961,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
}
case value_t::null:
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
case value_t::string:
case value_t::boolean:
@@ -11668,7 +12977,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return *m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -11710,7 +13019,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -11719,7 +13028,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- iter_impl const operator++(int) // NOLINT(readability-const-return-type)
+ iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
++(*this);
@@ -11770,7 +13079,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- iter_impl const operator--(int) // NOLINT(readability-const-return-type)
+ iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
--(*this);
@@ -11827,7 +13136,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
- JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
}
JSON_ASSERT(m_object != nullptr);
@@ -11872,7 +13181,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
- JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
}
JSON_ASSERT(m_object != nullptr);
@@ -11880,7 +13189,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
case value_t::array:
return (m_it.array_iterator < other.m_it.array_iterator);
@@ -11936,7 +13245,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
case value_t::array:
{
@@ -12015,7 +13324,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
case value_t::array:
return m_it.array_iterator - other.m_it.array_iterator;
@@ -12044,13 +13353,13 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
case value_t::array:
return *std::next(m_it.array_iterator, n);
case value_t::null:
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
case value_t::string:
case value_t::boolean:
@@ -12066,7 +13375,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return *m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -12084,7 +13393,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return m_it.object_iterator->first;
}
- JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
}
/*!
@@ -12102,22 +13411,34 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
/// the actual iterator of the associated instance
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
};
-} // namespace detail
-} // namespace nlohmann
+
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <cstddef> // ptrdiff_t
#include <iterator> // reverse_iterator
#include <utility> // declval
-namespace nlohmann
-{
+// #include <nlohmann/detail/abi_macros.hpp>
+
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
//////////////////////
// reverse_iterator //
//////////////////////
@@ -12158,7 +13479,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++)
- json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
+ json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
{
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
}
@@ -12170,7 +13491,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
}
/// post-decrement (it--)
- json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
+ json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
{
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
}
@@ -12225,16 +13546,30 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
return it.operator * ();
}
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
// #include <nlohmann/detail/json_pointer.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // all_of
#include <cctype> // isdigit
+#include <cerrno> // errno, ERANGE
+#include <cstdlib> // strtoull
+#ifndef JSON_NO_IO
+ #include <iosfwd> // ostream
+#endif // JSON_NO_IO
#include <limits> // max
#include <numeric> // accumulate
#include <string> // string
@@ -12245,49 +13580,79 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+
// #include <nlohmann/detail/string_escape.hpp>
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
-template<typename BasicJsonType>
+template<typename RefStringType>
class json_pointer
{
// allow basic_json to access private members
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json;
+ template<typename>
+ friend class json_pointer;
+
+ template<typename T>
+ struct string_t_helper
+ {
+ using type = T;
+ };
+
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
+ {
+ using type = StringType;
+ };
+
public:
+ // for backwards compatibility accept BasicJsonType
+ using string_t = typename string_t_helper<RefStringType>::type;
+
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
- explicit json_pointer(const std::string& s = "")
+ explicit json_pointer(const string_t& s = "")
: reference_tokens(split(s))
{}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
- std::string to_string() const
+ string_t to_string() const
{
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
- std::string{},
- [](const std::string & a, const std::string & b)
+ string_t{},
+ [](const string_t& a, const string_t& b)
{
- return a + "/" + detail::escape(b);
+ return detail::concat(a, '/', detail::escape(b));
});
}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
- operator std::string() const
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
+ operator string_t() const
{
return to_string();
}
+#ifndef JSON_NO_IO
+ /// @brief write string representation of the JSON pointer to stream
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
+ friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
+ {
+ o << ptr.to_string();
+ return o;
+ }
+#endif
+
/// @brief append another JSON pointer at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
json_pointer& operator/=(const json_pointer& ptr)
@@ -12300,7 +13665,7 @@ class json_pointer
/// @brief append an unescaped reference token at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
- json_pointer& operator/=(std::string token)
+ json_pointer& operator/=(string_t token)
{
push_back(std::move(token));
return *this;
@@ -12323,7 +13688,7 @@ class json_pointer
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
- friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
+ friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
{
return json_pointer(lhs) /= std::move(token);
}
@@ -12355,7 +13720,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
reference_tokens.pop_back();
@@ -12363,11 +13728,11 @@ class json_pointer
/// @brief return last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/back/
- const std::string& back() const
+ const string_t& back() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
return reference_tokens.back();
@@ -12375,14 +13740,14 @@ class json_pointer
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
- void push_back(const std::string& token)
+ void push_back(const string_t& token)
{
reference_tokens.push_back(token);
}
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
- void push_back(std::string&& token)
+ void push_back(string_t&& token)
{
reference_tokens.push_back(std::move(token));
}
@@ -12405,44 +13770,39 @@ class json_pointer
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.410 if an array index exceeds size_type
*/
- static typename BasicJsonType::size_type array_index(const std::string& s)
+ template<typename BasicJsonType>
+ static typename BasicJsonType::size_type array_index(const string_t& s)
{
using size_type = typename BasicJsonType::size_type;
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
{
- JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
{
- JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
- }
-
- std::size_t processed_chars = 0;
- unsigned long long res = 0; // NOLINT(runtime/int)
- JSON_TRY
- {
- res = std::stoull(s, &processed_chars);
- }
- JSON_CATCH(std::out_of_range&)
- {
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
}
- // check if the string was completely read
- if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
+ const char* p = s.c_str();
+ char* p_end = nullptr;
+ errno = 0; // strtoull doesn't reset errno
+ unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
+ if (p == p_end // invalid input or empty string
+ || errno == ERANGE // out of range
+ || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
{
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
}
// only triggered on special platforms (like 32bit), see also
// https://github.com/nlohmann/json/pull/2203
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
{
- JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
+ JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
}
return static_cast<size_type>(res);
@@ -12453,7 +13813,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
json_pointer result = *this;
@@ -12470,6 +13830,7 @@ class json_pointer
@throw parse_error.109 if array index is not a number
@throw type_error.313 if value cannot be unflattened
*/
+ template<typename BasicJsonType>
BasicJsonType& get_and_create(BasicJsonType& j) const
{
auto* result = &j;
@@ -12505,7 +13866,7 @@ class json_pointer
case detail::value_t::array:
{
// create an entry in the array
- result = &result->operator[](array_index(reference_token));
+ result = &result->operator[](array_index<BasicJsonType>(reference_token));
break;
}
@@ -12523,7 +13884,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
+ JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
}
}
@@ -12549,6 +13910,7 @@ class json_pointer
@throw parse_error.109 if an array index was not a number
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template<typename BasicJsonType>
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -12589,7 +13951,7 @@ class json_pointer
else
{
// convert array index to number; unchecked access
- ptr = &ptr->operator[](array_index(reference_token));
+ ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
}
break;
}
@@ -12603,7 +13965,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -12616,6 +13978,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template<typename BasicJsonType>
BasicJsonType& get_checked(BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -12634,13 +13997,13 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
- JSON_THROW(detail::out_of_range::create(402,
- "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
- ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat(
+ "array index '-' (", std::to_string(ptr->m_value.array->size()),
+ ") is out of range"), ptr));
}
// note: at performs range check
- ptr = &ptr->at(array_index(reference_token));
+ ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
break;
}
@@ -12653,7 +14016,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -12673,6 +14036,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template<typename BasicJsonType>
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -12691,11 +14055,11 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" cannot be used for const access
- JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
}
// use unchecked array access
- ptr = &ptr->operator[](array_index(reference_token));
+ ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
break;
}
@@ -12708,7 +14072,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -12721,6 +14085,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template<typename BasicJsonType>
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -12739,13 +14104,13 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
- JSON_THROW(detail::out_of_range::create(402,
- "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
- ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat(
+ "array index '-' (", std::to_string(ptr->m_value.array->size()),
+ ") is out of range"), ptr));
}
// note: at performs range check
- ptr = &ptr->at(array_index(reference_token));
+ ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
break;
}
@@ -12758,7 +14123,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -12769,6 +14134,7 @@ class json_pointer
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
*/
+ template<typename BasicJsonType>
bool contains(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -12816,7 +14182,7 @@ class json_pointer
}
}
- const auto idx = array_index(reference_token);
+ const auto idx = array_index<BasicJsonType>(reference_token);
if (idx >= ptr->size())
{
// index out of range
@@ -12857,9 +14223,9 @@ class json_pointer
@throw parse_error.107 if the pointer is not empty or begins with '/'
@throw parse_error.108 if character '~' is not followed by '0' or '1'
*/
- static std::vector<std::string> split(const std::string& reference_string)
+ static std::vector<string_t> split(const string_t& reference_string)
{
- std::vector<std::string> result;
+ std::vector<string_t> result;
// special case: empty reference string -> no reference tokens
if (reference_string.empty())
@@ -12870,7 +14236,7 @@ class json_pointer
// check if nonempty reference string begins with slash
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
{
- JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
}
// extract the reference tokens:
@@ -12881,11 +14247,11 @@ class json_pointer
std::size_t slash = reference_string.find_first_of('/', 1),
// set the beginning of the first reference token
start = 1;
- // we can stop if start == 0 (if slash == std::string::npos)
+ // we can stop if start == 0 (if slash == string_t::npos)
start != 0;
// set the beginning of the next reference token
- // (will eventually be 0 if slash == std::string::npos)
- start = (slash == std::string::npos) ? 0 : slash + 1,
+ // (will eventually be 0 if slash == string_t::npos)
+ start = (slash == string_t::npos) ? 0 : slash + 1,
// find next slash
slash = reference_string.find_first_of('/', start))
{
@@ -12895,7 +14261,7 @@ class json_pointer
// check reference tokens are properly escaped
for (std::size_t pos = reference_token.find_first_of('~');
- pos != std::string::npos;
+ pos != string_t::npos;
pos = reference_token.find_first_of('~', pos + 1))
{
JSON_ASSERT(reference_token[pos] == '~');
@@ -12905,7 +14271,7 @@ class json_pointer
(reference_token[pos + 1] != '0' &&
reference_token[pos + 1] != '1')))
{
- JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
}
}
@@ -12925,7 +14291,8 @@ class json_pointer
@note Empty objects or arrays are flattened to `null`.
*/
- static void flatten(const std::string& reference_string,
+ template<typename BasicJsonType>
+ static void flatten(const string_t& reference_string,
const BasicJsonType& value,
BasicJsonType& result)
{
@@ -12943,7 +14310,7 @@ class json_pointer
// iterate array and use index as reference string
for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
{
- flatten(reference_string + "/" + std::to_string(i),
+ flatten(detail::concat(reference_string, '/', std::to_string(i)),
value.m_value.array->operator[](i), result);
}
}
@@ -12962,7 +14329,7 @@ class json_pointer
// iterate object and use keys as reference string
for (const auto& element : *value.m_value.object)
{
- flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
+ flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
}
}
break;
@@ -12995,12 +14362,13 @@ class json_pointer
@throw type_error.315 if object values are not primitive
@throw type_error.313 if value cannot be unflattened
*/
+ template<typename BasicJsonType>
static BasicJsonType
unflatten(const BasicJsonType& value)
{
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
{
- JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
+ JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
}
BasicJsonType result;
@@ -13010,7 +14378,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
{
- JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
+ JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
}
// assign value to reference pointed to by JSON pointer; Note that if
@@ -13023,6 +14391,21 @@ class json_pointer
return result;
}
+ // can't use conversion operator because of ambiguity
+ json_pointer<string_t> convert() const&
+ {
+ json_pointer<string_t> result;
+ result.reference_tokens = reference_tokens;
+ return result;
+ }
+
+ json_pointer<string_t> convert()&&
+ {
+ json_pointer<string_t> result;
+ result.reference_tokens = std::move(reference_tokens);
+ return result;
+ }
+
/*!
@brief compares two JSON pointers for equality
@@ -13034,11 +14417,10 @@ class json_pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
- friend bool operator==(json_pointer const& lhs,
- json_pointer const& rhs) noexcept
- {
- return lhs.reference_tokens == rhs.reference_tokens;
- }
+ template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+ // NOLINTNEXTLINE(readability-redundant-declaration)
+ friend bool operator==(json_pointer<RefStringTypeLhs> const& lhs,
+ json_pointer<RefStringTypeRhs> const& rhs) noexcept;
/*!
@brief compares two JSON pointers for inequality
@@ -13051,30 +14433,55 @@ class json_pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
- friend bool operator!=(json_pointer const& lhs,
- json_pointer const& rhs) noexcept
- {
- return !(lhs == rhs);
- }
+ template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+ // NOLINTNEXTLINE(readability-redundant-declaration)
+ friend bool operator!=(json_pointer<RefStringTypeLhs> const& lhs,
+ json_pointer<RefStringTypeRhs> const& rhs) noexcept;
/// the reference tokens
- std::vector<std::string> reference_tokens;
+ std::vector<string_t> reference_tokens;
};
-} // namespace nlohmann
+
+// functions cannot be defined inside class due to ODR violations
+template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+inline bool operator==(json_pointer<RefStringTypeLhs> const& lhs,
+ json_pointer<RefStringTypeRhs> const& rhs) noexcept
+{
+ return lhs.reference_tokens == rhs.reference_tokens;
+}
+
+template<typename RefStringTypeLhs, typename RefStringTypeRhs>
+inline bool operator!=(json_pointer<RefStringTypeLhs> const& lhs,
+ json_pointer<RefStringTypeRhs> const& rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/json_ref.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <initializer_list>
#include <utility>
+// #include <nlohmann/detail/abi_macros.hpp>
+
// #include <nlohmann/detail/meta/type_traits.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
template<typename BasicJsonType>
class json_ref
{
@@ -13130,11 +14537,14 @@ class json_ref
mutable value_type owned_value = nullptr;
value_type const* value_ref = nullptr;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+
// #include <nlohmann/detail/string_escape.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
@@ -13142,22 +14552,40 @@ class json_ref
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/output/binary_writer.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // reverse
#include <array> // array
+#include <map> // map
#include <cmath> // isnan, isinf
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <cstring> // memcpy
#include <limits> // numeric_limits
#include <string> // string
#include <utility> // move
+#include <vector> // vector
// #include <nlohmann/detail/input/binary_reader.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/output/output_adapters.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // copy
@@ -13175,10 +14603,10 @@ class json_ref
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
/// abstract output adapter interface
template<typename CharType> struct output_adapter_protocol
{
@@ -13214,7 +14642,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
- std::copy(s, s + length, std::back_inserter(v));
+ v.insert(v.end(), s, s + length);
}
private:
@@ -13295,14 +14723,17 @@ class output_adapter
private:
output_adapter_t<CharType> oa = nullptr;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
+// #include <nlohmann/detail/string_concat.hpp>
-namespace nlohmann
-{
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
///////////////////
// binary writer //
///////////////////
@@ -13353,7 +14784,7 @@ class binary_writer
case value_t::discarded:
default:
{
- JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
}
}
}
@@ -14009,9 +15440,11 @@ class binary_writer
@param[in] use_count whether to use '#' prefixes (optimized format)
@param[in] use_type whether to use '$' prefixes (optimized format)
@param[in] add_prefix whether prefixes need to be used for this value
+ @param[in] use_bjdata whether write in BJData format, default is false
*/
void write_ubjson(const BasicJsonType& j, const bool use_count,
- const bool use_type, const bool add_prefix = true)
+ const bool use_type, const bool add_prefix = true,
+ const bool use_bjdata = false)
{
switch (j.type())
{
@@ -14037,19 +15470,19 @@ class binary_writer
case value_t::number_integer:
{
- write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
+ write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
break;
}
case value_t::number_unsigned:
{
- write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
+ write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
break;
}
case value_t::number_float:
{
- write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
+ write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
break;
}
@@ -14059,7 +15492,7 @@ class binary_writer
{
oa->write_character(to_char_type('S'));
}
- write_number_with_ubjson_prefix(j.m_value.string->size(), true);
+ write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size());
@@ -14077,14 +15510,16 @@ class binary_writer
if (use_type && !j.m_value.array->empty())
{
JSON_ASSERT(use_count);
- const CharType first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
- [this, first_prefix](const BasicJsonType & v)
+ [this, first_prefix, use_bjdata](const BasicJsonType & v)
{
- return ubjson_prefix(v) == first_prefix;
+ return ubjson_prefix(v, use_bjdata) == first_prefix;
});
- if (same_prefix)
+ std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
+
+ if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
{
prefix_required = false;
oa->write_character(to_char_type('$'));
@@ -14095,12 +15530,12 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
- write_number_with_ubjson_prefix(j.m_value.array->size(), true);
+ write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
}
for (const auto& el : *j.m_value.array)
{
- write_ubjson(el, use_count, use_type, prefix_required);
+ write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
}
if (!use_count)
@@ -14128,7 +15563,7 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
- write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
+ write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
}
if (use_type)
@@ -14156,6 +15591,14 @@ class binary_writer
case value_t::object:
{
+ if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
+ {
+ if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
+ {
+ break;
+ }
+ }
+
if (add_prefix)
{
oa->write_character(to_char_type('{'));
@@ -14165,14 +15608,16 @@ class binary_writer
if (use_type && !j.m_value.object->empty())
{
JSON_ASSERT(use_count);
- const CharType first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin(), j.end(),
- [this, first_prefix](const BasicJsonType & v)
+ [this, first_prefix, use_bjdata](const BasicJsonType & v)
{
- return ubjson_prefix(v) == first_prefix;
+ return ubjson_prefix(v, use_bjdata) == first_prefix;
});
- if (same_prefix)
+ std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
+
+ if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
{
prefix_required = false;
oa->write_character(to_char_type('$'));
@@ -14183,16 +15628,16 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
- write_number_with_ubjson_prefix(j.m_value.object->size(), true);
+ write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
}
for (const auto& el : *j.m_value.object)
{
- write_number_with_ubjson_prefix(el.first.size(), true);
+ write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
oa->write_characters(
reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size());
- write_ubjson(el.second, use_count, use_type, prefix_required);
+ write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
}
if (!use_count)
@@ -14223,7 +15668,7 @@ class binary_writer
const auto it = name.find(static_cast<typename string_t::value_type>(0));
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
{
- JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
+ JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
static_cast<void>(j);
}
@@ -14259,7 +15704,7 @@ class binary_writer
const double value)
{
write_bson_entry_header(name, 0x01);
- write_number<double, true>(value);
+ write_number<double>(value, true);
}
/*!
@@ -14278,7 +15723,7 @@ class binary_writer
{
write_bson_entry_header(name, 0x02);
- write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
+ write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
oa->write_characters(
reinterpret_cast<const CharType*>(value.c_str()),
value.size() + 1);
@@ -14311,12 +15756,12 @@ class binary_writer
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
{
write_bson_entry_header(name, 0x10); // int32
- write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
+ write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
}
else
{
write_bson_entry_header(name, 0x12); // int64
- write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
+ write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
}
}
@@ -14339,16 +15784,16 @@ class binary_writer
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
write_bson_entry_header(name, 0x10 /* int32 */);
- write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
+ write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
}
else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
write_bson_entry_header(name, 0x12 /* int64 */);
- write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
+ write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
}
else
{
- JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
+ JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
}
}
@@ -14392,7 +15837,7 @@ class binary_writer
const typename BasicJsonType::array_t& value)
{
write_bson_entry_header(name, 0x04); // array
- write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
+ write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
std::size_t array_index = 0ul;
@@ -14412,7 +15857,7 @@ class binary_writer
{
write_bson_entry_header(name, 0x05);
- write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
+ write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
@@ -14534,7 +15979,7 @@ class binary_writer
*/
void write_bson_object(const typename BasicJsonType::object_t& value)
{
- write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
+ write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
for (const auto& el : value)
{
@@ -14580,20 +16025,22 @@ class binary_writer
template<typename NumberType, typename std::enable_if<
std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n,
- const bool add_prefix)
+ const bool add_prefix,
+ const bool use_bjdata)
{
if (add_prefix)
{
oa->write_character(get_ubjson_float_prefix(n));
}
- write_number(n);
+ write_number(n, use_bjdata);
}
// UBJSON: write number (unsigned integer)
template<typename NumberType, typename std::enable_if<
std::is_unsigned<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n,
- const bool add_prefix)
+ const bool add_prefix,
+ const bool use_bjdata)
{
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
@@ -14601,7 +16048,7 @@ class binary_writer
{
oa->write_character(to_char_type('i')); // int8
}
- write_number(static_cast<std::uint8_t>(n));
+ write_number(static_cast<std::uint8_t>(n), use_bjdata);
}
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
{
@@ -14609,7 +16056,7 @@ class binary_writer
{
oa->write_character(to_char_type('U')); // uint8
}
- write_number(static_cast<std::uint8_t>(n));
+ write_number(static_cast<std::uint8_t>(n), use_bjdata);
}
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{
@@ -14617,7 +16064,15 @@ class binary_writer
{
oa->write_character(to_char_type('I')); // int16
}
- write_number(static_cast<std::int16_t>(n));
+ write_number(static_cast<std::int16_t>(n), use_bjdata);
+ }
+ else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('u')); // uint16 - bjdata only
+ }
+ write_number(static_cast<std::uint16_t>(n), use_bjdata);
}
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
@@ -14625,7 +16080,15 @@ class binary_writer
{
oa->write_character(to_char_type('l')); // int32
}
- write_number(static_cast<std::int32_t>(n));
+ write_number(static_cast<std::int32_t>(n), use_bjdata);
+ }
+ else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('m')); // uint32 - bjdata only
+ }
+ write_number(static_cast<std::uint32_t>(n), use_bjdata);
}
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
@@ -14633,7 +16096,15 @@ class binary_writer
{
oa->write_character(to_char_type('L')); // int64
}
- write_number(static_cast<std::int64_t>(n));
+ write_number(static_cast<std::int64_t>(n), use_bjdata);
+ }
+ else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('M')); // uint64 - bjdata only
+ }
+ write_number(static_cast<std::uint64_t>(n), use_bjdata);
}
else
{
@@ -14643,7 +16114,7 @@ class binary_writer
}
const auto number = BasicJsonType(n).dump();
- write_number_with_ubjson_prefix(number.size(), true);
+ write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i)
{
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@@ -14656,7 +16127,8 @@ class binary_writer
std::is_signed<NumberType>::value&&
!std::is_floating_point<NumberType>::value, int >::type = 0 >
void write_number_with_ubjson_prefix(const NumberType n,
- const bool add_prefix)
+ const bool add_prefix,
+ const bool use_bjdata)
{
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
{
@@ -14664,7 +16136,7 @@ class binary_writer
{
oa->write_character(to_char_type('i')); // int8
}
- write_number(static_cast<std::int8_t>(n));
+ write_number(static_cast<std::int8_t>(n), use_bjdata);
}
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)()))
{
@@ -14672,7 +16144,7 @@ class binary_writer
{
oa->write_character(to_char_type('U')); // uint8
}
- write_number(static_cast<std::uint8_t>(n));
+ write_number(static_cast<std::uint8_t>(n), use_bjdata);
}
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
{
@@ -14680,7 +16152,15 @@ class binary_writer
{
oa->write_character(to_char_type('I')); // int16
}
- write_number(static_cast<std::int16_t>(n));
+ write_number(static_cast<std::int16_t>(n), use_bjdata);
+ }
+ else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('u')); // uint16 - bjdata only
+ }
+ write_number(static_cast<uint16_t>(n), use_bjdata);
}
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
{
@@ -14688,7 +16168,15 @@ class binary_writer
{
oa->write_character(to_char_type('l')); // int32
}
- write_number(static_cast<std::int32_t>(n));
+ write_number(static_cast<std::int32_t>(n), use_bjdata);
+ }
+ else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('m')); // uint32 - bjdata only
+ }
+ write_number(static_cast<uint32_t>(n), use_bjdata);
}
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
{
@@ -14696,7 +16184,7 @@ class binary_writer
{
oa->write_character(to_char_type('L')); // int64
}
- write_number(static_cast<std::int64_t>(n));
+ write_number(static_cast<std::int64_t>(n), use_bjdata);
}
// LCOV_EXCL_START
else
@@ -14707,7 +16195,7 @@ class binary_writer
}
const auto number = BasicJsonType(n).dump();
- write_number_with_ubjson_prefix(number.size(), true);
+ write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i)
{
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@@ -14719,7 +16207,7 @@ class binary_writer
/*!
@brief determine the type prefix of container values
*/
- CharType ubjson_prefix(const BasicJsonType& j) const noexcept
+ CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
{
switch (j.type())
{
@@ -14743,10 +16231,18 @@ class binary_writer
{
return 'I';
}
+ if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
+ {
+ return 'u';
+ }
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)())
{
return 'l';
}
+ if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
+ {
+ return 'm';
+ }
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)())
{
return 'L';
@@ -14769,14 +16265,26 @@ class binary_writer
{
return 'I';
}
+ if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
+ {
+ return 'u';
+ }
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
return 'l';
}
+ if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
+ {
+ return 'm';
+ }
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
return 'L';
}
+ if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ return 'M';
+ }
// anything else is treated as high-precision number
return 'H'; // LCOV_EXCL_LINE
}
@@ -14810,6 +16318,118 @@ class binary_writer
return 'D'; // float 64
}
+ /*!
+ @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
+ */
+ bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
+ {
+ std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
+ {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
+ };
+
+ string_t key = "_ArrayType_";
+ auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
+ if (it == bjdtype.end())
+ {
+ return true;
+ }
+ CharType dtype = it->second;
+
+ key = "_ArraySize_";
+ std::size_t len = (value.at(key).empty() ? 0 : 1);
+ for (const auto& el : value.at(key))
+ {
+ len *= static_cast<std::size_t>(el.m_value.number_unsigned);
+ }
+
+ key = "_ArrayData_";
+ if (value.at(key).size() != len)
+ {
+ return true;
+ }
+
+ oa->write_character('[');
+ oa->write_character('$');
+ oa->write_character(dtype);
+ oa->write_character('#');
+
+ key = "_ArraySize_";
+ write_ubjson(value.at(key), use_count, use_type, true, true);
+
+ key = "_ArrayData_";
+ if (dtype == 'U' || dtype == 'C')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
+ }
+ }
+ else if (dtype == 'i')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
+ }
+ }
+ else if (dtype == 'u')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
+ }
+ }
+ else if (dtype == 'I')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
+ }
+ }
+ else if (dtype == 'm')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
+ }
+ }
+ else if (dtype == 'l')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
+ }
+ }
+ else if (dtype == 'M')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
+ }
+ }
+ else if (dtype == 'L')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
+ }
+ }
+ else if (dtype == 'd')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<float>(el.m_value.number_float), true);
+ }
+ }
+ else if (dtype == 'D')
+ {
+ for (const auto& el : value.at(key))
+ {
+ write_number(static_cast<double>(el.m_value.number_float), true);
+ }
+ }
+ return false;
+ }
+
///////////////////////
// Utility functions //
///////////////////////
@@ -14817,16 +16437,18 @@ class binary_writer
/*
@brief write a number to output input
@param[in] n number of type @a NumberType
- @tparam NumberType the type of the number
- @tparam OutputIsLittleEndian Set to true if output data is
+ @param[in] OutputIsLittleEndian Set to true if output data is
required to be little endian
+ @tparam NumberType the type of the number
@note This function needs to respect the system's endianness, because bytes
in CBOR, MessagePack, and UBJSON are stored in network order (big
endian) and therefore need reordering on little endian systems.
+ On the other hand, BSON and BJData use little endian and should reorder
+ on big endian systems.
*/
- template<typename NumberType, bool OutputIsLittleEndian = false>
- void write_number(const NumberType n)
+ template<typename NumberType>
+ void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
{
// step 1: write number to array of length NumberType
std::array<CharType, sizeof(NumberType)> vec{};
@@ -14917,12 +16539,22 @@ class binary_writer
/// the output
output_adapter_t<CharType> oa = nullptr;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/output/output_adapters.hpp>
// #include <nlohmann/detail/output/serializer.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <algorithm> // reverse, remove, fill, find, none_of
@@ -14935,11 +16567,19 @@ class binary_writer
#include <limits> // numeric_limits
#include <string> // string, char_traits
#include <iomanip> // setfill, setw
-#include <sstream> // stringstream
#include <type_traits> // is_same
#include <utility> // move
// #include <nlohmann/detail/conversions/to_chars.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#include <array> // array
@@ -14952,8 +16592,7 @@ class binary_writer
// #include <nlohmann/detail/macro_scope.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -15982,7 +17621,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
return append_exponent(buf, n - 1);
}
-} // namespace dtoa_impl
+} // namespace dtoa_impl
/*!
@brief generates a decimal representation of the floating-point number value in [first, last).
@@ -16049,8 +17688,8 @@ char* to_chars(char* first, const char* last, FloatType value)
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
}
-} // namespace detail
-} // namespace nlohmann
+} // namespace detail
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/exceptions.hpp>
@@ -16062,13 +17701,15 @@ char* to_chars(char* first, const char* last, FloatType value)
// #include <nlohmann/detail/output/output_adapters.hpp>
+// #include <nlohmann/detail/string_concat.hpp>
+
// #include <nlohmann/detail/value_t.hpp>
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+
///////////////////
// serialization //
///////////////////
@@ -16544,9 +18185,7 @@ class serializer
{
case error_handler_t::strict:
{
- std::stringstream ss;
- ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
- JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
+ JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
}
case error_handler_t::ignore:
@@ -16638,9 +18277,7 @@ class serializer
{
case error_handler_t::strict:
{
- std::stringstream ss;
- ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
- JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
+ JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
}
case error_handler_t::ignore:
@@ -16707,6 +18344,20 @@ class serializer
}
}
+ /*!
+ * @brief convert a byte to a uppercase hex representation
+ * @param[in] byte byte to represent
+ * @return representation ("00".."FF")
+ */
+ static std::string hex_bytes(std::uint8_t byte)
+ {
+ std::string result = "FF";
+ constexpr const char* nibble_to_hex = "0123456789ABCDEF";
+ result[0] = nibble_to_hex[byte / 16];
+ result[1] = nibble_to_hex[byte % 16];
+ return result;
+ }
+
// templates to avoid warnings about useless casts
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
bool is_negative_number(NumberType x)
@@ -17007,17 +18658,26 @@ class serializer
/// error_handler how to react on decoding errors
const error_handler_t error_handler;
};
+
} // namespace detail
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/value_t.hpp>
// #include <nlohmann/json_fwd.hpp>
// #include <nlohmann/ordered_map.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
-#include <functional> // less
+#include <functional> // equal_to, less
#include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator
@@ -17028,9 +18688,10 @@ class serializer
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/meta/type_traits.hpp>
-namespace nlohmann
-{
+
+NLOHMANN_JSON_NAMESPACE_BEGIN
/// ordered_map: a minimal map-like container that preserves insertion order
/// for use within nlohmann::basic_json<ordered_map>
@@ -17045,44 +18706,94 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
using const_iterator = typename Container::const_iterator;
using size_type = typename Container::size_type;
using value_type = typename Container::value_type;
+#ifdef JSON_HAS_CPP_14
+ using key_compare = std::equal_to<>;
+#else
+ using key_compare = std::equal_to<Key>;
+#endif
// Explicit constructors instead of `using Container::Container`
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
- ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
+ ordered_map() noexcept(noexcept(Container())) : Container{} {}
+ explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
template <class It>
ordered_map(It first, It last, const Allocator& alloc = Allocator())
: Container{first, last, alloc} {}
- ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
+ ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return {it, false};
}
}
- Container::emplace_back(key, t);
- return {--this->end(), true};
+ Container::emplace_back(key, std::forward<T>(t));
+ return {std::prev(this->end()), true};
+ }
+
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ std::pair<iterator, bool> emplace(KeyType && key, T && t)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ return {it, false};
+ }
+ }
+ Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
+ return {std::prev(this->end()), true};
}
- T& operator[](const Key& key)
+ T& operator[](const key_type& key)
{
return emplace(key, T{}).first->second;
}
- const T& operator[](const Key& key) const
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ T & operator[](KeyType && key)
+ {
+ return emplace(std::forward<KeyType>(key), T{}).first->second;
+ }
+
+ const T& operator[](const key_type& key) const
{
return at(key);
}
- T& at(const Key& key)
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ const T & operator[](KeyType && key) const
+ {
+ return at(std::forward<KeyType>(key));
+ }
+
+ T& at(const key_type& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ return it->second;
+ }
+ }
+
+ JSON_THROW(std::out_of_range("key not found"));
+ }
+
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ T & at(KeyType && key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return it->second;
}
@@ -17091,11 +18802,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
JSON_THROW(std::out_of_range("key not found"));
}
- const T& at(const Key& key) const
+ const T& at(const key_type& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return it->second;
}
@@ -17104,11 +18815,47 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
JSON_THROW(std::out_of_range("key not found"));
}
- size_type erase(const Key& key)
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ const T & at(KeyType && key) const
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ return it->second;
+ }
+ }
+
+ JSON_THROW(std::out_of_range("key not found"));
+ }
+
+ size_type erase(const key_type& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ // Since we cannot move const Keys, re-construct them in place
+ for (auto next = it; ++next != this->end(); ++it)
+ {
+ it->~value_type(); // Destroy but keep allocation
+ new (&*it) value_type{std::move(*next)};
+ }
+ Container::pop_back();
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ size_type erase(KeyType && key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
// Since we cannot move const Keys, re-construct them in place
for (auto next = it; ++next != this->end(); ++it)
@@ -17130,6 +18877,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
iterator erase(iterator first, iterator last)
{
+ if (first == last)
+ {
+ return first;
+ }
+
const auto elements_affected = std::distance(first, last);
const auto offset = std::distance(Container::begin(), first);
@@ -17176,11 +18928,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
return Container::begin() + offset;
}
- size_type count(const Key& key) const
+ size_type count(const key_type& key) const
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ size_type count(KeyType && key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return 1;
}
@@ -17188,11 +18954,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
return 0;
}
- iterator find(const Key& key)
+ iterator find(const key_type& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (m_compare(it->first, key))
+ {
+ return it;
+ }
+ }
+ return Container::end();
+ }
+
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
+ iterator find(KeyType && key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return it;
}
@@ -17200,11 +18980,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
return Container::end();
}
- const_iterator find(const Key& key) const
+ const_iterator find(const key_type& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == key)
+ if (m_compare(it->first, key))
{
return it;
}
@@ -17221,7 +19001,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
{
for (auto it = this->begin(); it != this->end(); ++it)
{
- if (it->first == value.first)
+ if (m_compare(it->first, value.first))
{
return {it, false};
}
@@ -17242,12 +19022,16 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
insert(*it);
}
}
+
+private:
+ JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
};
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
#if defined(JSON_HAS_CPP_17)
+ #include <any>
#include <string_view>
#endif
@@ -17256,8 +19040,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
@see https://github.com/nlohmann
@since version 1.0.0
*/
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief a class to store JSON values
@@ -17282,7 +19065,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
private:
template<detail::value_t> friend struct detail::external_constructor;
- friend ::nlohmann::json_pointer<basic_json>;
+
+ template<typename>
+ friend class ::nlohmann::json_pointer;
+ // can be restored when json_pointer backwards compatibility is removed
+ // friend ::nlohmann::json_pointer<StringType>;
template<typename BasicJsonType, typename InputType>
friend class ::nlohmann::detail::parser;
@@ -17341,7 +19128,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
public:
using value_t = detail::value_t;
/// JSON Pointer, see @ref nlohmann::json_pointer
- using json_pointer = ::nlohmann::json_pointer<basic_json>;
+ using json_pointer = ::nlohmann::json_pointer<StringType>;
template<typename T, typename SFINAE>
using json_serializer = JSONSerializer<T, SFINAE>;
/// how to treat decoding errors
@@ -17433,9 +19220,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result["name"] = "JSON for Modern C++";
result["url"] = "https://github.com/nlohmann/json";
result["version"]["string"] =
- std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
- std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
- std::to_string(NLOHMANN_JSON_VERSION_PATCH);
+ detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
+ std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
+ std::to_string(NLOHMANN_JSON_VERSION_PATCH));
result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
@@ -17457,7 +19244,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#elif defined(__clang__)
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
#elif defined(__GNUC__) || defined(__GNUG__)
- result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+ result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
+ std::to_string(__GNUC__), '.',
+ std::to_string(__GNUC_MINOR__), '.',
+ std::to_string(__GNUC_PATCHLEVEL__))
+ }
+ };
#elif defined(__HP_cc) || defined(__HP_aCC)
result["compiler"] = "hp"
#elif defined(__IBMCPP__)
@@ -17472,7 +19264,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
#endif
-#ifdef __cplusplus
+
+#if defined(_MSVC_LANG)
+ result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
+#elif defined(__cplusplus)
result["compiler"]["c++"] = std::to_string(__cplusplus);
#else
result["compiler"]["c++"] = "unknown";
@@ -17490,21 +19285,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// the template arguments passed to class @ref basic_json.
/// @{
- /// @brief object key comparator type
- /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
+ /// @brief default object key comparator type
+ /// The actual object key comparator type (@ref object_comparator_t) may be
+ /// different.
+ /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
#if defined(JSON_HAS_CPP_14)
- // Use transparent comparator if possible, combined with perfect forwarding
- // on find() and count() calls prevents unnecessary string construction.
- using object_comparator_t = std::less<>;
+ // use of transparent comparator avoids unnecessary repeated construction of temporaries
+ // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
+ using default_object_comparator_t = std::less<>;
#else
- using object_comparator_t = std::less<StringType>;
+ using default_object_comparator_t = std::less<StringType>;
#endif
/// @brief a type for an object
/// @sa https://json.nlohmann.me/api/basic_json/object_t/
using object_t = ObjectType<StringType,
basic_json,
- object_comparator_t,
+ default_object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>;
@@ -17536,6 +19333,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/binary_t/
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
+ /// @brief object key comparator type
+ /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
+ using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
+
/// @}
private:
@@ -17682,7 +19483,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
object = nullptr; // silence warning, see #821
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
{
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.0", nullptr)); // LCOV_EXCL_LINE
}
break;
}
@@ -17978,7 +19779,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief create a null object
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(std::nullptr_t = nullptr) noexcept
+ basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
: basic_json(value_t::null)
{
assert_invariant();
@@ -18050,6 +19851,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
+ JSON_ASSERT(m_type == val.type());
set_parents();
assert_invariant();
}
@@ -18080,7 +19882,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// if object is wanted but impossible, throw an exception
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
{
- JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
+ JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
}
}
@@ -18192,7 +19994,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
+ JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
}
// copy type from first iterator
@@ -18210,7 +20012,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
}
break;
}
@@ -18279,7 +20081,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
+ JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
}
set_parents();
@@ -18563,7 +20365,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.boolean;
}
- JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
}
/// get a pointer to the value (object)
@@ -18684,7 +20486,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return *ptr;
}
- JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
+ JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
}
public:
@@ -19034,14 +20836,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < typename ValueType, typename std::enable_if <
detail::conjunction <
detail::negation<std::is_pointer<ValueType>>,
+ detail::negation<std::is_same<ValueType, std::nullptr_t>>,
detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
detail::negation<detail::is_basic_json<ValueType>>,
detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
-
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
detail::negation<std::is_same<ValueType, std::string_view>>,
#endif
+#if defined(JSON_HAS_CPP_17)
+ detail::negation<std::is_same<ValueType, std::any>>,
+#endif
detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
>::value, int >::type = 0 >
JSON_EXPLICIT operator ValueType() const
@@ -19056,7 +20861,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (!is_binary())
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
}
return *get_ptr<binary_t*>();
@@ -19068,7 +20873,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (!is_binary())
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
}
return *get_ptr<const binary_t*>();
@@ -19099,12 +20904,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -19122,12 +20927,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -19136,22 +20941,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
reference at(const typename object_t::key_type& key)
{
// at only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_TRY
- {
- return set_parent(m_value.object->at(key));
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
- }
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
- else
+
+ auto it = m_value.object->find(key);
+ if (it == m_value.object->end())
+ {
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
+ }
+ return set_parent(it->second);
+ }
+
+ /// @brief access specified object element with bounds checking
+ /// @sa https://json.nlohmann.me/api/basic_json/at/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ reference at(KeyType && key)
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
+
+ auto it = m_value.object->find(std::forward<KeyType>(key));
+ if (it == m_value.object->end())
+ {
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
+ }
+ return set_parent(it->second);
}
/// @brief access specified object element with bounds checking
@@ -19159,22 +20979,37 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const_reference at(const typename object_t::key_type& key) const
{
// at only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_TRY
- {
- return m_value.object->at(key);
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
- }
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
- else
+
+ auto it = m_value.object->find(key);
+ if (it == m_value.object->end())
+ {
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
+ }
+ return it->second;
+ }
+
+ /// @brief access specified object element with bounds checking
+ /// @sa https://json.nlohmann.me/api/basic_json/at/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ const_reference at(KeyType && key) const
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
+
+ auto it = m_value.object->find(std::forward<KeyType>(key));
+ if (it == m_value.object->end())
+ {
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
+ }
+ return it->second;
}
/// @brief access specified array element
@@ -19220,7 +21055,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
}
/// @brief access specified array element
@@ -19233,12 +21068,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
}
/// @brief access specified object element
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](const typename object_t::key_type& key)
+ reference operator[](typename object_t::key_type key)
{
// implicitly convert null value to an empty object
if (is_null())
@@ -19251,10 +21086,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
- return set_parent(m_value.object->operator[](key));
+ auto result = m_value.object->emplace(std::move(key), nullptr);
+ return set_parent(result.first->second);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element
@@ -19264,74 +21100,92 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// const operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
- JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
- return m_value.object->find(key)->second;
+ auto it = m_value.object->find(key);
+ JSON_ASSERT(it != m_value.object->end());
+ return it->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+ // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
+ // (they seemingly cannot be constrained to resolve the ambiguity)
template<typename T>
- JSON_HEDLEY_NON_NULL(2)
reference operator[](T* key)
{
- // implicitly convert null to object
+ return operator[](typename object_t::key_type(key));
+ }
+
+ template<typename T>
+ const_reference operator[](T* key) const
+ {
+ return operator[](typename object_t::key_type(key));
+ }
+
+ /// @brief access specified object element
+ /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
+ reference operator[](KeyType && key)
+ {
+ // implicitly convert null value to an empty object
if (is_null())
{
m_type = value_t::object;
- m_value = value_t::object;
+ m_value.object = create<object_t>();
assert_invariant();
}
- // at only works for objects
+ // operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
- return set_parent(m_value.object->operator[](key));
+ auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
+ return set_parent(result.first->second);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- template<typename T>
- JSON_HEDLEY_NON_NULL(2)
- const_reference operator[](T* key) const
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
+ const_reference operator[](KeyType && key) const
{
- // at only works for objects
+ // const operator[] only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
- JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
- return m_value.object->find(key)->second;
+ auto it = m_value.object->find(std::forward<KeyType>(key));
+ JSON_ASSERT(it != m_value.object->end());
+ return it->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element with default value
/// @sa https://json.nlohmann.me/api/basic_json/value/
- /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
- template < class ValueType, typename std::enable_if <
- detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
- ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
- {
- // at only works for objects
+ // this is the value(const typename object_t::key_type&) overload
+ template < class KeyType, class ValueType, detail::enable_if_t <
+ std::is_same<KeyType, typename object_t::key_type>::value
+ && detail::is_getable<basic_json_t, ValueType>::value
+ && !std::is_same<value_t, ValueType>::value, int > = 0 >
+ typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
+ {
+ // value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
// if key is found, return value and given default value otherwise
const auto it = find(key);
if (it != end())
{
- return it->template get<ValueType>();
+ return it->template get<typename std::decay<ValueType>::type>();
}
- return default_value;
+ return std::forward<ValueType>(default_value);
}
- JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
}
/// @brief access specified object element with default value
@@ -19342,13 +21196,64 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(key, string_t(default_value));
}
+ // these two functions, in conjunction with value(const KeyType &, ValueType &&),
+ // resolve an ambiguity that would otherwise occur between the json_pointer and
+ // typename object_t::key_type & overloads
+ template < class ValueType, detail::enable_if_t <
+ detail::is_getable<basic_json_t, ValueType>::value
+ && !std::is_same<value_t, ValueType>::value, int > = 0 >
+ typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
+ {
+ return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
+ }
+
+ string_t value(const char* key, const char* default_value) const
+ {
+ return value(typename object_t::key_type(key), string_t(default_value));
+ }
+
+ /// @brief access specified object element with default value
+ /// @sa https://json.nlohmann.me/api/basic_json/value/
+ /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
+ template < class KeyType, class ValueType, detail::enable_if_t <
+ detail::is_getable<basic_json_t, ValueType>::value
+ && !std::is_same<value_t, ValueType>::value
+ && detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
+ typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
+ {
+ // value only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ // if key is found, return value and given default value otherwise
+ const auto it = find(std::forward<KeyType>(key));
+ if (it != end())
+ {
+ return it->template get<typename std::decay<ValueType>::type>();
+ }
+
+ return std::forward<ValueType>(default_value);
+ }
+
+ JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+ }
+
+ /// @brief access specified object element with default value
+ /// @sa https://json.nlohmann.me/api/basic_json/value/
+ /// overload for a default value of type const char*
+ template < class KeyType, detail::enable_if_t <
+ !detail::is_json_pointer<KeyType>::value, int > = 0 >
+ string_t value(KeyType && key, const char* default_value) const
+ {
+ return value(std::forward<KeyType>(key), string_t(default_value));
+ }
+
/// @brief access specified object element via JSON Pointer with default value
/// @sa https://json.nlohmann.me/api/basic_json/value/
- template<class ValueType, typename std::enable_if<
- detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
+ template < class ValueType, detail::enable_if_t <
+ detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
{
- // at only works for objects
+ // value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
// if pointer resolves a value, return it or use default value
@@ -19362,7 +21267,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
}
- JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+ }
+
+ template < class ValueType, class BasicJsonType, detail::enable_if_t <
+ detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
+ {
+ return value(ptr.convert(), default_value);
}
/// @brief access specified object element via JSON Pointer with default value
@@ -19374,6 +21287,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}
+ template<typename BasicJsonType>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ JSON_HEDLEY_NON_NULL(3)
+ string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
+ {
+ return value(ptr.convert(), default_value);
+ }
+
/// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/
reference front()
@@ -19408,16 +21329,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief remove element given an iterator
/// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, typename std::enable_if <
+ template < class IteratorType, detail::enable_if_t <
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
- = 0 >
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
IteratorType erase(IteratorType pos)
{
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
IteratorType result = end();
@@ -19433,7 +21353,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
{
- JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
+ JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
}
if (is_string())
@@ -19471,7 +21391,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
return result;
@@ -19479,16 +21399,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief remove elements given an iterator range
/// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, typename std::enable_if <
+ template < class IteratorType, detail::enable_if_t <
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
- = 0 >
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
IteratorType erase(IteratorType first, IteratorType last)
{
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
{
- JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
}
IteratorType result = end();
@@ -19505,7 +21424,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
}
if (is_string())
@@ -19545,23 +21464,63 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
return result;
}
- /// @brief remove element from a JSON object given a key
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- size_type erase(const typename object_t::key_type& key)
+ private:
+ template < typename KeyType, detail::enable_if_t <
+ detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
+ size_type erase_internal(KeyType && key)
{
// this erase only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
+ {
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
+ }
+
+ return m_value.object->erase(std::forward<KeyType>(key));
+ }
+
+ template < typename KeyType, detail::enable_if_t <
+ !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
+ size_type erase_internal(KeyType && key)
+ {
+ // this erase only works for objects
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- return m_value.object->erase(key);
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ const auto it = m_value.object->find(std::forward<KeyType>(key));
+ if (it != m_value.object->end())
+ {
+ m_value.object->erase(it);
+ return 1;
+ }
+ return 0;
+ }
+
+ public:
+
+ /// @brief remove element from a JSON object given a key
+ /// @sa https://json.nlohmann.me/api/basic_json/erase/
+ size_type erase(const typename object_t::key_type& key)
+ {
+ // the indirection via erase_internal() is added to avoid making this
+ // function a template and thus de-rank it during overload resolution
+ return erase_internal(key);
+ }
+
+ /// @brief remove element from a JSON object given a key
+ /// @sa https://json.nlohmann.me/api/basic_json/erase/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ size_type erase(KeyType && key)
+ {
+ return erase_internal(std::forward<KeyType>(key));
}
/// @brief remove element from a JSON array given an index
@@ -19573,14 +21532,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
{
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
}
else
{
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
}
@@ -19596,14 +21555,43 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief find an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/find/
- template<typename KeyT>
- iterator find(KeyT&& key)
+ iterator find(const typename object_t::key_type& key)
+ {
+ auto result = end();
+
+ if (is_object())
+ {
+ result.m_it.object_iterator = m_value.object->find(key);
+ }
+
+ return result;
+ }
+
+ /// @brief find an element in a JSON object
+ /// @sa https://json.nlohmann.me/api/basic_json/find/
+ const_iterator find(const typename object_t::key_type& key) const
+ {
+ auto result = cend();
+
+ if (is_object())
+ {
+ result.m_it.object_iterator = m_value.object->find(key);
+ }
+
+ return result;
+ }
+
+ /// @brief find an element in a JSON object
+ /// @sa https://json.nlohmann.me/api/basic_json/find/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ iterator find(KeyType && key)
{
auto result = end();
if (is_object())
{
- result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
}
return result;
@@ -19611,14 +21599,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief find an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/find/
- template<typename KeyT>
- const_iterator find(KeyT&& key) const
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ const_iterator find(KeyType && key) const
{
auto result = cend();
if (is_object())
{
- result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
}
return result;
@@ -19626,20 +21615,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief returns the number of occurrences of a key in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/count/
- template<typename KeyT>
- size_type count(KeyT&& key) const
+ size_type count(const typename object_t::key_type& key) const
+ {
+ // return 0 for all nonobject types
+ return is_object() ? m_value.object->count(key) : 0;
+ }
+
+ /// @brief returns the number of occurrences of a key in a JSON object
+ /// @sa https://json.nlohmann.me/api/basic_json/count/
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ size_type count(KeyType && key) const
{
// return 0 for all nonobject types
- return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
+ return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
+ }
+
+ /// @brief check the existence of an element in a JSON object
+ /// @sa https://json.nlohmann.me/api/basic_json/contains/
+ bool contains(const typename object_t::key_type& key) const
+ {
+ return is_object() && m_value.object->find(key) != m_value.object->end();
}
/// @brief check the existence of an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/contains/
- template < typename KeyT, typename std::enable_if <
- !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
- bool contains(KeyT && key) const
+ template<class KeyType, detail::enable_if_t<
+ detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
+ bool contains(KeyType && key) const
{
- return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
+ return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
}
/// @brief check the existence of an element in a JSON object given a JSON pointer
@@ -19649,6 +21654,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}
+ template<typename BasicJsonType>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
+ {
+ return ptr.contains(this);
+ }
+
/// @}
@@ -19988,7 +22000,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an array
@@ -20021,7 +22033,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an array
@@ -20053,7 +22065,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or objects
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an object
@@ -20109,7 +22121,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// emplace_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
}
// transform null object into an array
@@ -20134,7 +22146,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// emplace only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
{
- JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
}
// transform null object into an object
@@ -20188,14 +22200,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
return insert_iterator(pos, val);
}
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts element into array
@@ -20215,14 +22227,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
return insert_iterator(pos, cnt, val);
}
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts range of elements into array
@@ -20232,24 +22244,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
{
- JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
+ JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
}
// insert to array and return iterator
@@ -20263,13 +22275,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
@@ -20283,19 +22295,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for objects
if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
// passed iterators must belong to objects
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
{
- JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
}
m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
@@ -20322,19 +22334,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
// passed iterators must belong to objects
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
{
- JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
+ JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
}
for (auto it = first; it != last; ++it)
@@ -20391,11 +22403,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// swap only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
{
- std::swap(*(m_value.array), other);
+ using std::swap;
+ swap(*(m_value.array), other);
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
}
}
@@ -20406,11 +22419,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// swap only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
{
- std::swap(*(m_value.object), other);
+ using std::swap;
+ swap(*(m_value.object), other);
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
}
}
@@ -20421,11 +22435,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// swap only works for strings
if (JSON_HEDLEY_LIKELY(is_string()))
{
- std::swap(*(m_value.string), other);
+ using std::swap;
+ swap(*(m_value.string), other);
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
}
}
@@ -20436,11 +22451,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// swap only works for strings
if (JSON_HEDLEY_LIKELY(is_binary()))
{
- std::swap(*(m_value.binary), other);
+ using std::swap;
+ swap(*(m_value.binary), other);
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
}
}
@@ -20451,17 +22467,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// swap only works for strings
if (JSON_HEDLEY_LIKELY(is_binary()))
{
- std::swap(*(m_value.binary), other);
+ using std::swap;
+ swap(*(m_value.binary), other);
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
}
}
/// @}
- public:
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
@@ -20469,79 +22485,221 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @name lexicographical comparison operators
/// @{
+ // note parentheses around operands are necessary; see
+ // https://github.com/nlohmann/json/issues/1530
+#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
+ const auto lhs_type = lhs.type(); \
+ const auto rhs_type = rhs.type(); \
+ \
+ if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
+ { \
+ switch (lhs_type) \
+ { \
+ case value_t::array: \
+ return (*lhs.m_value.array) op (*rhs.m_value.array); \
+ \
+ case value_t::object: \
+ return (*lhs.m_value.object) op (*rhs.m_value.object); \
+ \
+ case value_t::null: \
+ return (null_result); \
+ \
+ case value_t::string: \
+ return (*lhs.m_value.string) op (*rhs.m_value.string); \
+ \
+ case value_t::boolean: \
+ return (lhs.m_value.boolean) op (rhs.m_value.boolean); \
+ \
+ case value_t::number_integer: \
+ return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \
+ \
+ case value_t::number_unsigned: \
+ return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \
+ \
+ case value_t::number_float: \
+ return (lhs.m_value.number_float) op (rhs.m_value.number_float); \
+ \
+ case value_t::binary: \
+ return (*lhs.m_value.binary) op (*rhs.m_value.binary); \
+ \
+ case value_t::discarded: \
+ default: \
+ return (unordered_result); \
+ } \
+ } \
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
+ { \
+ return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \
+ } \
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
+ { \
+ return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \
+ } \
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
+ { \
+ return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \
+ } \
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
+ { \
+ return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \
+ } \
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
+ { \
+ return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
+ } \
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
+ { \
+ return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
+ } \
+ else if(compares_unordered(lhs, rhs))\
+ {\
+ return (unordered_result);\
+ }\
+ \
+ return (default_result);
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ // returns true if:
+ // - any operand is NaN and the other operand is of number type
+ // - any operand is discarded
+ // in legacy mode, discarded values are considered ordered if
+ // an operation is computed as an odd number of inverses of others
+ static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
+ {
+ if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
+ || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
+ {
+ return true;
+ }
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+ return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
+#else
+ static_cast<void>(inverse);
+ return lhs.is_discarded() || rhs.is_discarded();
+#endif
+ }
+
+ private:
+ bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
+ {
+ return compares_unordered(*this, rhs, inverse);
+ }
+
+ public:
+#if JSON_HAS_THREE_WAY_COMPARISON
/// @brief comparison: equal
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+ bool operator==(const_reference rhs) const noexcept
{
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
- const auto lhs_type = lhs.type();
- const auto rhs_type = rhs.type();
-
- if (lhs_type == rhs_type)
- {
- switch (lhs_type)
- {
- case value_t::array:
- return *lhs.m_value.array == *rhs.m_value.array;
-
- case value_t::object:
- return *lhs.m_value.object == *rhs.m_value.object;
-
- case value_t::null:
- return true;
-
- case value_t::string:
- return *lhs.m_value.string == *rhs.m_value.string;
+ const_reference lhs = *this;
+ JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+ }
- case value_t::boolean:
- return lhs.m_value.boolean == rhs.m_value.boolean;
+ /// @brief comparison: equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+ template<typename ScalarType>
+ requires std::is_scalar_v<ScalarType>
+ bool operator==(ScalarType rhs) const noexcept
+ {
+ return *this == basic_json(rhs);
+ }
- case value_t::number_integer:
- return lhs.m_value.number_integer == rhs.m_value.number_integer;
+ /// @brief comparison: not equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
+ bool operator!=(const_reference rhs) const noexcept
+ {
+ if (compares_unordered(rhs, true))
+ {
+ return false;
+ }
+ return !operator==(rhs);
+ }
- case value_t::number_unsigned:
- return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+ /// @brief comparison: 3-way
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
+ std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
+ {
+ const_reference lhs = *this;
+ // default_result is used if we cannot compare values. In that case,
+ // we compare types.
+ JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
+ std::partial_ordering::equivalent,
+ std::partial_ordering::unordered,
+ lhs_type <=> rhs_type) // *NOPAD*
+ }
- case value_t::number_float:
- return lhs.m_value.number_float == rhs.m_value.number_float;
+ /// @brief comparison: 3-way
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
+ template<typename ScalarType>
+ requires std::is_scalar_v<ScalarType>
+ std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
+ {
+ return *this <=> basic_json(rhs); // *NOPAD*
+ }
- case value_t::binary:
- return *lhs.m_value.binary == *rhs.m_value.binary;
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+ // all operators that are computed as an odd number of inverses of others
+ // need to be overloaded to emulate the legacy comparison behavior
- case value_t::discarded:
- default:
- return false;
- }
- }
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
- {
- return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
- }
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
- {
- return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
- }
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
- {
- return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
- }
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
- {
- return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
- }
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
+ /// @brief comparison: less than or equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
+ bool operator<=(const_reference rhs) const noexcept
+ {
+ if (compares_unordered(rhs, true))
{
- return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+ return false;
}
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
+ return !(rhs < *this);
+ }
+
+ /// @brief comparison: less than or equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
+ template<typename ScalarType>
+ requires std::is_scalar_v<ScalarType>
+ bool operator<=(ScalarType rhs) const noexcept
+ {
+ return *this <= basic_json(rhs);
+ }
+
+ /// @brief comparison: greater than or equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
+ bool operator>=(const_reference rhs) const noexcept
+ {
+ if (compares_unordered(rhs, true))
{
- return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+ return false;
}
+ return !(*this < rhs);
+ }
- return false;
+ /// @brief comparison: greater than or equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
+ template<typename ScalarType>
+ requires std::is_scalar_v<ScalarType>
+ bool operator>=(ScalarType rhs) const noexcept
+ {
+ return *this >= basic_json(rhs);
+ }
+#endif
+#else
+ /// @brief comparison: equal
+ /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
+ friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+ {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
@@ -20569,6 +22727,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
{
+ if (compares_unordered(lhs, rhs, true))
+ {
+ return false;
+ }
return !(lhs == rhs);
}
@@ -20594,76 +22756,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
{
- const auto lhs_type = lhs.type();
- const auto rhs_type = rhs.type();
-
- if (lhs_type == rhs_type)
- {
- switch (lhs_type)
- {
- case value_t::array:
- // note parentheses are necessary, see
- // https://github.com/nlohmann/json/issues/1530
- return (*lhs.m_value.array) < (*rhs.m_value.array);
-
- case value_t::object:
- return (*lhs.m_value.object) < (*rhs.m_value.object);
-
- case value_t::null:
- return false;
-
- case value_t::string:
- return (*lhs.m_value.string) < (*rhs.m_value.string);
-
- case value_t::boolean:
- return (lhs.m_value.boolean) < (rhs.m_value.boolean);
-
- case value_t::number_integer:
- return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
-
- case value_t::number_unsigned:
- return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
-
- case value_t::number_float:
- return (lhs.m_value.number_float) < (rhs.m_value.number_float);
-
- case value_t::binary:
- return (*lhs.m_value.binary) < (*rhs.m_value.binary);
-
- case value_t::discarded:
- default:
- return false;
- }
- }
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
- {
- return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
- }
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
- {
- return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
- }
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
- {
- return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
- }
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
- {
- return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
- }
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
- {
- return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
- }
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
- {
- return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
- }
-
- // We only reach this line if we cannot compare values. In that case,
+ // default_result is used if we cannot compare values. In that case,
// we compare types. Note we have to call the operator explicitly,
// because MSVC has problems otherwise.
- return operator<(lhs_type, rhs_type);
+ JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
}
/// @brief comparison: less than
@@ -20688,6 +22784,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
{
+ if (compares_unordered(lhs, rhs, true))
+ {
+ return false;
+ }
return !(rhs < lhs);
}
@@ -20713,6 +22813,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
{
+ // double inverse
+ if (compares_unordered(lhs, rhs))
+ {
+ return false;
+ }
return !(lhs <= rhs);
}
@@ -20738,6 +22843,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
{
+ if (compares_unordered(lhs, rhs, true))
+ {
+ return false;
+ }
return !(lhs < rhs);
}
@@ -20758,6 +22867,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
return basic_json(lhs) >= rhs;
}
+#endif
+
+#undef JSON_IMPLEMENT_OPERATOR
/// @}
@@ -20886,7 +22998,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
auto ia = detail::input_adapter(std::forward<InputType>(i));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
}
/// @brief generate SAX events
@@ -20901,7 +23013,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
auto ia = detail::input_adapter(std::move(first), std::move(last));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
}
/// @brief generate SAX events
@@ -20922,7 +23034,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
}
#ifndef JSON_NO_IO
/// @brief deserialize from stream
@@ -21078,6 +23190,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
}
+ /// @brief create a BJData serialization of a given JSON value
+ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+ static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
+ const bool use_size = false,
+ const bool use_type = false)
+ {
+ std::vector<std::uint8_t> result;
+ to_bjdata(j, result, use_size, use_type);
+ return result;
+ }
+
+ /// @brief create a BJData serialization of a given JSON value
+ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+ static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
+ const bool use_size = false, const bool use_type = false)
+ {
+ binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
+ }
+
+ /// @brief create a BJData serialization of a given JSON value
+ /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
+ static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
+ const bool use_size = false, const bool use_type = false)
+ {
+ binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
+ }
+
/// @brief create a BSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
static std::vector<std::uint8_t> to_bson(const basic_json& j)
@@ -21113,7 +23252,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded);
}
@@ -21129,7 +23268,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded);
}
@@ -21156,7 +23295,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get();
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded);
}
@@ -21171,7 +23310,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21186,7 +23325,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21210,7 +23349,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get();
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21225,7 +23364,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21240,7 +23379,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21264,7 +23403,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get();
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+
+ /// @brief create a JSON value from an input in BJData format
+ /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_bjdata(InputType&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /// @brief create a JSON value from an input in BJData format
+ /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_bjdata(IteratorType first, IteratorType last,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21279,7 +23449,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21294,7 +23464,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
@@ -21318,7 +23488,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get();
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
return res ? result : basic_json(value_t::discarded);
}
/// @}
@@ -21337,6 +23507,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
+ template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
+ {
+ return ptr.get_unchecked(this);
+ }
+
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
const_reference operator[](const json_pointer& ptr) const
@@ -21344,6 +23521,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
+ template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
+ {
+ return ptr.get_unchecked(this);
+ }
+
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
reference at(const json_pointer& ptr)
@@ -21351,6 +23535,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
+ template<typename BasicJsonType>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
+ {
+ return ptr.get_checked(this);
+ }
+
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
const_reference at(const json_pointer& ptr) const
@@ -21358,6 +23549,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
+ template<typename BasicJsonType>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
+ const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
+ {
+ return ptr.get_checked(this);
+ }
+
/// @brief return flattened JSON value
/// @sa https://json.nlohmann.me/api/basic_json/flatten/
basic_json flatten() const
@@ -21383,13 +23581,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @name JSON Patch functions
/// @{
- /// @brief applies a JSON patch
+ /// @brief applies a JSON patch in-place without copying the object
/// @sa https://json.nlohmann.me/api/basic_json/patch/
- basic_json patch(const basic_json& json_patch) const
+ void patch_inplace(const basic_json& json_patch)
{
- // make a working copy to apply the patch to
- basic_json result = *this;
-
+ basic_json& result = *this;
// the valid JSON Patch operations
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
@@ -21443,7 +23639,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// get reference to parent of JSON pointer ptr
const auto last_path = ptr.back();
ptr.pop_back();
- basic_json& parent = result[ptr];
+ // parent must exist when performing patch add per RFC6902 specs
+ basic_json& parent = result.at(ptr);
switch (parent.m_type)
{
@@ -21464,11 +23661,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- const auto idx = json_pointer::array_index(last_path);
+ const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
{
// avoid undefined behavior
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
}
// default case: insert add offset
@@ -21509,20 +23706,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
}
}
else if (parent.is_array())
{
// note erase performs range check
- parent.erase(json_pointer::array_index(last_path));
+ parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
}
};
// type check: top level value must be an array
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
{
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
}
// iterate and apply the operations
@@ -21537,20 +23734,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
auto it = val.m_value.object->find(member);
// context-sensitive error message
- const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
+ const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
// check if desired value is present
if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
{
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
+ JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
}
// check if result is of type string
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
{
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
+ JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
}
// no error: return value
@@ -21560,7 +23757,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// type check: every element of the array must be an object
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
{
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
}
// collect mandatory members
@@ -21638,7 +23835,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// throw an exception if test fails
if (JSON_HEDLEY_UNLIKELY(!success))
{
- JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
+ JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
}
break;
@@ -21649,11 +23846,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
// op must be "add", "remove", "replace", "move", "copy", or
// "test"
- JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
+ JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
}
}
}
+ }
+ /// @brief applies a JSON patch to a copy of the current object
+ /// @sa https://json.nlohmann.me/api/basic_json/patch/
+ basic_json patch(const basic_json& json_patch) const
+ {
+ basic_json result = *this;
+ result.patch_inplace(json_patch);
return result;
}
@@ -21691,7 +23895,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
while (i < source.size() && i < target.size())
{
// recursive call to compare array values at index i
- auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
+ auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
++i;
}
@@ -21708,7 +23912,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result.insert(result.begin() + end_index, object(
{
{"op", "remove"},
- {"path", path + "/" + std::to_string(i)}
+ {"path", detail::concat(path, '/', std::to_string(i))}
}));
++i;
}
@@ -21719,7 +23923,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result.push_back(
{
{"op", "add"},
- {"path", path + "/-"},
+ {"path", detail::concat(path, "/-")},
{"value", target[i]}
});
++i;
@@ -21734,7 +23938,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
for (auto it = source.cbegin(); it != source.cend(); ++it)
{
// escape the key name to be used in a JSON patch
- const auto path_key = path + "/" + detail::escape(it.key());
+ const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
if (target.find(it.key()) != target.end())
{
@@ -21758,7 +23962,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (source.find(it.key()) == source.end())
{
// found a key that is not in this -> add it
- const auto path_key = path + "/" + detail::escape(it.key());
+ const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
result.push_back(
{
{"op", "add"}, {"path", path_key},
@@ -21791,7 +23995,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return result;
}
-
/// @}
////////////////////////////////
@@ -21840,7 +24043,30 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
return j.dump();
}
-} // namespace nlohmann
+inline namespace literals
+{
+inline namespace json_literals
+{
+
+/// @brief user-defined string literal for JSON values
+/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
+{
+ return nlohmann::json::parse(s, s + n);
+}
+
+/// @brief user-defined string literal for JSON pointer
+/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
+{
+ return nlohmann::json::json_pointer(std::string(s, n));
+}
+
+} // namespace json_literals
+} // namespace literals
+NLOHMANN_JSON_NAMESPACE_END
///////////////////////
// nonmember support //
@@ -21868,10 +24094,14 @@ struct less< ::nlohmann::detail::value_t> // do not remove the space after '<',
@brief compare two value_t enum values
@since version 3.0.0
*/
- bool operator()(nlohmann::detail::value_t lhs,
- nlohmann::detail::value_t rhs) const noexcept
+ bool operator()(::nlohmann::detail::value_t lhs,
+ ::nlohmann::detail::value_t rhs) const noexcept
{
- return nlohmann::detail::operator<(lhs, rhs);
+#if JSON_HAS_THREE_WAY_COMPARISON
+ return std::is_lt(lhs <=> rhs); // *NOPAD*
+#else
+ return ::nlohmann::detail::operator<(lhs, rhs);
+#endif
}
};
@@ -21890,25 +24120,21 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC
#endif
-} // namespace std
-
-/// @brief user-defined string literal for JSON values
-/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
-JSON_HEDLEY_NON_NULL(1)
-inline nlohmann::json operator "" _json(const char* s, std::size_t n)
-{
- return nlohmann::json::parse(s, s + n);
-}
+} // namespace std
-/// @brief user-defined string literal for JSON pointer
-/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
-JSON_HEDLEY_NON_NULL(1)
-inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
-{
- return nlohmann::json::json_pointer(std::string(s, n));
-}
+#if JSON_USE_GLOBAL_UDLS
+ using namespace nlohmann::literals::json_literals; // NOLINT(build/namespaces_literals)
+#endif
// #include <nlohmann/detail/macro_unscope.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
// restore clang diagnostic settings
@@ -21919,22 +24145,40 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
// clean up
#undef JSON_ASSERT
#undef JSON_INTERNAL_CATCH
-#undef JSON_CATCH
#undef JSON_THROW
-#undef JSON_TRY
#undef JSON_PRIVATE_UNLESS_TESTED
-#undef JSON_HAS_CPP_11
-#undef JSON_HAS_CPP_14
-#undef JSON_HAS_CPP_17
-#undef JSON_HAS_CPP_20
-#undef JSON_HAS_FILESYSTEM
-#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL
#undef JSON_EXPLICIT
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
+#undef JSON_INLINE_VARIABLE
+#undef JSON_NO_UNIQUE_ADDRESS
+#undef JSON_DISABLE_ENUM_SERIALIZATION
+#undef JSON_USE_GLOBAL_UDLS
+
+#ifndef JSON_TEST_KEEP_MACROS
+ #undef JSON_CATCH
+ #undef JSON_TRY
+ #undef JSON_HAS_CPP_11
+ #undef JSON_HAS_CPP_14
+ #undef JSON_HAS_CPP_17
+ #undef JSON_HAS_CPP_20
+ #undef JSON_HAS_FILESYSTEM
+ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
+ #undef JSON_HAS_THREE_WAY_COMPARISON
+ #undef JSON_HAS_RANGES
+ #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+#endif
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#undef JSON_HEDLEY_ALWAYS_INLINE
diff --git a/single_include/nlohmann/json_fwd.hpp b/single_include/nlohmann/json_fwd.hpp
index 2d5ba38..c6f2871 100644
--- a/single_include/nlohmann/json_fwd.hpp
+++ b/single_include/nlohmann/json_fwd.hpp
@@ -1,3 +1,11 @@
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++
+// | | |__ | | | | | | version 3.11.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
@@ -7,13 +15,15 @@
#include <string> // string
#include <vector> // vector
+#include <nlohmann/detail/abi_macros.hpp>
+
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
-namespace nlohmann
-{
+NLOHMANN_JSON_NAMESPACE_BEGIN
+
/*!
@brief default JSONSerializer template argument
@@ -59,6 +69,6 @@ struct ordered_map;
/// @sa https://json.nlohmann.me/api/ordered_json/
using ordered_json = basic_json<nlohmann::ordered_map>;
-} // namespace nlohmann
+NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_