Dump the entire json library in

This commit is contained in:
jordan4ibanez
2023-11-26 01:31:01 -05:00
parent 8f54e69d33
commit 650ccf9844
1077 changed files with 173944 additions and 0 deletions

View File

@ -0,0 +1,184 @@
cmake_minimum_required(VERSION 3.13...3.14)
option(JSON_Valgrind "Execute test suite with Valgrind." OFF)
option(JSON_FastTests "Skip expensive/slow tests." OFF)
set(JSON_32bitTest AUTO CACHE STRING "Enable the 32bit unit test (ON/OFF/AUTO/ONLY).")
set(JSON_TestStandards "" CACHE STRING "The list of standards to test explicitly.")
# using an env var, since this will also affect targets executing cmake (such as "ci_test_compiler_default")
set(JSON_FORCED_GLOBAL_COMPILE_OPTIONS $ENV{JSON_FORCED_GLOBAL_COMPILE_OPTIONS})
if (NOT "" STREQUAL "$ENV{JSON_FORCED_GLOBAL_COMPILE_OPTIONS}")
add_compile_options($ENV{JSON_FORCED_GLOBAL_COMPILE_OPTIONS})
endif()
if (NOT "" STREQUAL "$ENV{JSON_FORCED_GLOBAL_LINK_OPTIONS}")
add_link_options($ENV{JSON_FORCED_GLOBAL_LINK_OPTIONS})
endif()
include(test)
#############################################################################
# override standard support
#############################################################################
# Clang only supports C++17 starting from Clang 5.0
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
unset(compiler_supports_cpp_17)
endif()
# MSVC 2015 (14.0) does not support C++17
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.1)
unset(compiler_supports_cpp_17)
endif()
# Clang C++20 support appears insufficient prior to Clang 9.0 (based on CI build failure)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
unset(compiler_supports_cpp_20)
endif()
# GCC started supporting C++20 features in 8.0 but a test for #3070 segfaults prior to 9.0
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
unset(compiler_supports_cpp_20)
endif()
#############################################################################
# test_main library with shared code to speed up build and common settings
#############################################################################
add_library(test_main OBJECT src/unit.cpp)
target_compile_definitions(test_main PUBLIC
DOCTEST_CONFIG_SUPER_FAST_ASSERTS
JSON_TEST_KEEP_MACROS
JSON_TEST_USING_MULTIPLE_HEADERS=$<BOOL:${JSON_MultipleHeaders}>)
target_compile_features(test_main PRIVATE cxx_std_11)
target_compile_options(test_main PUBLIC
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
# MSVC: Force to always compile with W4
# Disable warning C4566: character represented by universal-character-name '\uFF01'
# cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<...>::operator <<': was declared deprecated
$<$<CXX_COMPILER_ID:MSVC>:/W4 /wd4566 /wd4996>
# https://github.com/nlohmann/json/issues/1114
$<$<CXX_COMPILER_ID:MSVC>:/bigobj> $<$<BOOL:${MINGW}>:-Wa,-mbig-obj>
# https://github.com/nlohmann/json/pull/3229
$<$<CXX_COMPILER_ID:Intel>:-diag-disable=2196>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:Intel>:-diag-disable=1786>)
target_include_directories(test_main PUBLIC
thirdparty/doctest
thirdparty/fifo_map
${PROJECT_BINARY_DIR}/include)
target_link_libraries(test_main PUBLIC ${NLOHMANN_JSON_TARGET_NAME})
#############################################################################
# define test- and standard-specific build settings
#############################################################################
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0 AND NOT MINGW)
# fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90050
json_test_set_test_options(all CXX_STANDARDS 17 LINK_LIBRARIES stdc++fs)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# avoid stack overflow, see https://github.com/nlohmann/json/issues/2955
json_test_set_test_options("test-cbor;test-msgpack;test-ubjson;test-bjdata;test-binary_formats" LINK_OPTIONS /STACK:4000000)
endif()
# disable exceptions for test-disabled_exceptions
json_test_set_test_options(test-disabled_exceptions
COMPILE_DEFINITIONS
JSON_NOEXCEPTION
# disabled due to https://github.com/nlohmann/json/discussions/2824
#$<$<CXX_COMPILER_ID:MSVC>:_HAS_EXCEPTIONS=0>
COMPILE_OPTIONS
$<$<CXX_COMPILER_ID:AppleClang>:-fno-exceptions> $<$<CXX_COMPILER_ID:Clang>:-fno-exceptions>
$<$<CXX_COMPILER_ID:GNU>:-fno-exceptions>
$<$<CXX_COMPILER_ID:Intel>:-fno-exceptions> $<$<CXX_COMPILER_ID:IntelLLVM>:-fno-exceptions>
# disabled due to https://github.com/nlohmann/json/discussions/2824
#$<$<CXX_COMPILER_ID:MSVC>:/EH>
)
# raise timeout of expensive Unicode test
json_test_set_test_options(test-unicode4 TEST_PROPERTIES TIMEOUT 3000)
#############################################################################
# add unit tests
#############################################################################
if("${JSON_TestStandards}" STREQUAL "")
set(test_cxx_standards 11 14 17 20 23)
unset(test_force)
else()
set(test_cxx_standards ${JSON_TestStandards})
set(test_force FORCE)
endif()
# Print selected standards marking unavailable ones with brackets
set(msg_standards "")
foreach(cxx_standard ${test_cxx_standards})
if(compiler_supports_cpp_${cxx_standard})
list(APPEND msg_standards ${cxx_standard})
else()
list(APPEND msg_standards [${cxx_standard}])
endif()
endforeach()
string(JOIN " " msg_standards ${msg_standards})
set(msg "Testing standards: ${msg_standards}")
if(test_force)
string(APPEND msg " (forced)")
endif()
message(STATUS "${msg}")
# *DO* use json_test_set_test_options() above this line
json_test_should_build_32bit_test(json_32bit_test json_32bit_test_only "${JSON_32bitTest}")
file(GLOB files src/unit-*.cpp)
if(json_32bit_test_only)
set(files src/unit-32bit.cpp)
elseif(NOT json_32bit_test)
list(FILTER files EXCLUDE REGEX src/unit-32bit.cpp)
endif()
foreach(file ${files})
json_test_add_test_for(${file} MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force})
endforeach()
if(json_32bit_test_only)
# Skip all other tests in this file
return()
endif()
# test legacy comparison of discarded values
json_test_set_test_options(test-comparison_legacy
COMPILE_DEFINITIONS JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1
)
json_test_add_test_for(src/unit-comparison.cpp
NAME test-comparison_legacy
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
)
# *DO NOT* use json_test_set_test_options() below this line
#############################################################################
# test ABI compatibility
#############################################################################
add_subdirectory(abi)
#############################################################################
# Test the generated build configs
#############################################################################
# these tests depend on the generated file nlohmann_jsonConfig.cmake
if (JSON_Install)
add_subdirectory(cmake_import)
add_subdirectory(cmake_import_minver)
endif()
add_subdirectory(cmake_add_subdirectory)
add_subdirectory(cmake_fetch_content)
add_subdirectory(cmake_fetch_content2)
add_subdirectory(cmake_target_include_directories)

View File

@ -0,0 +1,30 @@
# common build settings
add_library(abi_compat_common INTERFACE)
target_compile_definitions(abi_compat_common INTERFACE
DOCTEST_CONFIG_SUPER_FAST_ASSERTS
JSON_TEST_KEEP_MACROS)
target_compile_features(abi_compat_common INTERFACE cxx_std_11)
target_compile_options(abi_compat_common INTERFACE
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
# MSVC: Force to always compile with W4
$<$<CXX_COMPILER_ID:MSVC>:/W4>
# https://github.com/nlohmann/json/pull/3229
$<$<CXX_COMPILER_ID:Intel>:-diag-disable=2196>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:Intel>:-diag-disable=1786>)
target_include_directories(abi_compat_common SYSTEM INTERFACE
../thirdparty/doctest
include)
target_link_libraries(abi_compat_common INTERFACE ${NLOHMANN_JSON_TARGET_NAME})
# shared main()
add_library(abi_compat_main STATIC main.cpp)
target_link_libraries(abi_compat_main PUBLIC abi_compat_common)
# add individual tests
add_subdirectory(config)
add_subdirectory(diag)
add_subdirectory(inline_ns)

View File

@ -0,0 +1,22 @@
# test the different options to change the namespace
# test default namespace
add_executable(abi_config_default default.cpp)
target_link_libraries(abi_config_default PRIVATE abi_compat_main)
add_test(
NAME test-abi_config_default
COMMAND abi_config_default ${DOCTEST_TEST_FILTER})
# test no version namespace
add_executable(abi_config_noversion noversion.cpp)
target_link_libraries(abi_config_noversion PRIVATE abi_compat_main)
add_test(
NAME test-abi_config_noversion
COMMAND abi_config_noversion ${DOCTEST_TEST_FILTER})
# test custom namespace
add_executable(abi_config_custom custom.cpp)
target_link_libraries(abi_config_custom PRIVATE abi_compat_main)
add_test(
NAME test-abi_config_custom
COMMAND abi_config_custom ${DOCTEST_TEST_FILTER})

View File

@ -0,0 +1,35 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include "doctest.h"
#include <iostream>
#include <regex>
#include <string>
#define STRINGIZE_EX(x) #x
#define STRINGIZE(x) STRINGIZE_EX(x)
template<typename T>
std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
{
#if DOCTEST_MSVC && !DOCTEST_CLANG
ns = __FUNCSIG__;
#elif !DOCTEST_CLANG
ns = __PRETTY_FUNCTION__;
#endif
std::smatch m;
// extract the true namespace name from the function signature
CAPTURE(ns);
CHECK(std::regex_search(ns, m, std::regex("nlohmann(::[a-zA-Z0-9_]+)*::basic_json")));
return m.str();
}

View File

@ -0,0 +1,33 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include "config.hpp"
// define custom namespace
#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann {
#define NLOHMANN_JSON_NAMESPACE_END }
#include <nlohmann/json_fwd.hpp>
TEST_CASE("custom namespace")
{
// GCC 4.8 fails with regex_error
#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
SECTION("namespace matches expectation")
{
std::string expected = "nlohmann::basic_json";
// fallback for Clang
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
#endif
}

View File

@ -0,0 +1,41 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include "config.hpp"
#include <nlohmann/json_fwd.hpp>
TEST_CASE("default namespace")
{
// GCC 4.8 fails with regex_error
#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
SECTION("namespace matches expectation")
{
std::string expected = "nlohmann::json_abi";
#if JSON_DIAGNOSTICS
expected += "_diag";
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
expected += "_ldvcmp";
#endif
expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
// fallback for Clang
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
#endif
}

View File

@ -0,0 +1,40 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include "config.hpp"
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 1
#include <nlohmann/json_fwd.hpp>
TEST_CASE("default namespace without version component")
{
// GCC 4.8 fails with regex_error
#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
SECTION("namespace matches expectation")
{
std::string expected = "nlohmann::json_abi";
#if JSON_DIAGNOSTICS
expected += "_diag";
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
expected += "_ldvcmp";
#endif
expected += "::basic_json";
// fallback for Clang
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
#endif
}

View File

@ -0,0 +1,19 @@
# test linking library built with different JSON_DIAGNOSTICS setting
# into the same executable
# compile code using JSON_DIAGNOSTICS=1
add_library(abi_compat_diag_on STATIC diag_on.cpp)
target_link_libraries(abi_compat_diag_on PUBLIC abi_compat_common)
# compile code using JSON_DIAGNOSTICS=0
add_library(abi_compat_diag_off STATIC diag_off.cpp)
target_link_libraries(abi_compat_diag_off PUBLIC abi_compat_common)
# build test executable and add test
add_executable(abi_compat_diag diag.cpp)
target_link_libraries(abi_compat_diag PRIVATE
abi_compat_main abi_compat_diag_on abi_compat_diag_off)
add_test(
NAME test-abi_compat_diag
COMMAND abi_compat_diag ${DOCTEST_TEST_FILTER})

View File

@ -0,0 +1,29 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include "diag.hpp"
TEST_CASE("ABI compatible diagnostics")
{
SECTION("basic_json size")
{
// basic_json with diagnostics is larger because of added data members
CHECK(json_sizeof_diag_on() == json_sizeof_diag_on_explicit());
CHECK(json_sizeof_diag_off() == json_sizeof_diag_off_explicit());
CHECK(json_sizeof_diag_on() > json_sizeof_diag_off());
}
SECTION("basic_json at")
{
// accessing a nonexistent key throws different exception with diagnostics
CHECK_THROWS_WITH(json_at_diag_on(), "[json.exception.out_of_range.403] (/foo) key 'bar' not found");
CHECK_THROWS_WITH(json_at_diag_off(), "[json.exception.out_of_range.403] key 'bar' not found");
}
}

View File

@ -0,0 +1,20 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include <cstddef>
std::size_t json_sizeof_diag_on();
std::size_t json_sizeof_diag_on_explicit();
std::size_t json_sizeof_diag_off();
std::size_t json_sizeof_diag_off_explicit();
void json_at_diag_on();
void json_at_diag_off();

View File

@ -0,0 +1,30 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#undef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#include <nlohmann/json.hpp>
#include "diag.hpp"
std::size_t json_sizeof_diag_off()
{
return sizeof(nlohmann::json);
}
std::size_t json_sizeof_diag_off_explicit()
{
return sizeof(::NLOHMANN_JSON_NAMESPACE::json);
}
void json_at_diag_off()
{
using nlohmann::json;
json j = json{{"foo", json::object()}};
j.at(json::json_pointer("/foo/bar"));
}

View File

@ -0,0 +1,30 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#undef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 1
#include <nlohmann/json.hpp>
#include "diag.hpp"
std::size_t json_sizeof_diag_on()
{
return sizeof(nlohmann::json);
}
std::size_t json_sizeof_diag_on_explicit()
{
return sizeof(::NLOHMANN_JSON_NAMESPACE::json);
}
void json_at_diag_on()
{
using nlohmann::json;
json j = json{{"foo", json::object()}};
j.at(json::json_pointer("/foo/bar"));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
# test linking an old library version without an inline namespace
# with the current library using an inline namespace into the same executable
# build test executable and add test
add_executable(abi_compat_inline_ns
use_v3_10_5.cpp
use_current.cpp)
target_link_libraries(abi_compat_inline_ns PRIVATE abi_compat_main)
add_test(
NAME test-abi_compat_inline_ns
COMMAND abi_compat_inline_ns ${DOCTEST_TEST_FILTER})

View File

@ -0,0 +1,36 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
TEST_CASE("use current library with inline namespace")
{
SECTION("implicitly")
{
using nlohmann::json;
using nlohmann::ordered_json;
json j;
// In v3.10.5 mixing json_pointers of different basic_json types
// results in implicit string conversion
j[ordered_json::json_pointer("/root")] = json::object();
CHECK(j.dump() == "{\"root\":{}}");
}
SECTION("explicitly")
{
using NLOHMANN_JSON_NAMESPACE::json;
using NLOHMANN_JSON_NAMESPACE::ordered_json;
json j;
j[ordered_json::json_pointer("/root")] = json::object();
CHECK(j.dump() == "{\"root\":{}}");
}
}

View File

@ -0,0 +1,22 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json_v3_10_5.hpp>
using nlohmann::json;
using nlohmann::ordered_json;
TEST_CASE("use library v3.10.5 without inline namespace")
{
json j;
j[ordered_json::json_pointer("/root")] = json::object();
// In v3.10.5 mixing json_pointers of different basic_json types
// results in implicit string conversion
CHECK(j.dump() == "{\"/root\":{}}");
}

View File

@ -0,0 +1,11 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest_compatibility.h"

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.11...3.14)
project(JSON_Benchmarks LANGUAGES CXX)
# set compiler flags
if((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -DNDEBUG -O3")
endif()
# configure Google Benchmarks
include(FetchContent)
FetchContent_Declare(
benchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG origin/main
GIT_SHALLOW TRUE
)
FetchContent_GetProperties(benchmark)
if(NOT benchmark_POPULATED)
FetchContent_Populate(benchmark)
set(BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "" FORCE)
add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR})
endif()
# download test data
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake ${CMAKE_MODULE_PATH})
include(download_test_data)
# benchmark binary
add_executable(json_benchmarks src/benchmarks.cpp)
target_compile_features(json_benchmarks PRIVATE cxx_std_11)
target_link_libraries(json_benchmarks benchmark ${CMAKE_THREAD_LIBS_INIT})
add_dependencies(json_benchmarks download_test_data)
target_include_directories(json_benchmarks PRIVATE ${CMAKE_SOURCE_DIR}/../../single_include ${CMAKE_BINARY_DIR}/include)

View File

@ -0,0 +1,177 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <benchmark/benchmark.h>
#include <nlohmann/json.hpp>
#include <fstream>
#include <numeric>
#include <vector>
#include <test_data.hpp>
using json = nlohmann::json;
//////////////////////////////////////////////////////////////////////////////
// parse JSON from file
//////////////////////////////////////////////////////////////////////////////
static void ParseFile(benchmark::State& state, const char* filename)
{
while (state.KeepRunning())
{
state.PauseTiming();
auto* f = new std::ifstream(filename);
auto* j = new json();
state.ResumeTiming();
*j = json::parse(*f);
state.PauseTiming();
delete f;
delete j;
state.ResumeTiming();
}
std::ifstream file(filename, std::ios::binary | std::ios::ate);
state.SetBytesProcessed(state.iterations() * file.tellg());
}
BENCHMARK_CAPTURE(ParseFile, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseFile, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseFile, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseFile, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseFile, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseFile, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseFile, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseFile, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
// parse JSON from string
//////////////////////////////////////////////////////////////////////////////
static void ParseString(benchmark::State& state, const char* filename)
{
std::ifstream f(filename);
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
while (state.KeepRunning())
{
state.PauseTiming();
auto* j = new json();
state.ResumeTiming();
*j = json::parse(str);
state.PauseTiming();
delete j;
state.ResumeTiming();
}
state.SetBytesProcessed(state.iterations() * str.size());
}
BENCHMARK_CAPTURE(ParseString, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseString, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseString, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseString, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseString, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseString, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseString, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseString, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
// serialize JSON
//////////////////////////////////////////////////////////////////////////////
static void Dump(benchmark::State& state, const char* filename, int indent)
{
std::ifstream f(filename);
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
json j = json::parse(str);
while (state.KeepRunning())
{
j.dump(indent);
}
state.SetBytesProcessed(state.iterations() * j.dump(indent).size());
}
BENCHMARK_CAPTURE(Dump, jeopardy / -, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", -1);
BENCHMARK_CAPTURE(Dump, jeopardy / 4, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", 4);
BENCHMARK_CAPTURE(Dump, canada / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", -1);
BENCHMARK_CAPTURE(Dump, canada / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", 4);
BENCHMARK_CAPTURE(Dump, citm_catalog / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", -1);
BENCHMARK_CAPTURE(Dump, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
BENCHMARK_CAPTURE(Dump, twitter / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", -1);
BENCHMARK_CAPTURE(Dump, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
BENCHMARK_CAPTURE(Dump, floats / -, TEST_DATA_DIRECTORY "/regression/floats.json", -1);
BENCHMARK_CAPTURE(Dump, floats / 4, TEST_DATA_DIRECTORY "/regression/floats.json", 4);
BENCHMARK_CAPTURE(Dump, signed_ints / -, TEST_DATA_DIRECTORY "/regression/signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, signed_ints / 4, TEST_DATA_DIRECTORY "/regression/signed_ints.json", 4);
BENCHMARK_CAPTURE(Dump, unsigned_ints / -, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", -1);
BENCHMARK_CAPTURE(Dump, unsigned_ints / 4, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 4);
BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
//////////////////////////////////////////////////////////////////////////////
// serialize CBOR
//////////////////////////////////////////////////////////////////////////////
static void ToCbor(benchmark::State& state, const char* filename)
{
std::ifstream f(filename);
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
json j = json::parse(str);
while (state.KeepRunning())
{
json::to_cbor(j);
}
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
}
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
// serialize binary CBOR
//////////////////////////////////////////////////////////////////////////////
static void BinaryToCbor(benchmark::State& state)
{
std::vector<uint8_t> data(256);
std::iota(data.begin(), data.end(), 0);
auto it = data.begin();
std::vector<uint8_t> in;
in.reserve(state.range(0));
for (int i = 0; i < state.range(0); ++i)
{
if (it == data.end())
{
it = data.begin();
}
in.push_back(*it);
++it;
}
json::binary_t bin{in};
json j{{"type", "binary"}, {"data", bin}};
while (state.KeepRunning())
{
json::to_cbor(j);
}
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
}
BENCHMARK(BinaryToCbor)->RangeMultiplier(2)->Range(8, 8 << 12);
BENCHMARK_MAIN();

View File

@ -0,0 +1,18 @@
add_test(NAME cmake_add_subdirectory_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_add_subdirectory_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_add_subdirectory_configure PROPERTIES
FIXTURES_SETUP cmake_add_subdirectory
LABELS not_reproducible
)
set_tests_properties(cmake_add_subdirectory_build PROPERTIES
FIXTURES_REQUIRED cmake_add_subdirectory
LABELS not_reproducible
)

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.1...3.14)
project(DummyImport CXX)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(${nlohmann_json_source}
${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json)
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)
add_executable(without_namespace_target main.cpp)
target_link_libraries(without_namespace_target nlohmann_json)
if(NOT MSVC)
add_executable(without_exceptions main.cpp)
target_link_libraries(without_exceptions nlohmann_json::nlohmann_json)
target_compile_definitions(without_exceptions PRIVATE JSON_NOEXCEPTION)
target_compile_options(without_exceptions PRIVATE -fno-exceptions)
endif()

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,20 @@
if (${CMAKE_VERSION} VERSION_GREATER "3.11.0")
add_test(NAME cmake_fetch_content_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_fetch_content_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_fetch_content_configure PROPERTIES
FIXTURES_SETUP cmake_fetch_content
LABELS "git_required;not_reproducible"
)
set_tests_properties(cmake_fetch_content_build PROPERTIES
FIXTURES_REQUIRED cmake_fetch_content
LABELS "git_required;not_reproducible"
)
endif()

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.11...3.14)
project(DummyImport CXX)
include(FetchContent)
get_filename_component(GIT_REPOSITORY_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ABSOLUTE)
FetchContent_Declare(json GIT_REPOSITORY ${GIT_REPOSITORY_DIRECTORY} GIT_TAG HEAD)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)
add_executable(without_namespace_target main.cpp)
target_link_libraries(without_namespace_target nlohmann_json)

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,20 @@
if (${CMAKE_VERSION} VERSION_GREATER "3.14.0")
add_test(NAME cmake_fetch_content2_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_fetch_content2_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_fetch_content2_configure PROPERTIES
FIXTURES_SETUP cmake_fetch_content2
LABELS "git_required;not_reproducible"
)
set_tests_properties(cmake_fetch_content2_build PROPERTIES
FIXTURES_REQUIRED cmake_fetch_content2
LABELS "git_required;not_reproducible"
)
endif()

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.14)
project(DummyImport CXX)
include(FetchContent)
get_filename_component(GIT_REPOSITORY_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ABSOLUTE)
FetchContent_Declare(json GIT_REPOSITORY ${GIT_REPOSITORY_DIRECTORY} GIT_TAG HEAD)
FetchContent_MakeAvailable(json)
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)
add_executable(without_namespace_target main.cpp)
target_link_libraries(without_namespace_target nlohmann_json)

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,19 @@
add_test(NAME cmake_import_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_DIR=${PROJECT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_import_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_import_configure PROPERTIES
FIXTURES_SETUP cmake_import
LABELS not_reproducible
)
set_tests_properties(cmake_import_build PROPERTIES
FIXTURES_REQUIRED cmake_import
LABELS not_reproducible
)

View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.1...3.14)
project(DummyImport CXX)
find_package(nlohmann_json REQUIRED)
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)
add_executable(without_namespace_target main.cpp)
target_link_libraries(without_namespace_target nlohmann_json)

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,19 @@
add_test(NAME cmake_import_minver_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_DIR=${PROJECT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_import_minver_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_import_minver_configure PROPERTIES
FIXTURES_SETUP cmake_import_minver
LABELS not_reproducible
)
set_tests_properties(cmake_import_minver_build PROPERTIES
FIXTURES_REQUIRED cmake_import_minver
LABELS not_reproducible
)

View File

@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1...3.14)
project(DummyImportMinVer CXX)
find_package(nlohmann_json 3.2.0 REQUIRED)
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,18 @@
add_test(NAME cmake_target_include_directories_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_target_include_directories_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_target_include_directories_configure PROPERTIES
FIXTURES_SETUP cmake_target_include_directories
LABELS not_reproducible
)
set_tests_properties(cmake_target_include_directories_build PROPERTIES
FIXTURES_REQUIRED cmake_target_include_directories
LABELS not_reproducible
)

View File

@ -0,0 +1,11 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "Bar.hpp"
class Bar;

View File

@ -0,0 +1,12 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
#include "Foo.hpp"
class Bar : public Foo {};

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.1...3.14)
project(DummyImport CXX)
add_executable(with_private_target main.cpp)
target_include_directories(with_private_target PRIVATE ${nlohmann_json_source}/include)
set_target_properties(with_private_target PROPERTIES CXX_STANDARD 11)
add_executable(with_private_system_target main.cpp)
target_include_directories(with_private_system_target PRIVATE SYSTEM ${nlohmann_json_source}/include)
set_target_properties(with_private_system_target PROPERTIES CXX_STANDARD 11)
# regression from https://github.com/nlohmann/json/discussions/2281
add_library(Foo STATIC Foo.cpp Bar.cpp)
target_include_directories(Foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
set_target_properties(Foo PROPERTIES CXX_STANDARD 11)
add_library(Bar STATIC Bar.cpp)
target_link_libraries(Bar PRIVATE Foo)
target_include_directories(Bar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
set_target_properties(Bar PROPERTIES CXX_STANDARD 11)

View File

@ -0,0 +1,11 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "Foo.hpp"
class Foo;

View File

@ -0,0 +1,12 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include <nlohmann/json.hpp>
class Foo {};

View File

@ -0,0 +1,16 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main(int argc, char** argv)
{
nlohmann::json j;
return 0;
}

View File

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.18)
project(json_cuda LANGUAGES CUDA)
add_executable(json_cuda json_cuda.cu)
target_include_directories(json_cuda PRIVATE ../../include)
target_compile_features(json_cuda PUBLIC cuda_std_11)
set_target_properties(json_cuda PROPERTIES
CUDA_EXTENSIONS OFF
CUDA_STANDARD_REQUIRED ON
)

View File

@ -0,0 +1,19 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <nlohmann/json.hpp>
int main()
{
nlohmann::ordered_json json = {"Test"};
json.dump();
// regression for #3013 (ordered_json::reset() compile error with nvcc)
nlohmann::ordered_json metadata;
metadata.erase("key");
}

View File

@ -0,0 +1,81 @@
# Fuzz testing
Each parser of the library (JSON, BJData, BSON, CBOR, MessagePack, and UBJSON) can be fuzz tested. Currently,
[libFuzzer](https://llvm.org/docs/LibFuzzer.html) and [afl++](https://github.com/AFLplusplus/AFLplusplus) are supported.
## Corpus creation
For most effective fuzzing, a [corpus](https://llvm.org/docs/LibFuzzer.html#corpus) should be provided. A corpus is a
directory with some simple input files that cover several features of the parser and is hence a good starting point
for mutations.
```shell
TEST_DATA_VERSION=3.1.0
wget https://github.com/nlohmann/json_test_data/archive/refs/tags/v$TEST_DATA_VERSION.zip
unzip v$TEST_DATA_VERSION.zip
rm v$TEST_DATA_VERSION.zip
for FORMAT in json bjdata bson cbor msgpack ubjson
do
rm -fr corpus_$FORMAT
mkdir corpus_$FORMAT
find json_test_data-$TEST_DATA_VERSION -size -5k -name "*.$FORMAT" -exec cp "{}" "corpus_$FORMAT" \;
done
rm -fr json_test_data-$TEST_DATA_VERSION
```
The generated corpus can be used with both libFuzzer and afl++. The remainder of this documentation assumes the corpus
directories have been created in the `tests` directory.
## libFuzzer
To use libFuzzer, you need to pass `-fsanitize=fuzzer` as `FUZZER_ENGINE`. In the `tests` directory, call
```shell
make fuzzers FUZZER_ENGINE="-fsanitize=fuzzer"
```
This creates a fuzz tester binary for each parser that supports these
[command line options](https://llvm.org/docs/LibFuzzer.html#options).
In case your default compiler is not a Clang compiler that includes libFuzzer (Clang 6.0 or later), you need to set the
`CXX` variable accordingly. Note the compiler provided by Xcode (AppleClang) does not contain libFuzzer. Please install
Clang via Homebrew calling `brew install llvm` and add `CXX=$(brew --prefix llvm)/bin/clang` to the `make` call:
```shell
make fuzzers FUZZER_ENGINE="-fsanitize=fuzzer" CXX=$(brew --prefix llvm)/bin/clang
```
Then pass the corpus directory as command-line argument (assuming it is located in `tests`):
```shell
./parse_cbor_fuzzer corpus_cbor
```
The fuzzer should be able to run indefinitely without crashing. In case of a crash, the tested input is dumped into
a file starting with `crash-`.
## afl++
To use afl++, you need to pass `-fsanitize=fuzzer` as `FUZZER_ENGINE`. It will be replaced by a `libAFLDriver.a` to
re-use the same code written for libFuzzer with afl++. Furthermore, set `afl-clang-fast++` as compiler.
```shell
CXX=afl-clang-fast++ make fuzzers FUZZER_ENGINE="-fsanitize=fuzzer"
```
Then the fuzzer is called like this in the `tests` directory:
```shell
afl-fuzz -i corpus_cbor -o out -- ./parse_cbor_fuzzer
```
The fuzzer should be able to run indefinitely without crashing. In case of a crash, the tested input is written to the
directory `out`.
## OSS-Fuzz
The library is further fuzz-tested 24/7 by Google's [OSS-Fuzz project](https://github.com/google/oss-fuzz). It uses
the same `fuzzers` target as above and also relies on the `FUZZER_ENGINE` variable. See the used
[build script](https://github.com/google/oss-fuzz/blob/master/projects/json/build.sh) for more information.
In case the build at OSS-Fuzz fails, an issue will be created automatically.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,10 @@
<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
<tr><td style="width: 18ex"><b>Banner:</b></td><td>fuzz</td></tr>
<tr><td><b>Directory:</b></td><td>fuzz-testing/out</td></tr>
<tr><td><b>Generated on:</b></td><td>Mo 29 Aug 2016 22:14:22 CEST</td></tr>
</table>
<p>
<img src="high_freq.png" width=1000 height=300><p>
<img src="low_freq.png" width=1000 height=200><p>
<img src="exec_speed.png" width=1000 height=200>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,31 @@
Results of the latest benchmark from <https://github.com/miloyip/nativejson-benchmark>.
See <https://github.com/nlohmann/json/issues/307> for discussion.
Original post at 2016-09-09 to <json@yahoogroups.com>:
> Hi,
>
> This benchmark evaluated conformance, parse/stringify speed/memory, and
> code size. It can also be viewed as a long list of open source C/C++ JSON
> libraries.
>
> You can run the benchmark on your own machine by checkout this project.
>
> https://github.com/miloyip/nativejson-benchmark
>
> You can also view some sample results here:
>
> https://rawgit.com/miloyip/nativejson-benchmark/master/sample/conformance.html
> https://rawgit.com/miloyip/nativejson-benchmark/master/sample/performance_Corei7-4980HQ@2.80GHz_mac64_clang7.0.html
>
> If you make a new library, you may use this for testing conformance and
> performance. Afterwards, please submit a pull request.
>
> Enjoy!
>
> --
> Milo Yip
>
> https://github.com/miloyip/
> http://twitter.com/miloyip/

View File

@ -0,0 +1,670 @@
<!DOCTYPE html>
<html lang="en" class="">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
<meta charset='utf-8'>
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-3a71f36dec04358c4f2f42280fb2cf5c38856f935a3f609eab0a1ae31b1d635a.css" media="all" rel="stylesheet" />
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-5c885e880e980dc7f119393287b84906d930ccaff83f6bff8ae2c086b87ca4d8.css" media="all" rel="stylesheet" />
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-4ef7bbe907458c89cb1f7f5c5e6c4cd87e03acf66b1817325e644920d2a83330.css" media="all" rel="stylesheet" />
<link as="script" href="https://assets-cdn.github.com/assets/frameworks-88471af1fec40ff9418efbe2ddd15b6896af8d772f8179004c254dffc25ea490.js" rel="preload" />
<link as="script" href="https://assets-cdn.github.com/assets/github-e18e11a943ff2eb9394c72d4ec8b76592c454915b5839ae177d422777a046e29.js" rel="preload" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Language" content="en">
<meta name="viewport" content="width=device-width">
<title>nativejson-benchmark/conformance_Nlohmann (C++11).md at master · miloyip/nativejson-benchmark · GitHub</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
<meta property="fb:app_id" content="1401488693436528">
<meta content="https://avatars2.githubusercontent.com/u/1195774?v=3&amp;s=400" name="twitter:image:src" /><meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="miloyip/nativejson-benchmark" name="twitter:title" /><meta content="nativejson-benchmark - C/C++ JSON parser/generator benchmark" name="twitter:description" />
<meta content="https://avatars2.githubusercontent.com/u/1195774?v=3&amp;s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="miloyip/nativejson-benchmark" property="og:title" /><meta content="https://github.com/miloyip/nativejson-benchmark" property="og:url" /><meta content="nativejson-benchmark - C/C++ JSON parser/generator benchmark" property="og:description" />
<meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
<meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
<link rel="assets" href="https://assets-cdn.github.com/">
<meta name="pjax-timeout" content="1000">
<meta name="request-id" content="D4563DA7:75ED:525C921:57D6FEBB" data-pjax-transient>
<meta name="msapplication-TileImage" content="/windows-tile.png">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="selected-link" value="repo_source" data-pjax-transient>
<meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
<meta name="google-analytics" content="UA-3769691-2">
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="D4563DA7:75ED:525C921:57D6FEBB" name="octolytics-dimension-request_id" />
<meta content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-pjax-transient="true" name="analytics-location" />
<meta class="js-ga-set" name="dimension1" content="Logged Out">
<meta name="hostname" content="github.com">
<meta name="user-login" content="">
<meta name="expected-hostname" content="github.com">
<meta name="js-proxy-site-detection-payload" content="N2RkMmY1ZjE1MTA4MzRhYTA5NDNkMjliNDU3OTA3ZTdlMGNmNDZjN2QyODBiZjM3MmYzMjFjNzY1ZjIwNjY4NHx7InJlbW90ZV9hZGRyZXNzIjoiMjEyLjg2LjYxLjE2NyIsInJlcXVlc3RfaWQiOiJENDU2M0RBNzo3NUVEOjUyNUM5MjE6NTdENkZFQkIiLCJ0aW1lc3RhbXAiOjE0NzM3MDc3MDh9">
<link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#4078c0">
<link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">
<meta name="html-safe-nonce" content="deea0f406df2fb95709865c5ee80a255d8c47fa9">
<meta content="736eea9d74cf34fe850d2180e8a5f0a1cc7bc0be" name="form-nonce" />
<meta http-equiv="x-pjax-version" content="f302977937abe3fe1c9a4d4bed913565">
<meta name="description" content="nativejson-benchmark - C/C++ JSON parser/generator benchmark">
<meta name="go-import" content="github.com/miloyip/nativejson-benchmark git https://github.com/miloyip/nativejson-benchmark.git">
<meta content="1195774" name="octolytics-dimension-user_id" /><meta content="miloyip" name="octolytics-dimension-user_login" /><meta content="22976798" name="octolytics-dimension-repository_id" /><meta content="miloyip/nativejson-benchmark" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="22976798" name="octolytics-dimension-repository_network_root_id" /><meta content="miloyip/nativejson-benchmark" name="octolytics-dimension-repository_network_root_nwo" />
<link href="https://github.com/miloyip/nativejson-benchmark/commits/master.atom" rel="alternate" title="Recent Commits to nativejson-benchmark:master" type="application/atom+xml">
<link rel="canonical" href="https://github.com/miloyip/nativejson-benchmark/blob/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" data-pjax-transient>
</head>
<body class="logged-out env-production vis-public page-blob">
<div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div>
<a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a>
<header class="site-header js-details-container" role="banner">
<div class="container-responsive">
<a class="header-logo-invertocat" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark">
<svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
</a>
<button class="btn-link float-right site-header-toggle js-details-target" type="button" aria-label="Toggle navigation">
<svg aria-hidden="true" class="octicon octicon-three-bars" height="24" version="1.1" viewBox="0 0 12 16" width="18"><path d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"></path></svg>
</button>
<div class="site-header-menu">
<nav class="site-header-nav site-header-nav-main">
<a href="/personal" class="js-selected-navigation-item nav-item nav-item-personal" data-ga-click="Header, click, Nav menu - item:personal" data-selected-links="/personal /personal">
Personal
</a> <a href="/open-source" class="js-selected-navigation-item nav-item nav-item-opensource" data-ga-click="Header, click, Nav menu - item:opensource" data-selected-links="/open-source /open-source">
Open source
</a> <a href="/business" class="js-selected-navigation-item nav-item nav-item-business" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/partners /business/features /business/customers /business">
Business
</a> <a href="/explore" class="js-selected-navigation-item nav-item nav-item-explore" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship /explore">
Explore
</a> </nav>
<div class="site-header-actions">
<a class="btn btn-primary site-header-actions-btn" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a>
<a class="btn site-header-actions-btn mr-2" href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark%2Fblob%2Fmaster%2Fsample%2Fconformance_Nlohmann%2520%28C%252B%252B11%29.md" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a>
</div>
<nav class="site-header-nav site-header-nav-secondary">
<a class="nav-item" href="/pricing">Pricing</a>
<a class="nav-item" href="/blog">Blog</a>
<a class="nav-item" href="https://help.github.com">Support</a>
<a class="nav-item header-search-link" href="https://github.com/search">Search GitHub</a>
<div class="header-search scoped-search site-scoped-search js-site-search" role="search">
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="/miloyip/nativejson-benchmark/search" class="js-site-search-form" data-scoped-search-url="/miloyip/nativejson-benchmark/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>
<label class="form-control header-search-wrapper js-chromeless-input-container">
<div class="header-search-scope">This repository</div>
<input type="text"
class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable"
data-hotkey="s"
name="q"
placeholder="Search"
aria-label="Search this repository"
data-unscoped-placeholder="Search GitHub"
data-scoped-placeholder="Search"
autocapitalize="off">
</label>
</form></div>
</nav>
</div>
</div>
</header>
<div id="start-of-content" class="accessibility-aid"></div>
<div id="js-flash-container">
</div>
<div role="main">
<div itemscope itemtype="http://schema.org/SoftwareSourceCode">
<div id="js-repo-pjax-container" data-pjax-container>
<div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav">
<div class="container repohead-details-container">
<ul class="pagehead-actions">
<li>
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
aria-label="You must be signed in to watch a repository" rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"></path></svg>
Watch
</a>
<a class="social-count" href="/miloyip/nativejson-benchmark/watchers"
aria-label="40 users are watching this repository">
40
</a>
</li>
<li>
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
aria-label="You must be signed in to star a repository" rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"></path></svg>
Star
</a>
<a class="social-count js-social-count" href="/miloyip/nativejson-benchmark/stargazers"
aria-label="352 users starred this repository">
352
</a>
</li>
<li>
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
aria-label="You must be signed in to fork a repository" rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>
Fork
</a>
<a href="/miloyip/nativejson-benchmark/network" class="social-count"
aria-label="59 users are forked this repository">
59
</a>
</li>
</ul>
<h1 class="public ">
<svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"></path></svg>
<span class="author" itemprop="author"><a href="/miloyip" class="url fn" rel="author">miloyip</a></span><!--
--><span class="path-divider">/</span><!--
--><strong itemprop="name"><a href="/miloyip/nativejson-benchmark" data-pjax="#js-repo-pjax-container">nativejson-benchmark</a></strong>
</h1>
</div>
<div class="container">
<nav class="reponav js-repo-nav js-sidenav-container-pjax"
itemscope
itemtype="http://schema.org/BreadcrumbList"
role="navigation"
data-pjax="#js-repo-pjax-container">
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
<a href="/miloyip/nativejson-benchmark" aria-selected="true" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /miloyip/nativejson-benchmark" itemprop="url">
<svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"></path></svg>
<span itemprop="name">Code</span>
<meta itemprop="position" content="1">
</a> </span>
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
<a href="/miloyip/nativejson-benchmark/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /miloyip/nativejson-benchmark/issues" itemprop="url">
<svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg>
<span itemprop="name">Issues</span>
<span class="counter">8</span>
<meta itemprop="position" content="2">
</a> </span>
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
<a href="/miloyip/nativejson-benchmark/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /miloyip/nativejson-benchmark/pulls" itemprop="url">
<svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>
<span itemprop="name">Pull requests</span>
<span class="counter">1</span>
<meta itemprop="position" content="3">
</a> </span>
<a href="/miloyip/nativejson-benchmark/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="pulse /miloyip/nativejson-benchmark/pulse">
<svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0v2h3.6l.9-1.8.9 5.4L9 8.5l1.6 1.5H14V8z"></path></svg>
Pulse
</a>
<a href="/miloyip/nativejson-benchmark/graphs" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors /miloyip/nativejson-benchmark/graphs">
<svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"></path></svg>
Graphs
</a>
</nav>
</div>
</div>
<div class="container new-discussion-timeline experiment-repo-nav">
<div class="repository-content">
<a href="/miloyip/nativejson-benchmark/blob/95f27ebcf9a96c7ca4cee26467ed5420140090fb/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a>
<!-- blob contrib key: blob_contributors:v21:0bf9e3593dedd91db6c9dc69e13b7f95 -->
<div class="file-navigation js-zeroclipboard-container">
<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left">
<button class="btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w"
type="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true">
<i>Branch:</i>
<span class="js-select-button css-truncate-target">master</span>
</button>
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true">
<div class="select-menu-modal">
<div class="select-menu-header">
<svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
<span class="select-menu-title">Switch branches/tags</span>
</div>
<div class="select-menu-filters">
<div class="select-menu-text-filter">
<input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
</div>
<div class="select-menu-tabs">
<ul>
<li class="select-menu-tab">
<a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a>
</li>
<li class="select-menu-tab">
<a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a>
</li>
</ul>
</div>
</div>
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/Stixjson/sample/conformance_Nlohmann%20(C++11).md"
data-name="Stixjson"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
Stixjson
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/ccan/sample/conformance_Nlohmann%20(C++11).md"
data-name="ccan"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
ccan
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/jbson/sample/conformance_Nlohmann%20(C++11).md"
data-name="jbson"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
jbson
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/jute/sample/conformance_Nlohmann%20(C++11).md"
data-name="jute"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
jute
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/lastjson/sample/conformance_Nlohmann%20(C++11).md"
data-name="lastjson"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
lastjson
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/libjson/sample/conformance_Nlohmann%20(C++11).md"
data-name="libjson"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
libjson
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open selected"
href="/miloyip/nativejson-benchmark/blob/master/sample/conformance_Nlohmann%20(C++11).md"
data-name="master"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
master
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/qt/sample/conformance_Nlohmann%20(C++11).md"
data-name="qt"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
qt
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/tunnuz/sample/conformance_Nlohmann%20(C++11).md"
data-name="tunnuz"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
tunnuz
</span>
</a>
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/blob/ujson/sample/conformance_Nlohmann%20(C++11).md"
data-name="ujson"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
ujson
</span>
</a>
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div>
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
<a class="select-menu-item js-navigation-item js-navigation-open "
href="/miloyip/nativejson-benchmark/tree/v1.0.0/sample/conformance_Nlohmann%20(C%2B%2B11).md"
data-name="v1.0.0"
data-skip-pjax="true"
rel="nofollow">
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
<span class="select-menu-item-text css-truncate-target" title="v1.0.0">
v1.0.0
</span>
</a>
</div>
<div class="select-menu-no-results">Nothing to show</div>
</div>
</div>
</div>
</div>
<div class="btn-group float-right">
<a href="/miloyip/nativejson-benchmark/find/master"
class="js-pjax-capture-input btn btn-sm"
data-pjax
data-hotkey="t">
Find file
</a>
<button aria-label="Copy file path to clipboard" class="js-zeroclipboard btn btn-sm zeroclipboard-button tooltipped tooltipped-s" data-copied-hint="Copied!" type="button">Copy path</button>
</div>
<div class="breadcrumb js-zeroclipboard-target">
<span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/miloyip/nativejson-benchmark"><span>nativejson-benchmark</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a href="/miloyip/nativejson-benchmark/tree/master/sample"><span>sample</span></a></span><span class="separator">/</span><strong class="final-path">conformance_Nlohmann (C++11).md</strong>
</div>
</div>
<div class="commit-tease">
<span class="float-right">
<a class="commit-tease-sha" href="/miloyip/nativejson-benchmark/commit/a4a9f10f41c515d6abb0f019ab9f5d021ed4bb9e" data-pjax>
a4a9f10
</a>
<relative-time datetime="2016-09-09T03:15:21Z">Sep 9, 2016</relative-time>
</span>
<div>
<img alt="@miloyip" class="avatar" height="20" src="https://avatars3.githubusercontent.com/u/1195774?v=3&amp;s=40" width="20" />
<a href="/miloyip" class="user-mention" rel="author">miloyip</a>
<a href="/miloyip/nativejson-benchmark/commit/a4a9f10f41c515d6abb0f019ab9f5d021ed4bb9e" class="message" data-pjax="true" title="Update sample result for 41 libraries
Fixed #43">Update sample result for 41 libraries</a>
</div>
<div class="commit-tease-contributors">
<button type="button" class="btn-link muted-link contributors-toggle" data-facebox="#blob_contributors_box">
<strong>1</strong>
contributor
</button>
</div>
<div id="blob_contributors_box" style="display:none">
<h2 class="facebox-header" data-facebox-id="facebox-header">Users who have contributed to this file</h2>
<ul class="facebox-user-list" data-facebox-id="facebox-description">
<li class="facebox-user-list-item">
<img alt="@miloyip" height="24" src="https://avatars1.githubusercontent.com/u/1195774?v=3&amp;s=48" width="24" />
<a href="/miloyip">miloyip</a>
</li>
</ul>
</div>
</div>
<div class="file">
<div class="file-header">
<div class="file-actions">
<div class="btn-group">
<a href="/miloyip/nativejson-benchmark/raw/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm " id="raw-url">Raw</a>
<a href="/miloyip/nativejson-benchmark/blame/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm js-update-url-with-hash">Blame</a>
<a href="/miloyip/nativejson-benchmark/commits/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm " rel="nofollow">History</a>
</div>
<button type="button" class="btn-octicon disabled tooltipped tooltipped-nw"
aria-label="You must be signed in to make or propose changes">
<svg aria-hidden="true" class="octicon octicon-pencil" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"></path></svg>
</button>
<button type="button" class="btn-octicon btn-octicon-danger disabled tooltipped tooltipped-nw"
aria-label="You must be signed in to make or propose changes">
<svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"></path></svg>
</button>
</div>
<div class="file-info">
59 lines (37 sloc)
<span class="file-info-divider"></span>
545 Bytes
</div>
</div>
<div id="readme" class="readme blob instapaper_body">
<article class="markdown-body entry-content" itemprop="text"><h1><a id="user-content-conformance-of-nlohmann-c11" class="anchor" href="#conformance-of-nlohmann-c11" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conformance of Nlohmann (C++11)</h1>
<h2><a id="user-content-1-parse-validation" class="anchor" href="#1-parse-validation" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>1. Parse Validation</h2>
<p>Summary: 34 of 34 are correct.</p>
<h2><a id="user-content-2-parse-double" class="anchor" href="#2-parse-double" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>2. Parse Double</h2>
<p>Summary: 66 of 66 are correct.</p>
<h2><a id="user-content-3-parse-string" class="anchor" href="#3-parse-string" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>3. Parse String</h2>
<p>Summary: 9 of 9 are correct.</p>
<h2><a id="user-content-4-roundtrip" class="anchor" href="#4-roundtrip" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4. Roundtrip</h2>
<ul>
<li>Fail:</li>
</ul>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">5e-324</span>]</pre></div>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">4.94065645841247e-324</span>]</pre></div>
<ul>
<li>Fail:</li>
</ul>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.225073858507201e-308</span>]</pre></div>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072e-308</span>]</pre></div>
<ul>
<li>Fail:</li>
</ul>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072014e-308</span>]</pre></div>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072e-308</span>]</pre></div>
<ul>
<li>Fail:</li>
</ul>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">1.7976931348623157e308</span>]</pre></div>
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">1.79769313486232e+308</span>]</pre></div>
<p>Summary: 23 of 27 are correct.</p>
</article>
</div>
</div>
<button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="d-none">Jump to Line</button>
<div id="jump-to-line" style="display:none">
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>
<input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus>
<button type="submit" class="btn">Go</button>
</form></div>
</div>
<div class="modal-backdrop js-touch-events"></div>
</div>
</div>
</div>
</div>
<div class="container site-footer-container">
<div class="site-footer" role="contentinfo">
<ul class="site-footer-links float-right">
<li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li>
<li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
<li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
<li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>
<li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
<li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>
</ul>
<a href="https://github.com" aria-label="Homepage" class="site-footer-mark" title="GitHub">
<svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
</a>
<ul class="site-footer-links">
<li>&copy; 2016 <span title="0.18611s from github-fe151-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
<li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>
<li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>
<li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li>
<li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
<li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>
</ul>
</div>
</div>
<div id="ajax-error-message" class="ajax-error-message flash flash-error">
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg>
<button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
</button>
You can't perform that action at this time.
</div>
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/compat-40e365359d1c4db1e36a55be458e60f2b7c24d58b5a00ae13398480e7ba768e0.js"></script>
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-88471af1fec40ff9418efbe2ddd15b6896af8d772f8179004c254dffc25ea490.js"></script>
<script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-e18e11a943ff2eb9394c72d4ec8b76592c454915b5839ae177d422777a046e29.js"></script>
<div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none">
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg>
<span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
<span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
</div>
<div class="facebox" id="facebox" style="display:none;">
<div class="facebox-popup">
<div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
</div>
<button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
</button>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,10 @@
<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
<tr><td style="width: 18ex"><b>Banner:</b></td><td>fuzz</td></tr>
<tr><td><b>Directory:</b></td><td>fuzz-testing/out</td></tr>
<tr><td><b>Generated on:</b></td><td>Sun Oct 2 08:51:02 CEST 2016</td></tr>
</table>
<p>
<img src="high_freq.png" width=1000 height=300><p>
<img src="low_freq.png" width=1000 height=200><p>
<img src="exec_speed.png" width=1000 height=200>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,39 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
an implementation of the `LLVMFuzzerTestOneInput` function which processes a
passed byte array.
*/
#include <vector> // for vector
#include <cstdint> // for uint8_t
#include <iostream> // for cin
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
int main()
{
#ifdef __AFL_HAVE_MANUAL_CONTROL
while (__AFL_LOOP(1000))
{
#endif
// copy stdin to byte vector
std::vector<uint8_t> vec;
char c = 0;
while (std::cin.get(c))
{
vec.push_back(static_cast<uint8_t>(c));
}
LLVMFuzzerTestOneInput(vec.data(), vec.size());
#ifdef __AFL_HAVE_MANUAL_CONTROL
}
#endif
}

View File

@ -0,0 +1,85 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = from_bjdata(data)
- vec = to_bjdata(j1)
- j2 = from_bjdata(vec)
- assert(j1 == j2)
- vec2 = to_bjdata(j1, use_size = true, use_type = false)
- j3 = from_bjdata(vec2)
- assert(j1 == j3)
- vec3 = to_bjdata(j1, use_size = true, use_type = true)
- j4 = from_bjdata(vec3)
- assert(j1 == j4)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
std::vector<uint8_t> const vec1(data, data + size);
json const j1 = json::from_bjdata(vec1);
try
{
// step 2.1: round trip without adding size annotations to container types
std::vector<uint8_t> const vec2 = json::to_bjdata(j1, false, false);
// step 2.2: round trip with adding size annotations but without adding type annotations to container types
std::vector<uint8_t> const vec3 = json::to_bjdata(j1, true, false);
// step 2.3: round trip with adding size as well as type annotations to container types
std::vector<uint8_t> const vec4 = json::to_bjdata(j1, true, true);
// parse serialization
json const j2 = json::from_bjdata(vec2);
json const j3 = json::from_bjdata(vec3);
json const j4 = json::from_bjdata(vec4);
// serializations must match
assert(json::to_bjdata(j2, false, false) == vec2);
assert(json::to_bjdata(j3, true, false) == vec3);
assert(json::to_bjdata(j4, true, true) == vec4);
}
catch (const json::parse_error&)
{
// parsing a BJData serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::type_error&)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors may happen if provided sizes are excessive
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,74 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = from_bson(data)
- vec = to_bson(j1)
- j2 = from_bson(vec)
- assert(j1 == j2)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
std::vector<uint8_t> const vec1(data, data + size);
json const j1 = json::from_bson(vec1);
if (j1.is_discarded())
{
return 0;
}
try
{
// step 2: round trip
std::vector<uint8_t> const vec2 = json::to_bson(j1);
// parse serialization
json const j2 = json::from_bson(vec2);
// serializations must match
assert(json::to_bson(j2) == vec2);
}
catch (const json::parse_error&)
{
// parsing a BSON serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::type_error&)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors can occur during parsing, too
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,69 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = from_cbor(data)
- vec = to_cbor(j1)
- j2 = from_cbor(vec)
- assert(j1 == j2)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
std::vector<uint8_t> const vec1(data, data + size);
json const j1 = json::from_cbor(vec1);
try
{
// step 2: round trip
std::vector<uint8_t> const vec2 = json::to_cbor(j1);
// parse serialization
json const j2 = json::from_cbor(vec2);
// serializations must match
assert(json::to_cbor(j2) == vec2);
}
catch (const json::parse_error&)
{
// parsing a CBOR serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::type_error&)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors can occur during parsing, too
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,70 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = parse(data)
- s1 = serialize(j1)
- j2 = parse(s1)
- s2 = serialize(j2)
- assert(s1 == s2)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
json const j1 = json::parse(data, data + size);
try
{
// step 2: round trip
// first serialization
std::string const s1 = j1.dump();
// parse serialization
json const j2 = json::parse(s1);
// second serialization
std::string const s2 = j2.dump();
// serializations must match
assert(s1 == s2);
}
catch (const json::parse_error&)
{
// parsing a JSON serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::out_of_range&)
{
// out of range errors may happen if provided sizes are excessive
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,69 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = from_msgpack(data)
- vec = to_msgpack(j1)
- j2 = from_msgpack(vec)
- assert(j1 == j2)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
std::vector<uint8_t> const vec1(data, data + size);
json const j1 = json::from_msgpack(vec1);
try
{
// step 2: round trip
std::vector<uint8_t> const vec2 = json::to_msgpack(j1);
// parse serialization
json const j2 = json::from_msgpack(vec2);
// serializations must match
assert(json::to_msgpack(j2) == vec2);
}
catch (const json::parse_error&)
{
// parsing a MessagePack serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::type_error&)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors may happen if provided sizes are excessive
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,85 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
/*
This file implements a parser test suitable for fuzz testing. Given a byte
array data, it performs the following steps:
- j1 = from_ubjson(data)
- vec = to_ubjson(j1)
- j2 = from_ubjson(vec)
- assert(j1 == j2)
- vec2 = to_ubjson(j1, use_size = true, use_type = false)
- j3 = from_ubjson(vec2)
- assert(j1 == j3)
- vec3 = to_ubjson(j1, use_size = true, use_type = true)
- j4 = from_ubjson(vec3)
- assert(j1 == j4)
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
drivers.
*/
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// see http://llvm.org/docs/LibFuzzer.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
// step 1: parse input
std::vector<uint8_t> const vec1(data, data + size);
json const j1 = json::from_ubjson(vec1);
try
{
// step 2.1: round trip without adding size annotations to container types
std::vector<uint8_t> const vec2 = json::to_ubjson(j1, false, false);
// step 2.2: round trip with adding size annotations but without adding type annotations to container types
std::vector<uint8_t> const vec3 = json::to_ubjson(j1, true, false);
// step 2.3: round trip with adding size as well as type annotations to container types
std::vector<uint8_t> const vec4 = json::to_ubjson(j1, true, true);
// parse serialization
json const j2 = json::from_ubjson(vec2);
json const j3 = json::from_ubjson(vec3);
json const j4 = json::from_ubjson(vec4);
// serializations must match
assert(json::to_ubjson(j2, false, false) == vec2);
assert(json::to_ubjson(j3, true, false) == vec3);
assert(json::to_ubjson(j4, true, true) == vec4);
}
catch (const json::parse_error&)
{
// parsing a UBJSON serialization must not fail
assert(false);
}
}
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
catch (const json::type_error&)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors may happen if provided sizes are excessive
}
// return 0 - non-zero return values are reserved for future use
return 0;
}

View File

@ -0,0 +1,30 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include <cstdio> // fopen, fclose, FILE
#include <memory> // unique_ptr
#include <test_data.hpp>
#include <doctest.h>
namespace utils
{
inline bool check_testsuite_downloaded()
{
const std::unique_ptr<std::FILE, decltype(&std::fclose)> file(std::fopen(TEST_DATA_DIRECTORY "/README.md", "r"), &std::fclose);
return file != nullptr;
}
TEST_CASE("check test suite is downloaded")
{
REQUIRE_MESSAGE(utils::check_testsuite_downloaded(), "Test data not found in '" TEST_DATA_DIRECTORY "'. Please execute target 'download_test_data' before running this test suite. See <https://github.com/nlohmann/json#execute-unit-tests> for more information.");
}
} // namespace utils

View File

@ -0,0 +1,33 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
#include <cstdint> // uint8_t
#include <fstream> // ifstream, istreambuf_iterator, ios
#include <vector> // vector
namespace utils
{
inline std::vector<std::uint8_t> read_binary_file(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws);
file.seekg(0, std::ios::end);
const auto size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<std::uint8_t> byte_vector;
byte_vector.reserve(static_cast<std::size_t>(size));
byte_vector.insert(byte_vector.begin(), std::istream_iterator<std::uint8_t>(file), std::istream_iterator<std::uint8_t>());
return byte_vector;
}
} // namespace utils

View File

@ -0,0 +1,134 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <climits> // SIZE_MAX
#include <limits> // numeric_limits
template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
struct trait_test_arg
{
using of_type = OfType;
using type = T;
static constexpr bool min_in_range = MinInRange;
static constexpr bool max_in_range = MaxInRange;
};
TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test)
{
using nlohmann::detail::value_in_range_of;
using of_type = typename T::of_type;
using type = typename T::type;
constexpr bool min_in_range = T::min_in_range;
constexpr bool max_in_range = T::max_in_range;
type const val_min = std::numeric_limits<type>::min();
type const val_min2 = val_min + 1;
type const val_max = std::numeric_limits<type>::max();
type const val_max2 = val_max - 1;
REQUIRE(CHAR_BIT == 8);
std::string of_type_str;
if (std::is_unsigned<of_type>::value)
{
of_type_str += "u";
}
of_type_str += "int";
of_type_str += std::to_string(sizeof(of_type) * 8);
INFO("of_type := ", of_type_str);
std::string type_str;
if (std::is_unsigned<type>::value)
{
type_str += "u";
}
type_str += "int";
type_str += std::to_string(sizeof(type) * 8);
INFO("type := ", type_str);
CAPTURE(val_min);
CAPTURE(min_in_range);
CAPTURE(val_max);
CAPTURE(max_in_range);
if (min_in_range)
{
CHECK(value_in_range_of<of_type>(val_min));
CHECK(value_in_range_of<of_type>(val_min2));
}
else
{
CHECK_FALSE(value_in_range_of<of_type>(val_min));
CHECK_FALSE(value_in_range_of<of_type>(val_min2));
}
if (max_in_range)
{
CHECK(value_in_range_of<of_type>(val_max));
CHECK(value_in_range_of<of_type>(val_max2));
}
else
{
CHECK_FALSE(value_in_range_of<of_type>(val_max));
CHECK_FALSE(value_in_range_of<of_type>(val_max2));
}
}
TEST_CASE("32bit")
{
REQUIRE(SIZE_MAX == 0xffffffff);
}
TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
trait_test_arg<std::size_t, std::int32_t, false, true>, \
trait_test_arg<std::size_t, std::uint32_t, true, true>, \
trait_test_arg<std::size_t, std::int64_t, false, false>, \
trait_test_arg<std::size_t, std::uint64_t, true, false>);
TEST_CASE("BJData")
{
SECTION("parse errors")
{
SECTION("array")
{
SECTION("optimized array: negative size")
{
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
std::vector<uint8_t> const vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
json _;
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vM, true, false).is_discarded());
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vMX, true, false).is_discarded());
}
SECTION("optimized array: integer value overflow")
{
std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
json _;
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vL, true, false).is_discarded());
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vM, true, false).is_discarded());
}
}
}
}

View File

@ -0,0 +1,365 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <algorithm>
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("algorithms")
{
json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
json j_object = {{"one", 1}, {"two", 2}};
SECTION("non-modifying sequence operations")
{
SECTION("std::all_of")
{
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
{
return !value.empty();
}));
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.type() == json::value_t::number_integer;
}));
}
SECTION("std::any_of")
{
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.is_string() && value.get<std::string>() == "foo";
}));
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.get<int>() > 1;
}));
}
SECTION("std::none_of")
{
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.empty();
}));
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.get<int>() <= 0;
}));
}
SECTION("std::for_each")
{
SECTION("reading")
{
int sum = 0;
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
{
if (value.is_number())
{
sum += static_cast<int>(value);
}
});
CHECK(sum == 45);
}
SECTION("writing")
{
auto add17 = [](json & value)
{
if (value.is_array())
{
value.push_back(17);
}
};
std::for_each(j_array.begin(), j_array.end(), add17);
CHECK(j_array[6] == json({1, 2, 3, 17}));
}
}
SECTION("std::count")
{
CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1);
}
SECTION("std::count_if")
{
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
{
return (value.is_number());
}) == 3);
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
{
return true;
}) == 9);
}
SECTION("std::mismatch")
{
json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
}
SECTION("std::equal")
{
SECTION("using operator==")
{
CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
CHECK(!std::equal(j_array.begin(), j_array.end(), j_object.begin()));
}
SECTION("using user-defined comparison")
{
// compare objects only by size of its elements
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
[](const json & a, const json & b)
{
return (a.size() == b.size());
}));
}
}
SECTION("std::find")
{
auto it = std::find(j_array.begin(), j_array.end(), json(false));
CHECK(std::distance(j_array.begin(), it) == 5);
}
SECTION("std::find_if")
{
auto it = std::find_if(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_boolean();
});
CHECK(std::distance(j_array.begin(), it) == 4);
}
SECTION("std::find_if_not")
{
auto it = std::find_if_not(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_number();
});
CHECK(std::distance(j_array.begin(), it) == 3);
}
SECTION("std::adjacent_find")
{
CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
[](const json & v1, const json & v2)
{
return v1.type() == v2.type();
}) == j_array.begin());
}
}
SECTION("modifying sequence operations")
{
SECTION("std::reverse")
{
std::reverse(j_array.begin(), j_array.end());
CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
}
SECTION("std::rotate")
{
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
}
SECTION("std::partition")
{
auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
{
return v.is_string();
});
CHECK(std::distance(j_array.begin(), it) == 2);
CHECK(!it[2].is_string());
}
}
SECTION("sorting operations")
{
SECTION("std::sort")
{
SECTION("with standard comparison")
{
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::sort(j.begin(), j.end());
CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}
SECTION("with user-defined comparison")
{
json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
std::sort(j.begin(), j.end(), [](const json & a, const json & b)
{
return a.size() < b.size();
});
CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
}
SECTION("sorting an object")
{
json j({{"one", 1}, {"two", 2}});
CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
}
}
SECTION("std::partial_sort")
{
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::partial_sort(j.begin(), j.begin() + 4, j.end());
CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
}
}
SECTION("set operations")
{
SECTION("std::merge")
{
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
}
}
SECTION("std::set_difference")
{
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({4, 6, 8}));
}
SECTION("std::set_intersection")
{
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({1, 2, 3, 5, 7}));
}
SECTION("std::set_union")
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
}
SECTION("std::set_symmetric_difference")
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
}
}
SECTION("heap operations")
{
std::make_heap(j_array.begin(), j_array.end());
CHECK(std::is_heap(j_array.begin(), j_array.end()));
std::sort_heap(j_array.begin(), j_array.end());
CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}
SECTION("iota")
{
SECTION("int")
{
json json_arr = {0, 5, 2, 4, 10, 20, 30, 40, 50, 1};
std::iota(json_arr.begin(), json_arr.end(), 0);
CHECK(json_arr == json({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
}
SECTION("double")
{
json json_arr = {0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5};
std::iota(json_arr.begin(), json_arr.end(), 0.5);
CHECK(json_arr == json({0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5}));
}
SECTION("char")
{
json json_arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1'};
std::iota(json_arr.begin(), json_arr.end(), '0');
CHECK(json_arr == json({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}));
}
}
SECTION("copy")
{
SECTION("copy without if")
{
json dest_arr;
const json source_arr = {1, 2, 3, 4};
std::copy(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr));
CHECK(dest_arr == source_arr);
}
SECTION("copy if")
{
json dest_arr;
const json source_arr = {0, 3, 6, 9, 12, 15, 20};
std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json & _value)
{
return _value.get<int>() % 3 == 0;
});
CHECK(dest_arr == json({0, 3, 6, 9, 12, 15}));
}
SECTION("copy n")
{
const json source_arr = {0, 1, 2, 3, 4, 5, 6, 7};
json dest_arr;
const unsigned char numToCopy = 2;
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
CHECK(dest_arr == json{0, 1});
}
SECTION("copy n chars")
{
const json source_arr = {'1', '2', '3', '4', '5', '6', '7'};
json dest_arr;
const unsigned char numToCopy = 4;
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
CHECK(dest_arr == json{'1', '2', '3', '4'});
}
}
}

View File

@ -0,0 +1,263 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace
{
// special test case to check if memory is leaked if constructor throws
template<class T>
struct bad_allocator : std::allocator<T>
{
using std::allocator<T>::allocator;
bad_allocator() = default;
template<class U> bad_allocator(const bad_allocator<U>& /*unused*/) { }
template<class... Args>
void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
{
throw std::bad_alloc();
}
template <class U>
struct rebind
{
using other = bad_allocator<U>;
};
};
} // namespace
TEST_CASE("bad_alloc")
{
SECTION("bad_alloc")
{
// create JSON type using the throwing allocator
using bad_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
bad_allocator>;
// creating an object should throw
CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&);
}
}
namespace
{
bool next_construct_fails = false;
bool next_destroy_fails = false;
bool next_deallocate_fails = false;
template<class T>
struct my_allocator : std::allocator<T>
{
using std::allocator<T>::allocator;
template<class... Args>
void construct(T* p, Args&& ... args)
{
if (next_construct_fails)
{
next_construct_fails = false;
throw std::bad_alloc();
}
::new (reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...);
}
void deallocate(T* p, std::size_t n)
{
if (next_deallocate_fails)
{
next_deallocate_fails = false;
throw std::bad_alloc();
}
std::allocator<T>::deallocate(p, n);
}
void destroy(T* p)
{
if (next_destroy_fails)
{
next_destroy_fails = false;
throw std::bad_alloc();
}
static_cast<void>(p); // fix MSVC's C4100 warning
p->~T();
}
template <class U>
struct rebind
{
using other = my_allocator<U>;
};
};
// allows deletion of raw pointer, usually hold by json_value
template<class T>
void my_allocator_clean_up(T* p)
{
assert(p != nullptr);
my_allocator<T> alloc;
alloc.destroy(p);
alloc.deallocate(p, 1);
}
} // namespace
TEST_CASE("controlled bad_alloc")
{
// create JSON type using the throwing allocator
using my_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
my_allocator>;
SECTION("class json_value")
{
SECTION("json_value(value_t)")
{
SECTION("object")
{
next_construct_fails = false;
auto t = my_json::value_t::object;
CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).object));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&);
next_construct_fails = false;
}
SECTION("array")
{
next_construct_fails = false;
auto t = my_json::value_t::array;
CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).array));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&);
next_construct_fails = false;
}
SECTION("string")
{
next_construct_fails = false;
auto t = my_json::value_t::string;
CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).string));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&);
next_construct_fails = false;
}
}
SECTION("json_value(const string_t&)")
{
next_construct_fails = false;
const my_json::string_t v("foo");
CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(v).string));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc&);
next_construct_fails = false;
}
}
SECTION("class basic_json")
{
SECTION("basic_json(const CompatibleObjectType&)")
{
next_construct_fails = false;
const std::map<std::string, std::string> v {{"foo", "bar"}};
CHECK_NOTHROW(my_json(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
next_construct_fails = false;
}
SECTION("basic_json(const CompatibleArrayType&)")
{
next_construct_fails = false;
const std::vector<std::string> v {"foo", "bar", "baz"};
CHECK_NOTHROW(my_json(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
next_construct_fails = false;
}
SECTION("basic_json(const typename string_t::value_type*)")
{
next_construct_fails = false;
CHECK_NOTHROW(my_json("foo"));
next_construct_fails = true;
CHECK_THROWS_AS(my_json("foo"), std::bad_alloc&);
next_construct_fails = false;
}
SECTION("basic_json(const typename string_t::value_type*)")
{
next_construct_fails = false;
const std::string s("foo");
CHECK_NOTHROW(my_json(s));
next_construct_fails = true;
CHECK_THROWS_AS(my_json(s), std::bad_alloc&);
next_construct_fails = false;
}
}
}
namespace
{
template<class T>
struct allocator_no_forward : std::allocator<T>
{
allocator_no_forward() = default;
template <class U>
allocator_no_forward(allocator_no_forward<U> /*unused*/) {}
template <class U>
struct rebind
{
using other = allocator_no_forward<U>;
};
template <class... Args>
void construct(T* p, const Args& ... args) noexcept(noexcept(::new (static_cast<void*>(p)) T(args...)))
{
// force copy even if move is available
::new (static_cast<void*>(p)) T(args...);
}
};
} // namespace
TEST_CASE("bad my_allocator::construct")
{
SECTION("my_allocator::construct doesn't forward")
{
using bad_alloc_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
allocator_no_forward>;
bad_alloc_json j;
j["test"] = bad_alloc_json::array_t();
j["test"].push_back("should not leak");
}
}

View File

@ -0,0 +1,322 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-FileCopyrightText: 2018 Vitaliy Manushkin <agri@akamo.info>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
#include <string>
#include <utility>
/* forward declarations */
class alt_string;
bool operator<(const char* op1, const alt_string& op2) noexcept;
void int_to_string(alt_string& target, std::size_t value);
/*
* This is virtually a string class.
* It covers std::string under the hood.
*/
class alt_string
{
public:
using value_type = std::string::value_type;
static constexpr auto npos = static_cast<std::size_t>(-1);
alt_string(const char* str): str_impl(str) {}
alt_string(const char* str, std::size_t count): str_impl(str, count) {}
alt_string(size_t count, char chr): str_impl(count, chr) {}
alt_string() = default;
template <typename...TParams>
alt_string& append(TParams&& ...params)
{
str_impl.append(std::forward<TParams>(params)...);
return *this;
}
void push_back(char c)
{
str_impl.push_back(c);
}
template <typename op_type>
bool operator==(const op_type& op) const
{
return str_impl == op;
}
bool operator==(const alt_string& op) const
{
return str_impl == op.str_impl;
}
template <typename op_type>
bool operator!=(const op_type& op) const
{
return str_impl != op;
}
bool operator!=(const alt_string& op) const
{
return str_impl != op.str_impl;
}
std::size_t size() const noexcept
{
return str_impl.size();
}
void resize (std::size_t n)
{
str_impl.resize(n);
}
void resize (std::size_t n, char c)
{
str_impl.resize(n, c);
}
template <typename op_type>
bool operator<(const op_type& op) const noexcept
{
return str_impl < op;
}
bool operator<(const alt_string& op) const noexcept
{
return str_impl < op.str_impl;
}
const char* c_str() const
{
return str_impl.c_str();
}
char& operator[](std::size_t index)
{
return str_impl[index];
}
const char& operator[](std::size_t index) const
{
return str_impl[index];
}
char& back()
{
return str_impl.back();
}
const char& back() const
{
return str_impl.back();
}
void clear()
{
str_impl.clear();
}
const value_type* data() const
{
return str_impl.data();
}
bool empty() const
{
return str_impl.empty();
}
std::size_t find(const alt_string& str, std::size_t pos = 0) const
{
return str_impl.find(str.str_impl, pos);
}
std::size_t find_first_of(char c, std::size_t pos = 0) const
{
return str_impl.find_first_of(c, pos);
}
alt_string substr(std::size_t pos = 0, std::size_t count = npos) const
{
const std::string s = str_impl.substr(pos, count);
return {s.data(), s.size()};
}
alt_string& replace(std::size_t pos, std::size_t count, const alt_string& str)
{
str_impl.replace(pos, count, str.str_impl);
return *this;
}
private:
std::string str_impl {};
friend bool operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept;
};
void int_to_string(alt_string& target, std::size_t value)
{
target = std::to_string(value).c_str();
}
using alt_json = nlohmann::basic_json <
std::map,
std::vector,
alt_string,
bool,
std::int64_t,
std::uint64_t,
double,
std::allocator,
nlohmann::adl_serializer >;
bool operator<(const char* op1, const alt_string& op2) noexcept
{
return op1 < op2.str_impl;
}
TEST_CASE("alternative string type")
{
SECTION("dump")
{
{
alt_json doc;
doc["pi"] = 3.141;
alt_string dump = doc.dump();
CHECK(dump == R"({"pi":3.141})");
}
{
alt_json doc;
doc["happy"] = true;
alt_string dump = doc.dump();
CHECK(dump == R"({"happy":true})");
}
{
alt_json doc;
doc["name"] = "I'm Batman";
alt_string dump = doc.dump();
CHECK(dump == R"({"name":"I'm Batman"})");
}
{
alt_json doc;
doc["nothing"] = nullptr;
alt_string dump = doc.dump();
CHECK(dump == R"({"nothing":null})");
}
{
alt_json doc;
doc["answer"]["everything"] = 42;
alt_string dump = doc.dump();
CHECK(dump == R"({"answer":{"everything":42}})");
}
{
alt_json doc;
doc["list"] = { 1, 0, 2 };
alt_string dump = doc.dump();
CHECK(dump == R"({"list":[1,0,2]})");
}
{
alt_json doc;
doc["object"] = { {"currency", "USD"}, {"value", 42.99} };
alt_string dump = doc.dump();
CHECK(dump == R"({"object":{"currency":"USD","value":42.99}})");
}
}
SECTION("parse")
{
auto doc = alt_json::parse(R"({"foo": "bar"})");
alt_string dump = doc.dump();
CHECK(dump == R"({"foo":"bar"})");
}
SECTION("items")
{
auto doc = alt_json::parse(R"({"foo": "bar"})");
for (const auto& item : doc.items())
{
CHECK(item.key() == "foo");
CHECK(item.value() == "bar");
}
auto doc_array = alt_json::parse(R"(["foo", "bar"])");
for (const auto& item : doc_array.items())
{
if (item.key() == "0" )
{
CHECK( item.value() == "foo" );
}
else if (item.key() == "1" )
{
CHECK(item.value() == "bar");
}
else
{
CHECK(false);
}
}
}
SECTION("equality")
{
alt_json doc;
doc["Who are you?"] = "I'm Batman";
CHECK("I'm Batman" == doc["Who are you?"]);
CHECK(doc["Who are you?"] == "I'm Batman");
CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
{
const alt_json& const_doc = doc;
CHECK("I'm Batman" == const_doc["Who are you?"]);
CHECK(const_doc["Who are you?"] == "I'm Batman");
CHECK_FALSE("I'm Batman" != const_doc["Who are you?"]);
CHECK_FALSE(const_doc["Who are you?"] != "I'm Batman");
CHECK("I'm Bruce Wayne" != const_doc["Who are you?"]);
CHECK(const_doc["Who are you?"] != "I'm Bruce Wayne");
CHECK_FALSE("I'm Bruce Wayne" == const_doc["Who are you?"]);
CHECK_FALSE(const_doc["Who are you?"] == "I'm Bruce Wayne");
}
}
SECTION("JSON pointer")
{
// conversion from json to alt_json fails to compile (see #3425);
// attempted fix(*) produces: [[['b','a','r'],['b','a','z']]] (with each char being an integer)
// (*) disable implicit conversion for json_refs of any basic_json type
// alt_json j = R"(
// {
// "foo": ["bar", "baz"]
// }
// )"_json;
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
CHECK(j.at(alt_json::json_pointer("/foo/1")) == j["foo"][1]);
}
}

View File

@ -0,0 +1,48 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
// avoid warning when assert does not abort
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wstrict-overflow")
/// global variable to record side effect of assert calls
static int assert_counter;
/// set failure variable to true instead of calling assert(x)
#define JSON_ASSERT(x) {if (!(x)) ++assert_counter; }
#include <nlohmann/json.hpp>
using nlohmann::json;
// the test assumes exceptions to work
#if !defined(JSON_NOEXCEPTION)
TEST_CASE("JSON_ASSERT(x)")
{
SECTION("basic_json(first, second)")
{
assert_counter = 0;
CHECK(assert_counter == 0);
const json::iterator it{};
json j;
// in case assertions do not abort execution, an exception is thrown
CHECK_THROWS_WITH_AS(json(it, j.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator);
// check that assertion actually happened
CHECK(assert_counter == 1);
}
}
#endif
DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_CLANG_SUPPRESS_WARNING_POP

View File

@ -0,0 +1,211 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include "make_test_data_available.hpp"
TEST_CASE("Binary Formats" * doctest::skip())
{
SECTION("canada.json")
{
const auto* filename = TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json";
const json j = json::parse(std::ifstream(filename));
const auto json_size = j.dump().size();
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
const auto bson_size = json::to_bson(j).size();
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
const auto ubjson_2_size = json::to_ubjson(j, true).size();
const auto ubjson_3_size = json::to_ubjson(j, true, true).size();
CHECK(json_size == 2090303);
CHECK(bjdata_1_size == 1112030);
CHECK(bjdata_2_size == 1224148);
CHECK(bjdata_3_size == 1224148);
CHECK(bson_size == 1794522);
CHECK(cbor_size == 1055552);
CHECK(msgpack_size == 1056145);
CHECK(ubjson_1_size == 1112030);
CHECK(ubjson_2_size == 1224148);
CHECK(ubjson_3_size == 1169069);
CHECK((100.0 * double(json_size) / double(json_size)) == Approx(100.0));
CHECK((100.0 * double(bjdata_1_size) / double(json_size)) == Approx(53.199));
CHECK((100.0 * double(bjdata_2_size) / double(json_size)) == Approx(58.563));
CHECK((100.0 * double(bjdata_3_size) / double(json_size)) == Approx(58.563));
CHECK((100.0 * double(bson_size) / double(json_size)) == Approx(85.849));
CHECK((100.0 * double(cbor_size) / double(json_size)) == Approx(50.497));
CHECK((100.0 * double(msgpack_size) / double(json_size)) == Approx(50.526));
CHECK((100.0 * double(ubjson_1_size) / double(json_size)) == Approx(53.199));
CHECK((100.0 * double(ubjson_2_size) / double(json_size)) == Approx(58.563));
CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(55.928));
}
SECTION("twitter.json")
{
const auto* filename = TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json";
const json j = json::parse(std::ifstream(filename));
const auto json_size = j.dump().size();
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
const auto bson_size = json::to_bson(j).size();
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
const auto ubjson_2_size = json::to_ubjson(j, true).size();
const auto ubjson_3_size = json::to_ubjson(j, true, true).size();
CHECK(json_size == 466906);
CHECK(bjdata_1_size == 425342);
CHECK(bjdata_2_size == 429970);
CHECK(bjdata_3_size == 429970);
CHECK(bson_size == 444568);
CHECK(cbor_size == 402814);
CHECK(msgpack_size == 401510);
CHECK(ubjson_1_size == 426160);
CHECK(ubjson_2_size == 430788);
CHECK(ubjson_3_size == 430798);
CHECK((100.0 * double(json_size) / double(json_size)) == Approx(100.0));
CHECK((100.0 * double(bjdata_1_size) / double(json_size)) == Approx(91.097));
CHECK((100.0 * double(bjdata_2_size) / double(json_size)) == Approx(92.089));
CHECK((100.0 * double(bjdata_3_size) / double(json_size)) == Approx(92.089));
CHECK((100.0 * double(bson_size) / double(json_size)) == Approx(95.215));
CHECK((100.0 * double(cbor_size) / double(json_size)) == Approx(86.273));
CHECK((100.0 * double(msgpack_size) / double(json_size)) == Approx(85.993));
CHECK((100.0 * double(ubjson_1_size) / double(json_size)) == Approx(91.273));
CHECK((100.0 * double(ubjson_2_size) / double(json_size)) == Approx(92.264));
CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(92.266));
}
SECTION("citm_catalog.json")
{
const auto* filename = TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json";
const json j = json::parse(std::ifstream(filename));
const auto json_size = j.dump().size();
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
const auto bson_size = json::to_bson(j).size();
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
const auto ubjson_2_size = json::to_ubjson(j, true).size();
const auto ubjson_3_size = json::to_ubjson(j, true, true).size();
CHECK(json_size == 500299);
CHECK(bjdata_1_size == 390781);
CHECK(bjdata_2_size == 433557);
CHECK(bjdata_3_size == 432964);
CHECK(bson_size == 479430);
CHECK(cbor_size == 342373);
CHECK(msgpack_size == 342473);
CHECK(ubjson_1_size == 391463);
CHECK(ubjson_2_size == 434239);
CHECK(ubjson_3_size == 425073);
CHECK((100.0 * double(json_size) / double(json_size)) == Approx(100.0));
CHECK((100.0 * double(bjdata_1_size) / double(json_size)) == Approx(78.109));
CHECK((100.0 * double(bjdata_2_size) / double(json_size)) == Approx(86.659));
CHECK((100.0 * double(bjdata_3_size) / double(json_size)) == Approx(86.541));
CHECK((100.0 * double(bson_size) / double(json_size)) == Approx(95.828));
CHECK((100.0 * double(cbor_size) / double(json_size)) == Approx(68.433));
CHECK((100.0 * double(msgpack_size) / double(json_size)) == Approx(68.453));
CHECK((100.0 * double(ubjson_1_size) / double(json_size)) == Approx(78.245));
CHECK((100.0 * double(ubjson_2_size) / double(json_size)) == Approx(86.795));
CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(84.963));
}
SECTION("jeopardy.json")
{
const auto* filename = TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json";
json j = json::parse(std::ifstream(filename));
const auto json_size = j.dump().size();
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
const auto bson_size = json::to_bson({{"", j}}).size(); // wrap array in object for BSON
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
const auto ubjson_2_size = json::to_ubjson(j, true).size();
const auto ubjson_3_size = json::to_ubjson(j, true, true).size();
CHECK(json_size == 52508728);
CHECK(bjdata_1_size == 50710965);
CHECK(bjdata_2_size == 51144830);
CHECK(bjdata_3_size == 51144830);
CHECK(bson_size == 56008520);
CHECK(cbor_size == 46187320);
CHECK(msgpack_size == 46158575);
CHECK(ubjson_1_size == 50710965);
CHECK(ubjson_2_size == 51144830);
CHECK(ubjson_3_size == 49861422);
CHECK((100.0 * double(json_size) / double(json_size)) == Approx(100.0));
CHECK((100.0 * double(bjdata_1_size) / double(json_size)) == Approx(96.576));
CHECK((100.0 * double(bjdata_2_size) / double(json_size)) == Approx(97.402));
CHECK((100.0 * double(bjdata_3_size) / double(json_size)) == Approx(97.402));
CHECK((100.0 * double(bson_size) / double(json_size)) == Approx(106.665));
CHECK((100.0 * double(cbor_size) / double(json_size)) == Approx(87.961));
CHECK((100.0 * double(msgpack_size) / double(json_size)) == Approx(87.906));
CHECK((100.0 * double(ubjson_1_size) / double(json_size)) == Approx(96.576));
CHECK((100.0 * double(ubjson_2_size) / double(json_size)) == Approx(97.402));
CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(94.958));
}
SECTION("sample.json")
{
const auto* filename = TEST_DATA_DIRECTORY "/json_testsuite/sample.json";
const json j = json::parse(std::ifstream(filename));
const auto json_size = j.dump().size();
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
// BSON cannot process the file as it contains code point U+0000
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
const auto ubjson_2_size = json::to_ubjson(j, true).size();
const auto ubjson_3_size = json::to_ubjson(j, true, true).size();
CHECK(json_size == 168677);
CHECK(bjdata_1_size == 148695);
CHECK(bjdata_2_size == 150569);
CHECK(bjdata_3_size == 150569);
CHECK(cbor_size == 147095);
CHECK(msgpack_size == 147017);
CHECK(ubjson_1_size == 148695);
CHECK(ubjson_2_size == 150569);
CHECK(ubjson_3_size == 150883);
CHECK((100.0 * double(json_size) / double(json_size)) == Approx(100.0));
CHECK((100.0 * double(bjdata_1_size) / double(json_size)) == Approx(88.153));
CHECK((100.0 * double(bjdata_2_size) / double(json_size)) == Approx(89.264));
CHECK((100.0 * double(bjdata_3_size) / double(json_size)) == Approx(89.264));
CHECK((100.0 * double(cbor_size) / double(json_size)) == Approx(87.205));
CHECK((100.0 * double(msgpack_size) / double(json_size)) == Approx(87.158));
CHECK((100.0 * double(ubjson_1_size) / double(json_size)) == Approx(88.153));
CHECK((100.0 * double(ubjson_2_size) / double(json_size)) == Approx(89.264));
CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(89.450));
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("byte_container_with_subtype")
{
using subtype_type = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>::subtype_type;
SECTION("empty container")
{
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container;
CHECK(!container.has_subtype());
CHECK(container.subtype() == static_cast<subtype_type>(-1));
container.clear_subtype();
CHECK(!container.has_subtype());
CHECK(container.subtype() == static_cast<subtype_type>(-1));
container.set_subtype(42);
CHECK(container.has_subtype());
CHECK(container.subtype() == 42);
}
SECTION("subtyped container")
{
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container({}, 42);
CHECK(container.has_subtype());
CHECK(container.subtype() == 42);
container.clear_subtype();
CHECK(!container.has_subtype());
CHECK(container.subtype() == static_cast<subtype_type>(-1));
}
SECTION("comparisons")
{
std::vector<std::uint8_t> const bytes = {{0xCA, 0xFE, 0xBA, 0xBE}};
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container1;
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container2({}, 42);
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container3(bytes);
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container4(bytes, 42);
CHECK(container1 == container1);
CHECK(container1 != container2);
CHECK(container1 != container3);
CHECK(container1 != container4);
CHECK(container2 != container1);
CHECK(container2 == container2);
CHECK(container2 != container3);
CHECK(container2 != container4);
CHECK(container3 != container1);
CHECK(container3 != container2);
CHECK(container3 == container3);
CHECK(container3 != container4);
CHECK(container4 != container1);
CHECK(container4 != container2);
CHECK(container4 != container3);
CHECK(container4 == container4);
container3.clear();
container4.clear();
CHECK(container1 == container3);
CHECK(container2 == container4);
}
}

View File

@ -0,0 +1,543 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("capacity")
{
SECTION("empty()")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("array")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of empty")
{
CHECK(j.empty() == true);
CHECK(j_const.empty() == true);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("filled array")
{
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
}
SECTION("object")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of empty")
{
CHECK(j.empty() == true);
CHECK(j_const.empty() == true);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("filled object")
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
}
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of empty")
{
CHECK(j.empty() == false);
CHECK(j_const.empty() == false);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of empty")
{
CHECK(j.empty() == true);
CHECK(j_const.empty() == true);
}
SECTION("definition of empty")
{
CHECK(j.empty() == (j.begin() == j.end()));
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
}
}
}
SECTION("size()")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of size")
{
CHECK(j.size() == 1);
CHECK(j_const.size() == 1);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of size")
{
CHECK(j.size() == 1);
CHECK(j_const.size() == 1);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("array")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of size")
{
CHECK(j.size() == 0);
CHECK(j_const.size() == 0);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("filled array")
{
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of size")
{
CHECK(j.size() == 3);
CHECK(j_const.size() == 3);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
}
SECTION("object")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of size")
{
CHECK(j.size() == 0);
CHECK(j_const.size() == 0);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("filled object")
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of size")
{
CHECK(j.size() == 3);
CHECK(j_const.size() == 3);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
}
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of size")
{
CHECK(j.size() == 1);
CHECK(j_const.size() == 1);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of size")
{
CHECK(j.size() == 1);
CHECK(j_const.size() == 1);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of size")
{
CHECK(j.size() == 1);
CHECK(j_const.size() == 1);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of size")
{
CHECK(j.size() == 0);
CHECK(j_const.size() == 0);
}
SECTION("definition of size")
{
CHECK(std::distance(j.begin(), j.end()) == j.size());
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
}
}
}
SECTION("max_size()")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of max_size")
{
CHECK(j.max_size() == 1);
CHECK(j_const.max_size() == 1);
}
}
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of max_size")
{
CHECK(j.max_size() == 1);
CHECK(j_const.max_size() == 1);
}
}
SECTION("array")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of max_size")
{
CHECK(j.max_size() >= j.size());
CHECK(j_const.max_size() >= j_const.size());
}
}
SECTION("filled array")
{
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of max_size")
{
CHECK(j.max_size() >= j.size());
CHECK(j_const.max_size() >= j_const.size());
}
}
}
SECTION("object")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of max_size")
{
CHECK(j.max_size() >= j.size());
CHECK(j_const.max_size() >= j_const.size());
}
}
SECTION("filled object")
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of max_size")
{
CHECK(j.max_size() >= j.size());
CHECK(j_const.max_size() >= j_const.size());
}
}
}
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of max_size")
{
CHECK(j.max_size() == 1);
CHECK(j_const.max_size() == 1);
}
}
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of max_size")
{
CHECK(j.max_size() == 1);
CHECK(j_const.max_size() == 1);
}
}
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of max_size")
{
CHECK(j.max_size() == 1);
CHECK(j_const.max_size() == 1);
}
}
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of max_size")
{
CHECK(j.max_size() == 0);
CHECK(j_const.max_size() == 0);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,393 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("const_iterator class")
{
SECTION("construction")
{
SECTION("constructor")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator const it(&j);
}
SECTION("object")
{
json const j(json::value_t::object);
json::const_iterator const it(&j);
}
SECTION("array")
{
json const j(json::value_t::array);
json::const_iterator const it(&j);
}
}
SECTION("copy assignment")
{
json const j(json::value_t::null);
json::const_iterator const it(&j);
json::const_iterator it2(&j);
it2 = it;
}
SECTION("copy constructor from non-const iterator")
{
SECTION("create from uninitialized iterator")
{
const json::iterator it {};
json::const_iterator const cit(it);
}
SECTION("create from initialized iterator")
{
json j;
const json::iterator it = j.begin();
json::const_iterator const cit(it);
}
}
}
SECTION("initialization")
{
SECTION("set_begin")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator it(&j);
it.set_begin();
CHECK((it == j.cbegin()));
}
SECTION("object")
{
json const j(json::value_t::object);
json::const_iterator it(&j);
it.set_begin();
CHECK((it == j.cbegin()));
}
SECTION("array")
{
json const j(json::value_t::array);
json::const_iterator it(&j);
it.set_begin();
CHECK((it == j.cbegin()));
}
}
SECTION("set_end")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator it(&j);
it.set_end();
CHECK((it == j.cend()));
}
SECTION("object")
{
json const j(json::value_t::object);
json::const_iterator it(&j);
it.set_end();
CHECK((it == j.cend()));
}
SECTION("array")
{
json const j(json::value_t::array);
json::const_iterator it(&j);
it.set_end();
CHECK((it == j.cend()));
}
}
}
SECTION("element access")
{
SECTION("operator*")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator const it = j.cbegin();
CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cbegin();
CHECK(*it == json(17));
it = j.cend();
CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator const it = j.cbegin();
CHECK(*it == json("bar"));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator const it = j.cbegin();
CHECK(*it == json(1));
}
}
SECTION("operator->")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator const it = j.cbegin();
CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cbegin();
CHECK(std::string(it->type_name()) == "number");
it = j.cend();
CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator const it = j.cbegin();
CHECK(std::string(it->type_name()) == "string");
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator const it = j.cbegin();
CHECK(std::string(it->type_name()) == "number");
}
}
}
SECTION("increment/decrement")
{
SECTION("post-increment")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator it = j.cbegin();
CHECK((it.m_it.primitive_iterator.m_it == 1));
it++;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cbegin();
CHECK((it.m_it.primitive_iterator.m_it == 0));
it++;
CHECK((it.m_it.primitive_iterator.m_it == 1));
it++;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
SECTION("pre-increment")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator it = j.cbegin();
CHECK((it.m_it.primitive_iterator.m_it == 1));
++it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cbegin();
CHECK((it.m_it.primitive_iterator.m_it == 0));
++it;
CHECK((it.m_it.primitive_iterator.m_it == 1));
++it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
SECTION("post-decrement")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator const it = j.cend();
CHECK((it.m_it.primitive_iterator.m_it == 1));
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cend();
CHECK((it.m_it.primitive_iterator.m_it == 1));
it--;
CHECK((it.m_it.primitive_iterator.m_it == 0));
it--;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
SECTION("pre-decrement")
{
SECTION("null")
{
json const j(json::value_t::null);
json::const_iterator const it = j.cend();
CHECK((it.m_it.primitive_iterator.m_it == 1));
}
SECTION("number")
{
json const j(17);
json::const_iterator it = j.cend();
CHECK((it.m_it.primitive_iterator.m_it == 1));
--it;
CHECK((it.m_it.primitive_iterator.m_it == 0));
--it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
}
}

View File

@ -0,0 +1,468 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
template<typename Iter>
using can_post_increment_temporary = decltype((std::declval<Iter>()++)++);
template<typename Iter>
using can_post_decrement_temporary = decltype((std::declval<Iter>()--)--);
TEST_CASE("iterator class")
{
SECTION("construction")
{
SECTION("constructor")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator const it(&j);
}
SECTION("object")
{
json j(json::value_t::object);
json::iterator const it(&j);
}
SECTION("array")
{
json j(json::value_t::array);
json::iterator const it(&j);
}
}
SECTION("copy assignment")
{
json j(json::value_t::null);
json::iterator const it(&j);
json::iterator it2(&j);
it2 = it;
}
}
SECTION("initialization")
{
SECTION("set_begin")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator it(&j);
it.set_begin();
CHECK((it == j.begin()));
}
SECTION("object")
{
json j(json::value_t::object);
json::iterator it(&j);
it.set_begin();
CHECK((it == j.begin()));
}
SECTION("array")
{
json j(json::value_t::array);
json::iterator it(&j);
it.set_begin();
CHECK((it == j.begin()));
}
}
SECTION("set_end")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator it(&j);
it.set_end();
CHECK((it == j.end()));
}
SECTION("object")
{
json j(json::value_t::object);
json::iterator it(&j);
it.set_end();
CHECK((it == j.end()));
}
SECTION("array")
{
json j(json::value_t::array);
json::iterator it(&j);
it.set_end();
CHECK((it == j.end()));
}
}
}
SECTION("element access")
{
SECTION("operator*")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator const it = j.begin();
CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("number")
{
json j(17);
json::iterator it = j.begin();
CHECK(*it == json(17));
it = j.end();
CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator const it = j.begin();
CHECK(*it == json("bar"));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator const it = j.begin();
CHECK(*it == json(1));
}
}
SECTION("operator->")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator const it = j.begin();
CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("number")
{
json j(17);
json::iterator it = j.begin();
CHECK(std::string(it->type_name()) == "number");
it = j.end();
CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator const it = j.begin();
CHECK(std::string(it->type_name()) == "string");
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator const it = j.begin();
CHECK(std::string(it->type_name()) == "number");
}
}
}
SECTION("increment/decrement")
{
SECTION("post-increment")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator it = j.begin();
CHECK((it.m_it.primitive_iterator.m_it == 1));
it++;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("number")
{
json j(17);
json::iterator it = j.begin();
CHECK((it.m_it.primitive_iterator.m_it == 0));
it++;
CHECK((it.m_it.primitive_iterator.m_it == 1));
it++;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
SECTION("pre-increment")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator it = j.begin();
CHECK((it.m_it.primitive_iterator.m_it == 1));
++it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("number")
{
json j(17);
json::iterator it = j.begin();
CHECK((it.m_it.primitive_iterator.m_it == 0));
++it;
CHECK((it.m_it.primitive_iterator.m_it == 1));
++it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
SECTION("post-decrement")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator const it = j.end();
CHECK((it.m_it.primitive_iterator.m_it == 1));
}
SECTION("number")
{
json j(17);
json::iterator it = j.end();
CHECK((it.m_it.primitive_iterator.m_it == 1));
it--;
CHECK((it.m_it.primitive_iterator.m_it == 0));
it--;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
SECTION("pre-decrement")
{
SECTION("null")
{
json j(json::value_t::null);
json::iterator const it = j.end();
CHECK((it.m_it.primitive_iterator.m_it == 1));
}
SECTION("number")
{
json j(17);
json::iterator it = j.end();
CHECK((it.m_it.primitive_iterator.m_it == 1));
--it;
CHECK((it.m_it.primitive_iterator.m_it == 0));
--it;
CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
}
SECTION("object")
{
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
}
SECTION("equality-preserving")
{
SECTION("post-increment")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
}
SECTION("post-decrement")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
}
}
// prevent "accidental mutation of a temporary object"
SECTION("cert-dcl21-cpp")
{
using nlohmann::detail::is_detected;
SECTION("post-increment")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
}
SECTION("post-decrement")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
}
}
}

View File

@ -0,0 +1,226 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace
{
// shortcut to scan a string literal
json::lexer::token_type scan_string(const char* s, bool ignore_comments = false);
json::lexer::token_type scan_string(const char* s, const bool ignore_comments)
{
auto ia = nlohmann::detail::input_adapter(s);
return nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments).scan(); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
}
} // namespace
std::string get_error_message(const char* s, bool ignore_comments = false);
std::string get_error_message(const char* s, const bool ignore_comments)
{
auto ia = nlohmann::detail::input_adapter(s);
auto lexer = nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
lexer.scan();
return lexer.get_error_message();
}
TEST_CASE("lexer class")
{
SECTION("scan")
{
SECTION("structural characters")
{
CHECK((scan_string("[") == json::lexer::token_type::begin_array));
CHECK((scan_string("]") == json::lexer::token_type::end_array));
CHECK((scan_string("{") == json::lexer::token_type::begin_object));
CHECK((scan_string("}") == json::lexer::token_type::end_object));
CHECK((scan_string(",") == json::lexer::token_type::value_separator));
CHECK((scan_string(":") == json::lexer::token_type::name_separator));
}
SECTION("literal names")
{
CHECK((scan_string("null") == json::lexer::token_type::literal_null));
CHECK((scan_string("true") == json::lexer::token_type::literal_true));
CHECK((scan_string("false") == json::lexer::token_type::literal_false));
}
SECTION("numbers")
{
CHECK((scan_string("0") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("1") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("2") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("3") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("4") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("5") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("6") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("7") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("8") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("9") == json::lexer::token_type::value_unsigned));
CHECK((scan_string("-0") == json::lexer::token_type::value_integer));
CHECK((scan_string("-1") == json::lexer::token_type::value_integer));
CHECK((scan_string("1.1") == json::lexer::token_type::value_float));
CHECK((scan_string("-1.1") == json::lexer::token_type::value_float));
CHECK((scan_string("1E10") == json::lexer::token_type::value_float));
}
SECTION("whitespace")
{
// result is end_of_input, because not token is following
CHECK((scan_string(" ") == json::lexer::token_type::end_of_input));
CHECK((scan_string("\t") == json::lexer::token_type::end_of_input));
CHECK((scan_string("\n") == json::lexer::token_type::end_of_input));
CHECK((scan_string("\r") == json::lexer::token_type::end_of_input));
CHECK((scan_string(" \t\n\r\n\t ") == json::lexer::token_type::end_of_input));
}
}
SECTION("token_type_name")
{
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::uninitialized)) == "<uninitialized>"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::literal_true)) == "true literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::literal_false)) == "false literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::literal_null)) == "null literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::value_string)) == "string literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::value_unsigned)) == "number literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::value_integer)) == "number literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::value_float)) == "number literal"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::begin_array)) == "'['"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::begin_object)) == "'{'"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::end_array)) == "']'"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::end_object)) == "'}'"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::name_separator)) == "':'"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::value_separator)) == "','"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::parse_error)) == "<parse error>"));
CHECK((std::string(json::lexer::token_type_name(json::lexer::token_type::end_of_input)) == "end of input"));
}
SECTION("parse errors on first character")
{
for (int c = 1; c < 128; ++c)
{
// create string from the ASCII code
const auto s = std::string(1, static_cast<char>(c));
// store scan() result
const auto res = scan_string(s.c_str());
CAPTURE(s)
switch (c)
{
// single characters that are valid tokens
case ('['):
case (']'):
case ('{'):
case ('}'):
case (','):
case (':'):
case ('0'):
case ('1'):
case ('2'):
case ('3'):
case ('4'):
case ('5'):
case ('6'):
case ('7'):
case ('8'):
case ('9'):
{
CHECK((res != json::lexer::token_type::parse_error));
break;
}
// whitespace
case (' '):
case ('\t'):
case ('\n'):
case ('\r'):
{
CHECK((res == json::lexer::token_type::end_of_input));
break;
}
// anything else is not expected
default:
{
CHECK((res == json::lexer::token_type::parse_error));
break;
}
}
}
}
SECTION("very large string")
{
// strings larger than 1024 bytes yield a resize of the lexer's yytext buffer
std::string s("\"");
s += std::string(2048, 'x');
s += "\"";
CHECK((scan_string(s.c_str()) == json::lexer::token_type::value_string));
}
SECTION("fail on comments")
{
CHECK((scan_string("/", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/", false) == "invalid literal");
CHECK((scan_string("/!", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/!", false) == "invalid literal");
CHECK((scan_string("/*", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/*", false) == "invalid literal");
CHECK((scan_string("/**", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/**", false) == "invalid literal");
CHECK((scan_string("//", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("//", false) == "invalid literal");
CHECK((scan_string("/**/", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/**/", false) == "invalid literal");
CHECK((scan_string("/** /", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/** /", false) == "invalid literal");
CHECK((scan_string("/***/", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/***/", false) == "invalid literal");
CHECK((scan_string("/* true */", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/* true */", false) == "invalid literal");
CHECK((scan_string("/*/**/", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/*/**/", false) == "invalid literal");
CHECK((scan_string("/*/* */", false) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/*/* */", false) == "invalid literal");
}
SECTION("ignore comments")
{
CHECK((scan_string("/", true) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/", true) == "invalid comment; expecting '/' or '*' after '/'");
CHECK((scan_string("/!", true) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/!", true) == "invalid comment; expecting '/' or '*' after '/'");
CHECK((scan_string("/*", true) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/*", true) == "invalid comment; missing closing '*/'");
CHECK((scan_string("/**", true) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/**", true) == "invalid comment; missing closing '*/'");
CHECK((scan_string("//", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/**/", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/** /", true) == json::lexer::token_type::parse_error));
CHECK(get_error_message("/** /", true) == "invalid comment; missing closing '*/'");
CHECK((scan_string("/***/", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/* true */", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/*/**/", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/*/* */", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("//\n//\n", true) == json::lexer::token_type::end_of_input));
CHECK((scan_string("/**//**//**/", true) == json::lexer::token_type::end_of_input));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,595 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// cmake/test.cmake selects the C++ standard versions with which to build a
// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
// When using macros that are only defined for particular versions of the standard
// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
// version macro in a comment close by, like this:
// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
#if JSON_HAS_THREE_WAY_COMPARISON
// this can be replaced with the doctest stl extension header in version 2.5
namespace doctest
{
template<> struct StringMaker<std::partial_ordering>
{
static String convert(const std::partial_ordering& order)
{
if (order == std::partial_ordering::less)
{
return "std::partial_ordering::less";
}
if (order == std::partial_ordering::equivalent)
{
return "std::partial_ordering::equivalent";
}
if (order == std::partial_ordering::greater)
{
return "std::partial_ordering::greater";
}
if (order == std::partial_ordering::unordered)
{
return "std::partial_ordering::unordered";
}
return "{?}";
}
};
} // namespace doctest
#endif
namespace
{
// helper function to check std::less<json::value_t>
// see https://en.cppreference.com/w/cpp/utility/functional/less
template <typename A, typename B, typename U = std::less<json::value_t>>
bool f(A a, B b, U u = U())
{
return u(a, b);
}
} // namespace
TEST_CASE("lexicographical comparison operators")
{
constexpr auto f_ = false;
constexpr auto _t = true;
constexpr auto nan = std::numeric_limits<json::number_float_t>::quiet_NaN();
#if JSON_HAS_THREE_WAY_COMPARISON
constexpr auto lt = std::partial_ordering::less;
constexpr auto gt = std::partial_ordering::greater;
constexpr auto eq = std::partial_ordering::equivalent;
constexpr auto un = std::partial_ordering::unordered;
#endif
#if JSON_HAS_THREE_WAY_COMPARISON
INFO("using 3-way comparison");
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
INFO("using legacy comparison");
#endif
//REQUIRE(std::numeric_limits<json::number_float_t>::has_quiet_NaN);
REQUIRE(std::isnan(nan));
SECTION("types")
{
std::vector<json::value_t> j_types =
{
json::value_t::null,
json::value_t::boolean,
json::value_t::number_integer,
json::value_t::number_unsigned,
json::value_t::number_float,
json::value_t::object,
json::value_t::array,
json::value_t::string,
json::value_t::binary,
json::value_t::discarded
};
std::vector<std::vector<bool>> expected_lt =
{
//0 1 2 3 4 5 6 7 8 9
{f_, _t, _t, _t, _t, _t, _t, _t, _t, f_}, // 0
{f_, f_, _t, _t, _t, _t, _t, _t, _t, f_}, // 1
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 2
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 3
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 4
{f_, f_, f_, f_, f_, f_, _t, _t, _t, f_}, // 5
{f_, f_, f_, f_, f_, f_, f_, _t, _t, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
};
SECTION("comparison: less")
{
REQUIRE(expected_lt.size() == j_types.size());
for (size_t i = 0; i < j_types.size(); ++i)
{
REQUIRE(expected_lt[i].size() == j_types.size());
for (size_t j = 0; j < j_types.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
// check precomputed values
#if JSON_HAS_THREE_WAY_COMPARISON
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
CHECK((j_types[i] < j_types[j]) == expected_lt[i][j]);
#else
CHECK(operator<(j_types[i], j_types[j]) == expected_lt[i][j]);
#endif
CHECK(f(j_types[i], j_types[j]) == expected_lt[i][j]);
}
}
}
#if JSON_HAS_THREE_WAY_COMPARISON
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
SECTION("comparison: 3-way")
{
std::vector<std::vector<std::partial_ordering>> expected =
{
//0 1 2 3 4 5 6 7 8 9
{eq, lt, lt, lt, lt, lt, lt, lt, lt, un}, // 0
{gt, eq, lt, lt, lt, lt, lt, lt, lt, un}, // 1
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 2
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 3
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 4
{gt, gt, gt, gt, gt, eq, lt, lt, lt, un}, // 5
{gt, gt, gt, gt, gt, gt, eq, lt, lt, un}, // 6
{gt, gt, gt, gt, gt, gt, gt, eq, lt, un}, // 7
{gt, gt, gt, gt, gt, gt, gt, gt, eq, un}, // 8
{un, un, un, un, un, un, un, un, un, un}, // 9
};
// check expected partial_ordering against expected boolean
REQUIRE(expected.size() == expected_lt.size());
for (size_t i = 0; i < expected.size(); ++i)
{
REQUIRE(expected[i].size() == expected_lt[i].size());
for (size_t j = 0; j < expected[i].size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
}
}
// check 3-way comparison against expected partial_ordering
REQUIRE(expected.size() == j_types.size());
for (size_t i = 0; i < j_types.size(); ++i)
{
REQUIRE(expected[i].size() == j_types.size());
for (size_t j = 0; j < j_types.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
}
}
}
#endif
}
SECTION("values")
{
json j_values =
{
nullptr, nullptr, // 0 1
-17, 42, // 2 3
8u, 13u, // 4 5
3.14159, 23.42, // 6 7
nan, nan, // 8 9
"foo", "bar", // 10 11
true, false, // 12 13
{1, 2, 3}, {"one", "two", "three"}, // 14 15
{{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}, // 16 17
json::binary({1, 2, 3}), json::binary({1, 2, 4}), // 18 19
json(json::value_t::discarded), json(json::value_t::discarded) // 20 21
};
std::vector<std::vector<bool>> expected_eq =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
{f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
{f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
{f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
{f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
std::vector<std::vector<bool>> expected_lt =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 0
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 1
{f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 3
{f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 4
{f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 5
{f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 6
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 11
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 12
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
SECTION("compares unordered")
{
std::vector<std::vector<bool>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 0
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 1
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 3
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 4
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 5
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 7
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 8
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 19
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 20
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 21
};
// check if two values compare unordered as expected
REQUIRE(expected.size() == j_values.size());
for (size_t i = 0; i < j_values.size(); ++i)
{
REQUIRE(expected[i].size() == j_values.size());
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK(json::compares_unordered(j_values[i], j_values[j]) == expected[i][j]);
}
}
}
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
SECTION("compares unordered (inverse)")
{
std::vector<std::vector<bool>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
// check that two values compare unordered as expected (with legacy-mode enabled)
REQUIRE(expected.size() == j_values.size());
for (size_t i = 0; i < j_values.size(); ++i)
{
REQUIRE(expected[i].size() == j_values.size());
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CAPTURE(j_values[i])
CAPTURE(j_values[j])
CHECK(json::compares_unordered(j_values[i], j_values[j], true) == expected[i][j]);
}
}
}
#endif
SECTION("comparison: equal")
{
// check that two values compare equal
REQUIRE(expected_eq.size() == j_values.size());
for (size_t i = 0; i < j_values.size(); ++i)
{
REQUIRE(expected_eq[i].size() == j_values.size());
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_values[i] == j_values[j]) == expected_eq[i][j]);
}
}
// compare with null pointer
json j_null;
CHECK(j_null == nullptr);
CHECK(nullptr == j_null);
}
SECTION("comparison: not equal")
{
// check that two values compare unequal as expected
for (size_t i = 0; i < j_values.size(); ++i)
{
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
if (json::compares_unordered(j_values[i], j_values[j], true))
{
// if two values compare unordered,
// check that the boolean comparison result is always false
CHECK_FALSE(j_values[i] != j_values[j]);
}
else
{
// otherwise, check that they compare according to their definition
// as the inverse of equal
CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
}
}
}
// compare with null pointer
const json j_null;
CHECK((j_null != nullptr) == false);
CHECK((nullptr != j_null) == false);
CHECK((j_null != nullptr) == !(j_null == nullptr));
CHECK((nullptr != j_null) == !(nullptr == j_null));
}
SECTION("comparison: less")
{
// check that two values compare less than as expected
REQUIRE(expected_lt.size() == j_values.size());
for (size_t i = 0; i < j_values.size(); ++i)
{
REQUIRE(expected_lt[i].size() == j_values.size());
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_values[i] < j_values[j]) == expected_lt[i][j]);
}
}
}
SECTION("comparison: less than or equal equal")
{
// check that two values compare less than or equal as expected
for (size_t i = 0; i < j_values.size(); ++i)
{
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
if (json::compares_unordered(j_values[i], j_values[j], true))
{
// if two values compare unordered,
// check that the boolean comparison result is always false
CHECK_FALSE(j_values[i] <= j_values[j]);
}
else
{
// otherwise, check that they compare according to their definition
// as the inverse of less than with the operand order reversed
CHECK((j_values[i] <= j_values[j]) == !(j_values[j] < j_values[i]));
}
}
}
}
SECTION("comparison: greater than")
{
// check that two values compare greater than as expected
for (size_t i = 0; i < j_values.size(); ++i)
{
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
if (json::compares_unordered(j_values[i], j_values[j]))
{
// if two values compare unordered,
// check that the boolean comparison result is always false
CHECK_FALSE(j_values[i] > j_values[j]);
}
else
{
// otherwise, check that they compare according to their definition
// as the inverse of less than or equal which is defined as
// the inverse of less than with the operand order reversed
CHECK((j_values[i] > j_values[j]) == !(j_values[i] <= j_values[j]));
CHECK((j_values[i] > j_values[j]) == !!(j_values[j] < j_values[i]));
}
}
}
}
SECTION("comparison: greater than or equal")
{
// check that two values compare greater than or equal as expected
for (size_t i = 0; i < j_values.size(); ++i)
{
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
if (json::compares_unordered(j_values[i], j_values[j], true))
{
// if two values compare unordered,
// check that the boolean result is always false
CHECK_FALSE(j_values[i] >= j_values[j]);
}
else
{
// otherwise, check that they compare according to their definition
// as the inverse of less than
CHECK((j_values[i] >= j_values[j]) == !(j_values[i] < j_values[j]));
}
}
}
}
#if JSON_HAS_THREE_WAY_COMPARISON
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
SECTION("comparison: 3-way")
{
std::vector<std::vector<std::partial_ordering>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 0
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 1
{gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 2
{gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 3
{gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 4
{gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 5
{gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 6
{gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 7
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 8
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 9
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 10
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 11
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un}, // 12
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un}, // 13
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un}, // 14
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un}, // 15
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un}, // 16
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un}, // 17
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un}, // 18
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un}, // 19
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 20
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 21
};
// check expected partial_ordering against expected booleans
REQUIRE(expected.size() == expected_eq.size());
REQUIRE(expected.size() == expected_lt.size());
for (size_t i = 0; i < expected.size(); ++i)
{
REQUIRE(expected[i].size() == expected_eq[i].size());
REQUIRE(expected[i].size() == expected_lt[i].size());
for (size_t j = 0; j < expected[i].size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK(std::is_eq(expected[i][j]) == expected_eq[i][j]);
CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
if (std::is_gt(expected[i][j]))
{
CHECK((!expected_eq[i][j] && !expected_lt[i][j]));
}
}
}
// check that two values compare according to their expected ordering
REQUIRE(expected.size() == j_values.size());
for (size_t i = 0; i < j_values.size(); ++i)
{
REQUIRE(expected[i].size() == j_values.size());
for (size_t j = 0; j < j_values.size(); ++j)
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
}
}
}
#endif
}
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
SECTION("parser callback regression")
{
SECTION("filter specific element")
{
const auto* s_object = R"(
{
"foo": 2,
"bar": {
"baz": 1
}
}
)";
const auto* s_array = R"(
[1,2,[3,4,5],4,5]
)";
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{
// filter all number(2) elements
return j != json(2);
});
CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{
return j != json(2);
});
CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
}
}
#endif
}

View File

@ -0,0 +1,150 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("concepts")
{
SECTION("container requirements for json")
{
// X: container class: json
// T: type of objects: json
// a, b: values of type X: json
// TABLE 96 - Container Requirements
// X::value_type must return T
CHECK((std::is_same<json::value_type, json>::value));
// X::reference must return lvalue of T
CHECK((std::is_same<json::reference, json&>::value));
// X::const_reference must return const lvalue of T
CHECK((std::is_same<json::const_reference, const json&>::value));
// X::iterator must return iterator whose value_type is T
CHECK((std::is_same<json::iterator::value_type, json>::value));
// X::iterator must meet the forward iterator requirements
CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
// X::iterator must be convertible to X::const_iterator
CHECK((std::is_convertible<json::iterator, json::const_iterator>::value));
// X::const_iterator must return iterator whose value_type is T
CHECK((std::is_same<json::const_iterator::value_type, json>::value));
// X::const_iterator must meet the forward iterator requirements
CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
// X::difference_type must return a signed integer
CHECK((std::is_signed<json::difference_type>::value));
// X::difference_type must be identical to X::iterator::difference_type
CHECK((std::is_same<json::difference_type, json::iterator::difference_type>::value));
// X::difference_type must be identical to X::const_iterator::difference_type
CHECK((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
// X::size_type must return an unsigned integer
CHECK((std::is_unsigned<json::size_type>::value));
// X::size_type can represent any non-negative value of X::difference_type
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
(std::numeric_limits<json::size_type>::max)());
// the expression "X u" has the post-condition "u.empty()"
{
const json u;
CHECK(u.empty());
}
// the expression "X()" has the post-condition "X().empty()"
CHECK(json().empty());
}
SECTION("class json")
{
SECTION("DefaultConstructible")
{
CHECK(std::is_nothrow_default_constructible<json>::value);
}
SECTION("MoveConstructible")
{
CHECK(std::is_move_constructible<json>::value);
CHECK(std::is_nothrow_move_constructible<json>::value);
}
SECTION("CopyConstructible")
{
CHECK(std::is_copy_constructible<json>::value);
}
SECTION("MoveAssignable")
{
CHECK(std::is_nothrow_move_assignable<json>::value);
}
SECTION("CopyAssignable")
{
CHECK(std::is_copy_assignable<json>::value);
}
SECTION("Destructible")
{
CHECK(std::is_nothrow_destructible<json>::value);
}
SECTION("StandardLayoutType")
{
CHECK(std::is_standard_layout<json>::value);
}
}
SECTION("class iterator")
{
SECTION("CopyConstructible")
{
CHECK(std::is_nothrow_copy_constructible<json::iterator>::value);
CHECK(std::is_nothrow_copy_constructible<json::const_iterator>::value);
}
SECTION("CopyAssignable")
{
// STL iterators used by json::iterator don't pass this test in Debug mode
#if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
CHECK(std::is_nothrow_copy_assignable<json::iterator>::value);
CHECK(std::is_nothrow_copy_assignable<json::const_iterator>::value);
#endif
}
SECTION("Destructible")
{
CHECK(std::is_nothrow_destructible<json::iterator>::value);
CHECK(std::is_nothrow_destructible<json::const_iterator>::value);
}
SECTION("Swappable")
{
{
json j {1, 2, 3};
json::iterator it1 = j.begin();
json::iterator it2 = j.end();
swap(it1, it2);
CHECK(it1 == j.end());
CHECK(it2 == j.begin());
}
{
json j {1, 2, 3};
json::const_iterator it1 = j.cbegin();
json::const_iterator it2 = j.cend();
swap(it1, it2);
CHECK(it1 == j.end());
CHECK(it2 == j.begin());
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("other constructors and destructor")
{
SECTION("copy constructor")
{
SECTION("object")
{
json j {{"foo", 1}, {"bar", false}};
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("array")
{
json j {"foo", 1, 42.23, false};
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("null")
{
json j(nullptr);
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("boolean")
{
json j(true);
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("string")
{
json j("Hello world");
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("number (integer)")
{
json j(42);
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("number (unsigned)")
{
json j(42u);
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("number (floating-point)")
{
json j(42.23);
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
SECTION("binary")
{
json j = json::binary({1, 2, 3});
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(j == k);
}
}
SECTION("move constructor")
{
json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
CHECK(j.type() == json::value_t::object);
const json k(std::move(j));
CHECK(k.type() == json::value_t::object);
CHECK(j.type() == json::value_t::null); // NOLINT: access after move is OK here
}
SECTION("copy assignment")
{
SECTION("object")
{
json j {{"foo", 1}, {"bar", false}};
json k;
k = j;
CHECK(j == k);
}
SECTION("array")
{
json j {"foo", 1, 42.23, false};
json k;
k = j;
CHECK(j == k);
}
SECTION("null")
{
json j(nullptr);
json k;
k = j;
CHECK(j == k);
}
SECTION("boolean")
{
json j(true);
json k;
k = j;
CHECK(j == k);
}
SECTION("string")
{
json j("Hello world");
json k;
k = j;
CHECK(j == k);
}
SECTION("number (integer)")
{
json j(42);
json k;
k = j;
CHECK(j == k);
}
SECTION("number (unsigned)")
{
json j(42u);
json k;
k = j;
CHECK(j == k);
}
SECTION("number (floating-point)")
{
json j(42.23);
json k;
k = j;
CHECK(j == k);
}
SECTION("binary")
{
json j = json::binary({1, 2, 3});
json k;
k = j;
CHECK(j == k);
}
}
SECTION("destructor")
{
SECTION("object")
{
auto* j = new json {{"foo", 1}, {"bar", false}}; // NOLINT(cppcoreguidelines-owning-memory)
delete j; // NOLINT(cppcoreguidelines-owning-memory)
}
SECTION("array")
{
auto* j = new json {"foo", 1, 1u, false, 23.42}; // NOLINT(cppcoreguidelines-owning-memory)
delete j; // NOLINT(cppcoreguidelines-owning-memory)
}
SECTION("string")
{
auto* j = new json("Hello world"); // NOLINT(cppcoreguidelines-owning-memory)
delete j; // NOLINT(cppcoreguidelines-owning-memory)
}
}
}

View File

@ -0,0 +1,205 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <sstream>
namespace
{
struct alt_string_iter
{
alt_string_iter() = default;
alt_string_iter(const char* cstr)
: impl(cstr)
{}
void reserve(std::size_t s)
{
impl.reserve(s);
}
template<typename Iter>
void append(Iter first, Iter last)
{
impl.append(first, last);
}
std::string::const_iterator begin() const noexcept
{
return impl.begin();
}
std::string::const_iterator end() const noexcept
{
return impl.end();
}
std::size_t size() const noexcept
{
return impl.size();
}
alt_string_iter& operator+=(const char c)
{
impl += c;
return *this;
}
std::string impl{};
};
struct alt_string_data
{
alt_string_data() = default;
alt_string_data(const char* cstr)
: impl(cstr)
{}
void reserve(std::size_t s)
{
impl.reserve(s);
}
void append(const char* p, std::size_t s)
{
impl.append(p, s);
}
const char* data() const
{
return impl.data();
}
std::size_t size() const
{
return impl.size();
}
alt_string_data& operator+=(const char c)
{
impl += c;
return *this;
}
std::string impl{};
};
void check_escaped(const char* original, const char* escaped = "", bool ensure_ascii = false);
void check_escaped(const char* original, const char* escaped, const bool ensure_ascii)
{
std::stringstream ss;
json::serializer s(nlohmann::detail::output_adapter<char>(ss), ' ');
s.dump_escaped(original, ensure_ascii);
CHECK(ss.str() == escaped);
}
} // namespace
TEST_CASE("convenience functions")
{
SECTION("type name as string")
{
CHECK(std::string(json(json::value_t::null).type_name()) == "null");
CHECK(std::string(json(json::value_t::object).type_name()) == "object");
CHECK(std::string(json(json::value_t::array).type_name()) == "array");
CHECK(std::string(json(json::value_t::number_integer).type_name()) == "number");
CHECK(std::string(json(json::value_t::number_unsigned).type_name()) == "number");
CHECK(std::string(json(json::value_t::number_float).type_name()) == "number");
CHECK(std::string(json(json::value_t::binary).type_name()) == "binary");
CHECK(std::string(json(json::value_t::boolean).type_name()) == "boolean");
CHECK(std::string(json(json::value_t::string).type_name()) == "string");
CHECK(std::string(json(json::value_t::discarded).type_name()) == "discarded");
}
SECTION("string escape")
{
check_escaped("\"", "\\\"");
check_escaped("\\", "\\\\");
check_escaped("\b", "\\b");
check_escaped("\f", "\\f");
check_escaped("\n", "\\n");
check_escaped("\r", "\\r");
check_escaped("\t", "\\t");
check_escaped("\x01", "\\u0001");
check_escaped("\x02", "\\u0002");
check_escaped("\x03", "\\u0003");
check_escaped("\x04", "\\u0004");
check_escaped("\x05", "\\u0005");
check_escaped("\x06", "\\u0006");
check_escaped("\x07", "\\u0007");
check_escaped("\x08", "\\b");
check_escaped("\x09", "\\t");
check_escaped("\x0a", "\\n");
check_escaped("\x0b", "\\u000b");
check_escaped("\x0c", "\\f");
check_escaped("\x0d", "\\r");
check_escaped("\x0e", "\\u000e");
check_escaped("\x0f", "\\u000f");
check_escaped("\x10", "\\u0010");
check_escaped("\x11", "\\u0011");
check_escaped("\x12", "\\u0012");
check_escaped("\x13", "\\u0013");
check_escaped("\x14", "\\u0014");
check_escaped("\x15", "\\u0015");
check_escaped("\x16", "\\u0016");
check_escaped("\x17", "\\u0017");
check_escaped("\x18", "\\u0018");
check_escaped("\x19", "\\u0019");
check_escaped("\x1a", "\\u001a");
check_escaped("\x1b", "\\u001b");
check_escaped("\x1c", "\\u001c");
check_escaped("\x1d", "\\u001d");
check_escaped("\x1e", "\\u001e");
check_escaped("\x1f", "\\u001f");
// invalid UTF-8 characters
CHECK_THROWS_WITH_AS(check_escaped("ä\xA9ü"), "[json.exception.type_error.316] invalid UTF-8 byte at index 2: 0xA9", json::type_error&);
CHECK_THROWS_WITH_AS(check_escaped("\xC2"), "[json.exception.type_error.316] incomplete UTF-8 string; last byte: 0xC2", json::type_error&);
}
SECTION("string concat")
{
using nlohmann::detail::concat;
const char* expected = "Hello, world!";
alt_string_iter const hello_iter{"Hello, "};
alt_string_data const hello_data{"Hello, "};
std::string const world = "world";
SECTION("std::string")
{
std::string str1 = concat(hello_iter, world, '!');
std::string str2 = concat(hello_data, world, '!');
std::string str3 = concat("Hello, ", world, '!');
CHECK(str1 == expected);
CHECK(str2 == expected);
CHECK(str3 == expected);
}
SECTION("alt_string_iter")
{
alt_string_iter str = concat<alt_string_iter>(hello_iter, world, '!');
CHECK(str.impl == expected);
}
SECTION("alt_string_data")
{
alt_string_data str = concat<alt_string_data>(hello_data, world, '!');
CHECK(str.impl == expected);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,356 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.10.2
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2019 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.
*/
#include <set>
#include <sstream>
#include <string>
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
// Test extending nlohmann::json by using a custom base class.
// Add some metadata to each node and test the behaviour of copy / move
template<class MetaDataType>
class json_metadata
{
public:
using metadata_t = MetaDataType;
metadata_t& metadata()
{
return m_metadata;
}
const metadata_t& metadata() const
{
return m_metadata;
}
private:
metadata_t m_metadata = {};
};
template<class T>
using json_with_metadata =
nlohmann::basic_json <
std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
std::allocator,
nlohmann::adl_serializer,
std::vector<std::uint8_t>,
json_metadata<T>
>;
TEST_CASE("JSON Node Metadata")
{
SECTION("type int")
{
using json = json_with_metadata<int>;
json null;
auto obj = json::object();
auto array = json::array();
null.metadata() = 1;
obj.metadata() = 2;
array.metadata() = 3;
auto copy = array;
CHECK(null.metadata() == 1);
CHECK(obj.metadata() == 2);
CHECK(array.metadata() == 3);
CHECK(copy.metadata() == 3);
}
SECTION("type vector<int>")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
auto copy = value;
value.metadata().emplace_back(2);
CHECK(copy.metadata().size() == 1);
CHECK(copy.metadata().at(0) == 1);
CHECK(value.metadata().size() == 2);
CHECK(value.metadata().at(0) == 1);
CHECK(value.metadata().at(1) == 2);
}
SECTION("copy ctor")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
value.metadata().emplace_back(2);
json copy = value;
CHECK(copy.metadata().size() == 2);
CHECK(copy.metadata().at(0) == 1);
CHECK(copy.metadata().at(1) == 2);
CHECK(value.metadata().size() == 2);
CHECK(value.metadata().at(0) == 1);
CHECK(value.metadata().at(1) == 2);
value.metadata().clear();
CHECK(copy.metadata().size() == 2);
CHECK(value.metadata().size() == 0);
}
SECTION("move ctor")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
value.metadata().emplace_back(2);
const json moved = std::move(value);
CHECK(moved.metadata().size() == 2);
CHECK(moved.metadata().at(0) == 1);
CHECK(moved.metadata().at(1) == 2);
}
SECTION("move assign")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
value.metadata().emplace_back(2);
json moved;
moved = std::move(value);
CHECK(moved.metadata().size() == 2);
CHECK(moved.metadata().at(0) == 1);
CHECK(moved.metadata().at(1) == 2);
}
SECTION("copy assign")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
value.metadata().emplace_back(2);
json copy;
copy = value;
CHECK(copy.metadata().size() == 2);
CHECK(copy.metadata().at(0) == 1);
CHECK(copy.metadata().at(1) == 2);
CHECK(value.metadata().size() == 2);
CHECK(value.metadata().at(0) == 1);
CHECK(value.metadata().at(1) == 2);
value.metadata().clear();
CHECK(copy.metadata().size() == 2);
CHECK(value.metadata().size() == 0);
}
SECTION("type unique_ptr<int>")
{
using json = json_with_metadata<std::unique_ptr<int>>;
json value;
value.metadata().reset(new int(42)); // NOLINT(cppcoreguidelines-owning-memory)
auto moved = std::move(value);
CHECK(moved.metadata() != nullptr);
CHECK(*moved.metadata() == 42);
}
SECTION("type vector<int> in json array")
{
using json = json_with_metadata<std::vector<int>>;
json value;
value.metadata().emplace_back(1);
value.metadata().emplace_back(2);
json const array(10, value);
CHECK(value.metadata().size() == 2);
CHECK(value.metadata().at(0) == 1);
CHECK(value.metadata().at(1) == 2);
for (const auto& val : array)
{
CHECK(val.metadata().size() == 2);
CHECK(val.metadata().at(0) == 1);
CHECK(val.metadata().at(1) == 2);
}
}
}
// Test extending nlohmann::json by using a custom base class.
// Add a custom member function template iterating over the whole json tree.
class visitor_adaptor
{
public:
template <class Fnc>
void visit(const Fnc& fnc) const;
private:
template <class Ptr, class Fnc>
void do_visit(const Ptr& ptr, const Fnc& fnc) const;
};
using json_with_visitor_t = nlohmann::basic_json <
std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
std::allocator,
nlohmann::adl_serializer,
std::vector<std::uint8_t>,
visitor_adaptor
>;
template <class Fnc>
void visitor_adaptor::visit(const Fnc& fnc) const
{
do_visit(json_with_visitor_t::json_pointer{}, fnc);
}
template <class Ptr, class Fnc>
void visitor_adaptor::do_visit(const Ptr& ptr, const Fnc& fnc) const
{
using value_t = nlohmann::detail::value_t;
const json_with_visitor_t& json = *static_cast<const json_with_visitor_t*>(this); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
switch (json.type())
{
case value_t::object:
for (const auto& entry : json.items())
{
entry.value().do_visit(ptr / entry.key(), fnc);
}
break;
case value_t::array:
for (std::size_t i = 0; i < json.size(); ++i)
{
json.at(i).do_visit(ptr / std::to_string(i), fnc);
}
break;
case value_t::discarded:
break;
case value_t::null:
case value_t::string:
case value_t::boolean:
case value_t::number_integer:
case value_t::number_unsigned:
case value_t::number_float:
case value_t::binary:
default:
fnc(ptr, json);
}
}
TEST_CASE("JSON Visit Node")
{
json_with_visitor_t json;
json["null"];
json["int"] = -1;
json["uint"] = 1U;
json["float"] = 1.0;
json["boolean"] = true;
json["string"] = "string";
json["array"].push_back(0);
json["array"].push_back(1);
json["array"].push_back(json);
std::set<std::string> expected
{
"/null - null - null",
"/int - number_integer - -1",
"/uint - number_unsigned - 1",
"/float - number_float - 1.0",
"/boolean - boolean - true",
"/string - string - \"string\"",
"/array/0 - number_integer - 0",
"/array/1 - number_integer - 1",
"/array/2/null - null - null",
"/array/2/int - number_integer - -1",
"/array/2/uint - number_unsigned - 1",
"/array/2/float - number_float - 1.0",
"/array/2/boolean - boolean - true",
"/array/2/string - string - \"string\"",
"/array/2/array/0 - number_integer - 0",
"/array/2/array/1 - number_integer - 1"
};
json.visit(
[&](const json_with_visitor_t::json_pointer & p,
const json_with_visitor_t& j)
{
std::stringstream str;
str << p.to_string() << " - " ;
using value_t = nlohmann::detail::value_t;
switch (j.type())
{
case value_t::object:
str << "object";
break;
case value_t::array:
str << "array";
break;
case value_t::discarded:
str << "discarded";
break;
case value_t::null:
str << "null";
break;
case value_t::string:
str << "string";
break;
case value_t::boolean:
str << "boolean";
break;
case value_t::number_integer:
str << "number_integer";
break;
case value_t::number_unsigned:
str << "number_unsigned";
break;
case value_t::number_float:
str << "number_float";
break;
case value_t::binary:
str << "binary";
break;
default:
str << "error";
break;
}
str << " - " << j.dump();
CHECK(json.at(p) == j);
INFO(str.str());
CHECK(expected.count(str.str()) == 1);
expected.erase(str.str());
}
);
CHECK(expected.empty());
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,246 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#ifdef JSON_DIAGNOSTICS
#undef JSON_DIAGNOSTICS
#endif
#define JSON_DIAGNOSTICS 1
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("Better diagnostics")
{
SECTION("empty JSON Pointer")
{
json const j = 1;
std::string s;
CHECK_THROWS_WITH_AS(s = j.get<std::string>(), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
}
SECTION("invalid type")
{
json j;
j["a"]["b"]["c"] = 1;
std::string s;
CHECK_THROWS_WITH_AS(s = j["a"]["b"]["c"].get<std::string>(), "[json.exception.type_error.302] (/a/b/c) type must be string, but is number", json::type_error);
}
SECTION("missing key")
{
json j;
j["object"]["object"] = true;
CHECK_THROWS_WITH_AS(j["object"].at("not_found"), "[json.exception.out_of_range.403] (/object) key 'not_found' not found", json::out_of_range);
}
SECTION("array index out of range")
{
json j;
j["array"][4] = true;
CHECK_THROWS_WITH_AS(j["array"].at(5), "[json.exception.out_of_range.401] (/array) array index 5 is out of range", json::out_of_range);
}
SECTION("array index at wrong type")
{
json j;
j["array"][4] = true;
CHECK_THROWS_WITH_AS(j["array"][4][5], "[json.exception.type_error.305] (/array/4) cannot use operator[] with a numeric argument with boolean", json::type_error);
}
SECTION("wrong iterator")
{
json j;
j["array"] = json::array();
CHECK_THROWS_WITH_AS(j["array"].erase(j.begin()), "[json.exception.invalid_iterator.202] (/array) iterator does not fit current value", json::invalid_iterator);
}
SECTION("JSON Pointer escaping")
{
json j;
j["a/b"]["m~n"] = 1;
std::string s;
CHECK_THROWS_WITH_AS(s = j["a/b"]["m~n"].get<std::string>(), "[json.exception.type_error.302] (/a~1b/m~0n) type must be string, but is number", json::type_error);
}
SECTION("Parse error")
{
json _;
CHECK_THROWS_WITH_AS(_ = json::parse(""), "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error);
}
SECTION("Wrong type in update()")
{
json j = {{"foo", "bar"}};
json k = {{"bla", 1}};
CHECK_THROWS_WITH_AS(j.update(k["bla"].begin(), k["bla"].end()), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
CHECK_THROWS_WITH_AS(j.update(k["bla"]), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
}
}
TEST_CASE("Regression tests for extended diagnostics")
{
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
{
CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
}
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
{
json j;
j["/foo"] = {1, 2, 3};
CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
}
SECTION("Regression test for issue #2838 - Assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
{
// void push_back(basic_json&& val)
{
json j_arr = json::array();
j_arr.push_back(json::object());
j_arr.push_back(json::object());
j_arr.push_back(json::object());
j_arr.push_back(json::object());
json j_obj = json::object();
j_obj["key"] = j_arr;
}
// void push_back(const basic_json& val)
{
json j_arr = json::array();
auto object = json::object();
j_arr.push_back(object);
j_arr.push_back(object);
j_arr.push_back(object);
j_arr.push_back(object);
json j_obj = json::object();
j_obj["key"] = j_arr;
}
// reference emplace_back(Args&& ... args)
{
json j_arr = json::array();
j_arr.emplace_back(json::object());
j_arr.emplace_back(json::object());
j_arr.emplace_back(json::object());
j_arr.emplace_back(json::object());
json j_obj = json::object();
j_obj["key"] = j_arr;
}
// iterator insert(const_iterator pos, const basic_json& val)
{
json j_arr = json::array();
j_arr.insert(j_arr.begin(), json::object());
j_arr.insert(j_arr.begin(), json::object());
j_arr.insert(j_arr.begin(), json::object());
j_arr.insert(j_arr.begin(), json::object());
json j_obj = json::object();
j_obj["key"] = j_arr;
}
// iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
{
json j_arr = json::array();
j_arr.insert(j_arr.begin(), 2, json::object());
json j_obj = json::object();
j_obj["key"] = j_arr;
}
// iterator insert(const_iterator pos, const_iterator first, const_iterator last)
{
json j_arr = json::array();
json j_objects = {json::object(), json::object()};
j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
json j_obj = json::object();
j_obj["key"] = j_arr;
}
}
SECTION("Regression test for issue #2962 - JSON_DIAGNOSTICS assertion for ordered_json")
{
nlohmann::ordered_json j;
nlohmann::ordered_json j2;
const std::string value;
j["first"] = value;
j["second"] = value;
j2["something"] = j;
}
SECTION("Regression test for issue #3007 - Parent pointers properly set when using update()")
{
// void update(const_reference j)
{
json j = json::object();
{
json j2 = json::object();
j2["one"] = 1;
j.update(j2);
}
// Must call operator[] on const element, otherwise m_parent gets updated.
auto const& constJ = j;
CHECK_THROWS_WITH_AS(constJ["one"].at(0), "[json.exception.type_error.304] (/one) cannot use at() with number", json::type_error);
}
// void update(const_iterator first, const_iterator last)
{
json j = json::object();
{
json j2 = json::object();
j2["one"] = 1;
j.update(j2.begin(), j2.end());
}
// Must call operator[] on const element, otherwise m_parent gets updated.
auto const& constJ = j;
CHECK_THROWS_WITH_AS(constJ["one"].at(0), "[json.exception.type_error.304] (/one) cannot use at() with number", json::type_error);
}
// Code from #3007 triggering unwanted assertion without fix to update().
{
json root = json::array();
json lower = json::object();
{
json lowest = json::object();
lowest["one"] = 1;
lower.update(lowest);
}
root.push_back(lower);
}
}
SECTION("Regression test for issue #3032 - Yet another assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
{
// reference operator[](size_type idx)
{
json j_arr = json::array();
j_arr[0] = 0;
j_arr[1] = 1;
j_arr[2] = 2;
j_arr[3] = 3;
j_arr[4] = 4;
j_arr[5] = 5;
j_arr[6] = 6;
j_arr[7] = 7;
json const j_arr_copy = j_arr;
}
}
}

View File

@ -0,0 +1,52 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
// disable -Wnoexcept as exceptions are switched off for this test suite
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
#include <nlohmann/json.hpp>
using json = nlohmann::json;
/////////////////////////////////////////////////////////////////////
// for #2824
/////////////////////////////////////////////////////////////////////
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
{
public:
explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser<json>(j, false) {}
static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
{
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
return false;
}
static std::string* error_string;
};
std::string* sax_no_exception::error_string = nullptr;
TEST_CASE("Tests with disabled exceptions")
{
SECTION("issue #2824 - encoding of json::exception::what()")
{
json j;
sax_no_exception sax(j);
CHECK (!json::sax_parse("xyz", &sax));
CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
}
}
DOCTEST_GCC_SUPPRESS_WARNING_POP

View File

@ -0,0 +1,881 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
TEST_CASE("element access 1")
{
SECTION("array")
{
json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
const json j_const = j;
SECTION("access specified element with bounds checking")
{
SECTION("access within bounds")
{
CHECK(j.at(0) == json(1));
CHECK(j.at(1) == json(1u));
CHECK(j.at(2) == json(true));
CHECK(j.at(3) == json(nullptr));
CHECK(j.at(4) == json("string"));
CHECK(j.at(5) == json(42.23));
CHECK(j.at(6) == json::object());
CHECK(j.at(7) == json({1, 2, 3}));
CHECK(j_const.at(0) == json(1));
CHECK(j_const.at(1) == json(1u));
CHECK(j_const.at(2) == json(true));
CHECK(j_const.at(3) == json(nullptr));
CHECK(j_const.at(4) == json("string"));
CHECK(j_const.at(5) == json(42.23));
CHECK(j_const.at(6) == json::object());
CHECK(j_const.at(7) == json({1, 2, 3}));
}
SECTION("access outside bounds")
{
CHECK_THROWS_WITH_AS(j.at(8),
"[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
CHECK_THROWS_WITH_AS(j_const.at(8),
"[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
}
SECTION("access on non-array type")
{
SECTION("null")
{
json j_nonarray(json::value_t::null);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with null", json::type_error&);
}
SECTION("boolean")
{
json j_nonarray(json::value_t::boolean);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&);
}
SECTION("string")
{
json j_nonarray(json::value_t::string);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with string", json::type_error&);
}
SECTION("object")
{
json j_nonarray(json::value_t::object);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with object", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with object", json::type_error&);
}
SECTION("number (integer)")
{
json j_nonarray(json::value_t::number_integer);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
}
SECTION("number (unsigned)")
{
json j_nonarray(json::value_t::number_unsigned);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
}
SECTION("number (floating-point)")
{
json j_nonarray(json::value_t::number_float);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&);
}
}
}
SECTION("front and back")
{
CHECK(j.front() == json(1));
CHECK(j_const.front() == json(1));
CHECK(j.back() == json({1, 2, 3}));
CHECK(j_const.back() == json({1, 2, 3}));
}
SECTION("access specified element")
{
SECTION("access within bounds")
{
CHECK(j[0] == json(1));
CHECK(j[1] == json(1u));
CHECK(j[2] == json(true));
CHECK(j[3] == json(nullptr));
CHECK(j[4] == json("string"));
CHECK(j[5] == json(42.23));
CHECK(j[6] == json::object());
CHECK(j[7] == json({1, 2, 3}));
CHECK(j_const[0] == json(1));
CHECK(j_const[1] == json(1u));
CHECK(j_const[2] == json(true));
CHECK(j_const[3] == json(nullptr));
CHECK(j_const[4] == json("string"));
CHECK(j_const[5] == json(42.23));
CHECK(j_const[6] == json::object());
CHECK(j_const[7] == json({1, 2, 3}));
}
SECTION("access on non-array type")
{
SECTION("null")
{
SECTION("standard tests")
{
json j_nonarray(json::value_t::null);
const json j_nonarray_const(j_nonarray);
CHECK_NOTHROW(j_nonarray[0]);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with null", json::type_error&);
}
SECTION("implicit transformation to properly filled array")
{
json j_nonarray;
j_nonarray[3] = 42;
CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
}
}
SECTION("boolean")
{
json j_nonarray(json::value_t::boolean);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&);
}
SECTION("string")
{
json j_nonarray(json::value_t::string);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&);
}
SECTION("object")
{
json j_nonarray(json::value_t::object);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&);
}
SECTION("number (integer)")
{
json j_nonarray(json::value_t::number_integer);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
}
SECTION("number (unsigned)")
{
json j_nonarray(json::value_t::number_unsigned);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
}
SECTION("number (floating-point)")
{
json j_nonarray(json::value_t::number_float);
const json j_nonarray_const(j_nonarray);
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
}
}
}
SECTION("remove specified element")
{
SECTION("remove element by index")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(0);
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(1);
CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(2);
CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(3);
CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(4);
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(5);
CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(6);
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
jarray.erase(7);
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
CHECK_THROWS_WITH_AS(jarray.erase(8), "[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
}
}
SECTION("remove element by iterator")
{
SECTION("erase(begin())")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::iterator const it2 = jarray.erase(jarray.begin());
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(1u));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::const_iterator const it2 = jarray.erase(jarray.cbegin());
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(1u));
}
}
SECTION("erase(begin(), end())")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
CHECK(jarray == json::array());
CHECK(it2 == jarray.end());
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
CHECK(jarray == json::array());
CHECK(it2 == jarray.cend());
}
}
SECTION("erase(begin(), begin())")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::iterator const it2 = jarray.erase(jarray.begin(), jarray.begin());
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(1));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::const_iterator const it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(1));
}
}
SECTION("erase at offset")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::iterator const it = jarray.begin() + 4;
json::iterator const it2 = jarray.erase(it);
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(42.23));
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::const_iterator const it = jarray.cbegin() + 4;
json::const_iterator const it2 = jarray.erase(it);
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
CHECK(*it2 == json(42.23));
}
}
SECTION("erase subrange")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::iterator const it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
CHECK(*it2 == json::object());
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json::const_iterator const it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
CHECK(*it2 == json::object());
}
}
SECTION("different arrays")
{
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json jarray2 = {"foo", "bar"};
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin()),
"[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray.begin(), jarray2.end()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray.end()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray2.end()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
}
{
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
json const jarray2 = {"foo", "bar"};
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin()),
"[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray.cbegin(), jarray2.cend()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray.cend()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()),
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
}
}
}
SECTION("remove element by index in non-array type")
{
SECTION("null")
{
json j_nonobject(json::value_t::null);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
}
SECTION("boolean")
{
json j_nonobject(json::value_t::boolean);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with boolean", json::type_error&);
}
SECTION("string")
{
json j_nonobject(json::value_t::string);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with string", json::type_error&);
}
SECTION("object")
{
json j_nonobject(json::value_t::object);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with object", json::type_error&);
}
SECTION("number (integer)")
{
json j_nonobject(json::value_t::number_integer);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
}
SECTION("number (unsigned)")
{
json j_nonobject(json::value_t::number_unsigned);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
}
SECTION("number (floating-point)")
{
json j_nonobject(json::value_t::number_float);
CHECK_THROWS_WITH_AS(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number", json::type_error&);
}
}
}
}
SECTION("other values")
{
SECTION("front and back")
{
SECTION("null")
{
{
json j;
CHECK_THROWS_WITH_AS(j.front(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.back(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
{
const json j{};
CHECK_THROWS_WITH_AS(j.front(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.back(), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
}
}
SECTION("string")
{
{
json j = "foo";
CHECK(j.front() == j);
CHECK(j.back() == j);
}
{
const json j = "bar";
CHECK(j.front() == j);
CHECK(j.back() == j);
}
}
SECTION("number (boolean)")
{
{
json j = false;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
{
const json j = true;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
}
SECTION("number (integer)")
{
{
json j = 17;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
{
const json j = 17;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
{
const json j = 17u;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
{
const json j = 23.42;
CHECK(j.front() == j);
CHECK(j.back() == j);
}
}
}
SECTION("erase with one valid iterator")
{
SECTION("null")
{
{
json j;
CHECK_THROWS_WITH_AS(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
}
{
json j;
CHECK_THROWS_WITH_AS(j.erase(j.begin()),
"[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
}
}
SECTION("string")
{
{
json j = "foo";
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = "bar";
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (boolean)")
{
{
json j = false;
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = true;
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (integer)")
{
{
json j = 17;
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 17;
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 17u;
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 23.42;
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("binary")
{
{
json j = json::binary({1, 2, 3});
json::iterator it = j.erase(j.begin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = json::binary({1, 2, 3});
json::const_iterator it = j.erase(j.cbegin());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
}
SECTION("erase with one invalid iterator")
{
SECTION("string")
{
{
json j = "foo";
CHECK_THROWS_WITH_AS(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
{
json j = "bar";
CHECK_THROWS_WITH_AS(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
}
SECTION("number (boolean)")
{
{
json j = false;
CHECK_THROWS_WITH_AS(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
{
json j = true;
CHECK_THROWS_WITH_AS(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
}
SECTION("number (integer)")
{
{
json j = 17;
CHECK_THROWS_WITH_AS(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
{
json j = 17;
CHECK_THROWS_WITH_AS(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
CHECK_THROWS_WITH_AS(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
{
json j = 17u;
CHECK_THROWS_WITH_AS(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
CHECK_THROWS_WITH_AS(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
{
json j = 23.42;
CHECK_THROWS_WITH_AS(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range", json::invalid_iterator&);
}
}
}
SECTION("erase with two valid iterators")
{
SECTION("null")
{
{
json j;
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.end()), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
}
{
json j;
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cend()), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
}
}
SECTION("string")
{
{
json j = "foo";
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = "bar";
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (boolean)")
{
{
json j = false;
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = true;
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (integer)")
{
{
json j = 17;
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 17;
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 17u;
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = 23.42;
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
SECTION("binary")
{
{
json j = json::binary({1, 2, 3});
json::iterator it = j.erase(j.begin(), j.end());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
{
json j = json::binary({1, 2, 3});
json::const_iterator it = j.erase(j.cbegin(), j.cend());
CHECK(j.type() == json::value_t::null);
CHECK(it == j.end());
}
}
}
SECTION("erase with two invalid iterators")
{
SECTION("string")
{
{
json j = "foo";
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json j = "bar";
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
SECTION("number (boolean)")
{
{
json j = false;
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json j = true;
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
SECTION("number (integer)")
{
{
json j = 17;
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json j = 17;
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json j = 17u;
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json j = 23.42;
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json;
#include <set>
TEST_CASE("hash<nlohmann::json>")
{
// Collect hashes for different JSON values and make sure that they are distinct
// We cannot compare against fixed values, because the implementation of
// std::hash may differ between compilers.
std::set<std::size_t> hashes;
// null
hashes.insert(std::hash<json> {}(json(nullptr)));
// boolean
hashes.insert(std::hash<json> {}(json(true)));
hashes.insert(std::hash<json> {}(json(false)));
// string
hashes.insert(std::hash<json> {}(json("")));
hashes.insert(std::hash<json> {}(json("foo")));
// number
hashes.insert(std::hash<json> {}(json(0)));
hashes.insert(std::hash<json> {}(json(static_cast<unsigned>(0))));
hashes.insert(std::hash<json> {}(json(-1)));
hashes.insert(std::hash<json> {}(json(0.0)));
hashes.insert(std::hash<json> {}(json(42.23)));
// array
hashes.insert(std::hash<json> {}(json::array()));
hashes.insert(std::hash<json> {}(json::array({1, 2, 3})));
// object
hashes.insert(std::hash<json> {}(json::object()));
hashes.insert(std::hash<json> {}(json::object({{"foo", "bar"}})));
// binary
hashes.insert(std::hash<json> {}(json::binary({})));
hashes.insert(std::hash<json> {}(json::binary({}, 0)));
hashes.insert(std::hash<json> {}(json::binary({}, 42)));
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3})));
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3}, 0)));
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3}, 42)));
// discarded
hashes.insert(std::hash<json> {}(json(json::value_t::discarded)));
CHECK(hashes.size() == 21);
}
TEST_CASE("hash<nlohmann::ordered_json>")
{
// Collect hashes for different JSON values and make sure that they are distinct
// We cannot compare against fixed values, because the implementation of
// std::hash may differ between compilers.
std::set<std::size_t> hashes;
// null
hashes.insert(std::hash<ordered_json> {}(ordered_json(nullptr)));
// boolean
hashes.insert(std::hash<ordered_json> {}(ordered_json(true)));
hashes.insert(std::hash<ordered_json> {}(ordered_json(false)));
// string
hashes.insert(std::hash<ordered_json> {}(ordered_json("")));
hashes.insert(std::hash<ordered_json> {}(ordered_json("foo")));
// number
hashes.insert(std::hash<ordered_json> {}(ordered_json(0)));
hashes.insert(std::hash<ordered_json> {}(ordered_json(static_cast<unsigned>(0))));
hashes.insert(std::hash<ordered_json> {}(ordered_json(-1)));
hashes.insert(std::hash<ordered_json> {}(ordered_json(0.0)));
hashes.insert(std::hash<ordered_json> {}(ordered_json(42.23)));
// array
hashes.insert(std::hash<ordered_json> {}(ordered_json::array()));
hashes.insert(std::hash<ordered_json> {}(ordered_json::array({1, 2, 3})));
// object
hashes.insert(std::hash<ordered_json> {}(ordered_json::object()));
hashes.insert(std::hash<ordered_json> {}(ordered_json::object({{"foo", "bar"}})));
// binary
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({})));
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({}, 0)));
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({}, 42)));
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3})));
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3}, 0)));
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3}, 42)));
// discarded
hashes.insert(std::hash<ordered_json> {}(ordered_json(ordered_json::value_t::discarded)));
CHECK(hashes.size() == 21);
}

View File

@ -0,0 +1,459 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <sstream>
#include "make_test_data_available.hpp"
TEST_CASE("object inspection")
{
SECTION("convenience type checker")
{
SECTION("object")
{
json const j {{"foo", 1}, {"bar", false}};
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(!j.is_primitive());
CHECK(j.is_structured());
}
SECTION("array")
{
json const j {"foo", 1, 1u, 42.23, false};
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(!j.is_primitive());
CHECK(j.is_structured());
}
SECTION("null")
{
json const j(nullptr);
CHECK(j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("boolean")
{
json const j(true);
CHECK(!j.is_null());
CHECK(j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("string")
{
json const j("Hello world");
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("number (integer)")
{
json const j(42);
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(j.is_number());
CHECK(j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("number (unsigned)")
{
json const j(42u);
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(j.is_number());
CHECK(j.is_number_integer());
CHECK(j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("number (floating-point)")
{
json const j(42.23);
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("binary")
{
json const j(json::value_t::binary);
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(!j.is_discarded());
CHECK(j.is_primitive());
CHECK(!j.is_structured());
}
SECTION("discarded")
{
json const j(json::value_t::discarded);
CHECK(!j.is_null());
CHECK(!j.is_boolean());
CHECK(!j.is_number());
CHECK(!j.is_number_integer());
CHECK(!j.is_number_unsigned());
CHECK(!j.is_number_float());
CHECK(!j.is_binary());
CHECK(!j.is_object());
CHECK(!j.is_array());
CHECK(!j.is_string());
CHECK(j.is_discarded());
CHECK(!j.is_primitive());
CHECK(!j.is_structured());
}
}
SECTION("serialization")
{
json const j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
SECTION("no indent / indent=-1")
{
CHECK(j.dump() ==
"{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
CHECK(j.dump() == j.dump(-1));
}
SECTION("indent=0")
{
CHECK(j.dump(0) ==
"{\n\"array\": [\n1,\n2,\n3,\n4\n],\n\"boolean\": false,\n\"null\": null,\n\"number\": 42,\n\"object\": {},\n\"string\": \"Hello world\"\n}");
}
SECTION("indent=1, space='\t'")
{
CHECK(j.dump(1, '\t') ==
"{\n\t\"array\": [\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t],\n\t\"boolean\": false,\n\t\"null\": null,\n\t\"number\": 42,\n\t\"object\": {},\n\t\"string\": \"Hello world\"\n}");
}
SECTION("indent=4")
{
CHECK(j.dump(4) ==
"{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
}
SECTION("indent=x")
{
CHECK(j.dump().size() == 94);
CHECK(j.dump(1).size() == 127);
CHECK(j.dump(2).size() == 142);
CHECK(j.dump(512).size() == 7792);
// important test, because it yields a resize of the indent_string
// inside the dump() function
CHECK(j.dump(1024).size() == 15472);
const auto binary = json::binary({1, 2, 3}, 128);
CHECK(binary.dump(1024).size() == 2086);
}
SECTION("dump and floating-point numbers")
{
auto s = json(42.23).dump();
CHECK(s.find("42.23") != std::string::npos);
}
SECTION("dump and small floating-point numbers")
{
auto s = json(1.23456e-78).dump();
CHECK(s.find("1.23456e-78") != std::string::npos);
}
SECTION("dump and non-ASCII characters")
{
CHECK(json("ä").dump() == "\"ä\"");
CHECK(json("Ö").dump() == "\"Ö\"");
CHECK(json("❤️").dump() == "\"❤️\"");
}
SECTION("dump with ensure_ascii and non-ASCII characters")
{
CHECK(json("ä").dump(-1, ' ', true) == "\"\\u00e4\"");
CHECK(json("Ö").dump(-1, ' ', true) == "\"\\u00d6\"");
CHECK(json("❤️").dump(-1, ' ', true) == "\"\\u2764\\ufe0f\"");
}
SECTION("full Unicode escaping to ASCII")
{
SECTION("parsing yields the same JSON value")
{
std::ifstream f_escaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode_ascii.json");
std::ifstream f_unescaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json");
json j1 = json::parse(f_escaped);
json j2 = json::parse(f_unescaped);
CHECK(j1 == j2);
}
SECTION("dumping yields the same JSON text")
{
std::ifstream f_escaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode_ascii.json");
std::ifstream f_unescaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json");
json const value = json::parse(f_unescaped);
std::string text = value.dump(4, ' ', true);
std::string expected((std::istreambuf_iterator<char>(f_escaped)),
std::istreambuf_iterator<char>());
CHECK(text == expected);
}
}
SECTION("serialization of discarded element")
{
json const j_discarded(json::value_t::discarded);
CHECK(j_discarded.dump() == "<discarded>");
}
SECTION("check that precision is reset after serialization")
{
// create stringstream and set precision
std::stringstream ss;
ss.precision(3);
ss << 3.141592653589793 << std::fixed;
CHECK(ss.str() == "3.14");
// reset stringstream
ss.str(std::string());
// use stringstream for JSON serialization
json const j_number = 3.14159265358979;
ss << j_number;
// check that precision has been overridden during serialization
CHECK(ss.str() == "3.14159265358979");
// check that precision has been restored
CHECK(ss.precision() == 3);
}
}
SECTION("round trips")
{
for (const auto& s :
{"3.141592653589793", "1000000000000000010E5"
})
{
json const j1 = json::parse(s);
std::string s1 = j1.dump();
json const j2 = json::parse(s1);
std::string s2 = j2.dump();
CHECK(s1 == s2);
}
}
SECTION("return the type of the object (explicit)")
{
SECTION("null")
{
json const j = nullptr;
CHECK(j.type() == json::value_t::null);
}
SECTION("object")
{
json const j = {{"foo", "bar"}};
CHECK(j.type() == json::value_t::object);
}
SECTION("array")
{
json const j = {1, 2, 3, 4};
CHECK(j.type() == json::value_t::array);
}
SECTION("boolean")
{
json const j = true;
CHECK(j.type() == json::value_t::boolean);
}
SECTION("string")
{
json const j = "Hello world";
CHECK(j.type() == json::value_t::string);
}
SECTION("number (integer)")
{
json const j = 23;
CHECK(j.type() == json::value_t::number_integer);
}
SECTION("number (unsigned)")
{
json const j = 23u;
CHECK(j.type() == json::value_t::number_unsigned);
}
SECTION("number (floating-point)")
{
json const j = 42.23;
CHECK(j.type() == json::value_t::number_float);
}
}
SECTION("return the type of the object (implicit)")
{
SECTION("null")
{
json const j = nullptr;
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("object")
{
json const j = {{"foo", "bar"}};
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("array")
{
json const j = {1, 2, 3, 4};
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("boolean")
{
json const j = true;
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("string")
{
json const j = "Hello world";
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("number (integer)")
{
json const j = 23;
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("number (unsigned)")
{
json const j = 23u;
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("number (floating-point)")
{
json const j = 42.23;
json::value_t t = j;
CHECK(t == j.type());
}
SECTION("binary")
{
json const j = json::binary({});
json::value_t t = j;
CHECK(t == j.type());
}
}
}

Some files were not shown because too many files have changed in this diff Show More