diff --git a/.gitignore b/.gitignore index bec7f598..7e5a881e 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ benchmarks/files/numbers/*.json .wsjcpp/* .idea -cmake-build-debug +/cmake-build-* test/test-* /.vs @@ -32,3 +32,4 @@ doc/mkdocs/docs/images doc/mkdocs/docs/examples doc/mkdocs/site doc/mkdocs/docs/__pycache__/ +doc/xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b18b83d..7ee9381d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ endif () option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON) option(JSON_Install "Install CMake targets during install step." ON) option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) -option(JSON_ImplicitConversions "Enable implicit conversions" ON) +option(JSON_ImplicitConversions "Enable implicit conversions." ON) ## ## CONFIGURATION @@ -49,6 +49,10 @@ else() message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}") endif() +if (NOT JSON_ImplicitConversions) + message(STATUS "Implicit conversions are disabled") +endif() + ## ## TARGET ## create target and add include path diff --git a/Makefile b/Makefile index fd73a338..9d26bc9d 100644 --- a/Makefile +++ b/Makefile @@ -54,13 +54,13 @@ all: ########################################################################## coverage: - rm -fr build_coverage - mkdir build_coverage - cd build_coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON - cd build_coverage ; ninja - cd build_coverage ; ctest -j10 - cd build_coverage ; ninja lcov_html - open build_coverage/test/html/index.html + rm -fr cmake-build-coverage + mkdir cmake-build-coverage + cd cmake-build-coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON + cd cmake-build-coverage ; ninja + cd cmake-build-coverage ; ctest -j10 + cd cmake-build-coverage ; ninja lcov_html + open cmake-build-coverage/test/html/index.html ########################################################################## # documentation tests @@ -88,7 +88,7 @@ doctest: # -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches # -Wno-weak-vtables: exception class is defined inline, but has virtual method pedantic_clang: - rm -fr build_pedantic + rm -fr cmake-build-pedantic CXXFLAGS=" \ -std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \ -Werror \ @@ -103,12 +103,12 @@ pedantic_clang: -Wno-padded \ -Wno-range-loop-analysis \ -Wno-switch-enum -Wno-covered-switch-default \ - -Wno-weak-vtables" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On - cmake --build build_pedantic + -Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On + cmake --build cmake-build-pedantic # calling GCC with most warnings pedantic_gcc: - rm -fr build_pedantic + rm -fr cmake-build-pedantic CXXFLAGS=" \ -std=c++11 \ -pedantic \ @@ -366,19 +366,19 @@ pedantic_gcc: -Wwrite-strings \ -Wzero-as-null-pointer-constant \ -Wzero-length-bounds \ - " cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On - cmake --build build_pedantic + " cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On + cmake --build cmake-build-pedantic ########################################################################## # benchmarks ########################################################################## run_benchmarks: - rm -fr build_benchmarks - mkdir build_benchmarks - cd build_benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On - cd build_benchmarks ; ninja - cd build_benchmarks ; ./json_benchmarks + rm -fr cmake-build-benchmarks + mkdir cmake-build-benchmarks + cd cmake-build-benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On + cd cmake-build-benchmarks ; ninja + cd cmake-build-benchmarks ; ./json_benchmarks ########################################################################## # fuzzing @@ -451,14 +451,14 @@ cppcheck: # call Clang Static Analyzer clang_analyze: - rm -fr clang_analyze_build - mkdir clang_analyze_build - cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On - cd clang_analyze_build ; \ + rm -fr cmake-build-clang-analyze + mkdir cmake-build-clang-analyze + cd cmake-build-clang-analyze ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On + cd cmake-build-clang-analyze ; \ $(COMPILER_DIR)/scan-build \ -enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull \ --use-c++=$(COMPILER_DIR)/clang++ -analyze-headers -o report ninja - open clang_analyze_build/report/*/index.html + open cmake-build-clang-analyze/report/*/index.html # call cpplint # Note: some errors expected due to false positives @@ -473,18 +473,18 @@ clang_tidy: # call PVS-Studio Analyzer pvs_studio: - rm -fr pvs_studio_build - mkdir pvs_studio_build - cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=ON - cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10 - cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs - open pvs_studio_build/pvs/index.html + rm -fr cmake-build-pvs-studio + mkdir cmake-build-pvs-studio + cd cmake-build-pvs-studio ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=ON + cd cmake-build-pvs-studio ; pvs-studio-analyzer analyze -j 10 + cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs + open cmake-build-pvs-studio/pvs/index.html # call Infer static analyzer infer: - rm -fr infer_build - mkdir infer_build - cd infer_build ; infer compile -- cmake .. -DJSON_MultipleHeaders=ON ; infer run -- make -j 4 + rm -fr cmake-build-infer + mkdir cmake-build-infer + cd cmake-build-infer ; infer compile -- cmake .. -DJSON_MultipleHeaders=ON ; infer run -- make -j 4 # call OCLint static analyzer oclint: @@ -493,11 +493,11 @@ oclint: # execute the test suite with Clang sanitizers (address and undefined behavior) clang_sanitize: - rm -fr clang_sanitize_build - mkdir clang_sanitize_build - cd clang_sanitize_build ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja - cd clang_sanitize_build ; ninja - cd clang_sanitize_build ; ctest -j10 + rm -fr cmake-build-clang-sanitize + mkdir cmake-build-clang-sanitize + cd cmake-build-clang-sanitize ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja + cd cmake-build-clang-sanitize ; ninja + cd cmake-build-clang-sanitize ; ctest -j10 ########################################################################## @@ -525,7 +525,7 @@ pretty: --preserve-date \ --suffix=none \ --formatted \ - $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp + $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/utils/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp # create single header file amalgamate: $(AMALGAMATED_FILE) @@ -625,7 +625,7 @@ clean: rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html rm -fr benchmarks/files/numbers/*.json rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64 - rm -fr build_coverage build_benchmarks fuzz-testing clang_analyze_build pvs_studio_build infer_build clang_sanitize_build cmake_build + rm -fr cmake-build-coverage cmake-build-benchmarks fuzz-testing cmake-build-clang-analyze cmake-build-pvs-studio cmake-build-infer cmake-build-clang-sanitize cmake_build $(MAKE) clean -Cdoc ########################################################################## diff --git a/README.md b/README.md index c1463349..eb9c268e 100644 --- a/README.md +++ b/README.md @@ -762,6 +762,7 @@ Supported types can be implicitly converted to JSON values. It is recommended to **NOT USE** implicit conversions **FROM** a JSON value. You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958). +You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` before including the `json.hpp` header. When using CMake, you can also achieve this by setting the option `JSON_ImplicitConversions` to `OFF`. ```cpp // strings diff --git a/doc/mkdocs/docs/features/arbitrary_types.md b/doc/mkdocs/docs/features/arbitrary_types.md index 7bd7adf7..23913bba 100644 --- a/doc/mkdocs/docs/features/arbitrary_types.md +++ b/doc/mkdocs/docs/features/arbitrary_types.md @@ -92,6 +92,10 @@ There are two macros to make your life easier as long as you (1) want to use a J In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. +!!! note + + At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. + ??? example The `to_json`/`from_json` functions for the `person` struct above can be created with: diff --git a/doc/mkdocs/docs/features/macros.md b/doc/mkdocs/docs/features/macros.md index 48c71adf..696438d2 100644 --- a/doc/mkdocs/docs/features/macros.md +++ b/doc/mkdocs/docs/features/macros.md @@ -36,6 +36,26 @@ This macro overrides `#!cpp try` calls inside the library. It has no arguments a See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example. +## `JSON_USE_IMPLICIT_CONVERSIONS` + +When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. + +??? example + + This is an example for an implicit conversion: + + ```cpp + json j = "Hello, world!"; + std::string s = j; + ``` + + When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be written like this: + + ```cpp + json j = "Hello, world!"; + auto s = j.get(); + ``` + ## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object. diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index c32a46d1..8c9f6329 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -264,8 +264,8 @@ #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) -#define NLOHMANN_JSON_TO(v1) j[#v1] = t.v1; -#define NLOHMANN_JSON_FROM(v1) j.at(#v1).get_to(t.v1); +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); /*! @brief macro @@ -273,8 +273,8 @@ @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } /*! @brief macro @@ -282,8 +282,8 @@ @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } #ifndef JSON_USE_IMPLICIT_CONVERSIONS #define JSON_USE_IMPLICIT_CONVERSIONS 1 diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 53c174a3..f08967ce 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2281,8 +2281,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) -#define NLOHMANN_JSON_TO(v1) j[#v1] = t.v1; -#define NLOHMANN_JSON_FROM(v1) j.at(#v1).get_to(t.v1); +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); /*! @brief macro @@ -2290,8 +2290,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } /*! @brief macro @@ -2299,8 +2299,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } #ifndef JSON_USE_IMPLICIT_CONVERSIONS #define JSON_USE_IMPLICIT_CONVERSIONS 1 @@ -16501,7 +16501,7 @@ class basic_json detail::parser_callback_tcb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false - ) + ) { return ::nlohmann::detail::parser(std::move(adapter), std::move(cb), allow_exceptions, ignore_comments); @@ -25041,7 +25041,7 @@ template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value&& is_nothrow_move_assignable::value - ) +) { j1.swap(j2); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 76ba31d8..9ce1594c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -151,7 +151,7 @@ foreach(file ${files}) $<$>:-Wno-deprecated;-Wno-float-equal> $<$:-Wno-deprecated-declarations> ) - target_include_directories(${testcase} PRIVATE ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map) + target_include_directories(${testcase} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map) target_link_libraries(${testcase} PRIVATE ${NLOHMANN_JSON_TARGET_NAME}) if (JSON_Coverage) diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index aa3acbc3..80a8012d 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -35,6 +35,7 @@ using nlohmann::json; #include #include #include +#include TEST_CASE("BSON") { @@ -1263,10 +1264,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse BSON file - std::ifstream f_bson(filename + ".bson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_bson)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".bson"); json j2; CHECK_NOTHROW(j2 = json::from_bson(packed)); @@ -1296,10 +1294,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse BSON file - std::ifstream f_bson(filename + ".bson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_bson)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".bson"); json j2; CHECK_NOTHROW(j2 = json::from_bson({packed.data(), packed.size()})); @@ -1314,10 +1309,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse BSON file - std::ifstream f_bson(filename + ".bson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_bson)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".bson"); { INFO_WITH_TEMP(filename + ": output adapters: std::vector"); diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 7eaba84a..d5641327 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -39,6 +39,7 @@ using nlohmann::json; #include #include #include +#include namespace { @@ -1920,9 +1921,7 @@ TEST_CASE("single CBOR roundtrip") json j1 = json::parse(f_json); // parse CBOR file - std::ifstream f_cbor(filename + ".cbor", std::ios::binary); - std::vector packed((std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".cbor"); json j2; CHECK_NOTHROW(j2 = json::from_cbor(packed)); @@ -1994,10 +1993,7 @@ TEST_CASE("CBOR regressions") try { // parse CBOR file - std::ifstream f_cbor(filename, std::ios::binary); - std::vector vec1( - (std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto vec1 = utils::read_binary_file(filename); json j1 = json::from_cbor(vec1); try @@ -2204,10 +2200,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse CBOR file - std::ifstream f_cbor(filename + ".cbor", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".cbor"); json j2; CHECK_NOTHROW(j2 = json::from_cbor(packed)); @@ -2237,10 +2230,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse CBOR file - std::ifstream f_cbor(filename + ".cbor", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".cbor"); json j2; CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()})); @@ -2255,10 +2245,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse CBOR file - std::ifstream f_cbor(filename + ".cbor", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".cbor"); if (!exclude_packed.count(filename)) { @@ -2493,15 +2480,11 @@ TEST_CASE("examples from RFC 7049 Appendix A") SECTION("byte arrays") { - std::ifstream f_cbor(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor", std::ios::binary); - std::vector packed((std::istreambuf_iterator(f_cbor)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor"); json j; CHECK_NOTHROW(j = json::from_cbor(packed)); - std::ifstream f_bin(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out", std::ios::binary); - std::vector expected((std::istreambuf_iterator(f_bin)), - std::istreambuf_iterator()); + auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out"); CHECK(j == json::binary(expected)); CHECK(json::to_cbor(json::binary(std::vector {}, 0x42)) == std::vector {0xd8, 0x42, 0x40}); diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 97a4e6b6..7ab0e9a3 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -278,8 +278,8 @@ TEST_CASE("value conversion") SECTION("reserve is called on containers that supports it") { // make sure all values are properly copied - json j({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); - auto v2 = j.get>(); + json j2({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + auto v2 = j2.get>(); CHECK(v2.size() == 10); } #endif diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 2130c887..c3761fb5 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -37,6 +37,7 @@ using nlohmann::json; #include #include #include +#include namespace { @@ -514,7 +515,7 @@ TEST_CASE("MessagePack") (static_cast(result[2]) << 020) + (static_cast(result[3]) << 010) + static_cast(result[4]); - CHECK(restored == i); + CHECK(static_cast(restored) == i); // roundtrip CHECK(json::from_msgpack(result) == j); @@ -1609,9 +1610,7 @@ TEST_CASE("single MessagePack roundtrip") json j1 = json::parse(f_json); // parse MessagePack file - std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary); - std::vector packed((std::istreambuf_iterator(f_msgpack)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".msgpack"); json j2; CHECK_NOTHROW(j2 = json::from_msgpack(packed)); @@ -1824,10 +1823,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse MessagePack file - std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_msgpack)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".msgpack"); json j2; CHECK_NOTHROW(j2 = json::from_msgpack(packed)); @@ -1857,10 +1853,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse MessagePack file - std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_msgpack)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".msgpack"); json j2; CHECK_NOTHROW(j2 = json::from_msgpack({packed.data(), packed.size()})); @@ -1875,10 +1868,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip()) json j1 = json::parse(f_json); // parse MessagePack file - std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_msgpack)), - std::istreambuf_iterator()); + auto packed = utils::read_binary_file(filename + ".msgpack"); if (!exclude_packed.count(filename)) { diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 649ac656..d70114ee 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1516,8 +1516,8 @@ TEST_CASE("regression tests") SECTION("issue #838 - incorrect parse error with binary data in keys") { - uint8_t key1[] = { 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127 }; - std::string key1_str(key1, key1 + sizeof(key1) / sizeof(key1[0])); + uint8_t key1[] = { 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127, 0 }; + std::string key1_str(reinterpret_cast(key1)); json j = key1_str; CHECK_THROWS_AS(j.dump(), json::type_error&); CHECK_THROWS_WITH(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E"); diff --git a/test/src/unit-ubjson.cpp b/test/src/unit-ubjson.cpp index 0f95bcec..ac133c0b 100644 --- a/test/src/unit-ubjson.cpp +++ b/test/src/unit-ubjson.cpp @@ -35,6 +35,7 @@ using nlohmann::json; #include #include #include +#include namespace { @@ -2457,11 +2458,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip()) std::ifstream f_json(filename); json j1 = json::parse(f_json); - // parse MessagePack file - std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_ubjson)), - std::istreambuf_iterator()); + // parse UBJSON file + auto packed = utils::read_binary_file(filename + ".ubjson"); json j2; CHECK_NOTHROW(j2 = json::from_ubjson(packed)); @@ -2475,7 +2473,7 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip()) std::ifstream f_json(filename); json j1 = json::parse(f_json); - // parse MessagePack file + // parse UBJSON file std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary); json j2; CHECK_NOTHROW(j2 = json::from_ubjson(f_ubjson)); @@ -2490,11 +2488,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip()) std::ifstream f_json(filename); json j1 = json::parse(f_json); - // parse MessagePack file - std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_ubjson)), - std::istreambuf_iterator()); + // parse UBJSON file + auto packed = utils::read_binary_file(filename + ".ubjson"); json j2; CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()})); @@ -2508,11 +2503,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip()) std::ifstream f_json(filename); json j1 = json::parse(f_json); - // parse MessagePack file - std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary); - std::vector packed( - (std::istreambuf_iterator(f_ubjson)), - std::istreambuf_iterator()); + // parse UBJSON file + auto packed = utils::read_binary_file(filename + ".ubjson"); { INFO_WITH_TEMP(filename + ": output adapters: std::vector"); diff --git a/test/utils/test_utils.hpp b/test/utils/test_utils.hpp new file mode 100644 index 00000000..12c260e7 --- /dev/null +++ b/test/utils/test_utils.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include // uint8_t +#include // ifstream, istreambuf_iterator, ios +#include // vector + +namespace utils +{ + +inline std::vector 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 byte_vector; + byte_vector.reserve(static_cast(size)); + byte_vector.insert(byte_vector.begin(), std::istream_iterator(file), std::istream_iterator()); + return byte_vector; +} + +} // namespace utils