diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 1a47a885c0..d6b6540779 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -3,13 +3,61 @@ name: Ubuntu on: [push, pull_request] jobs: - build: + gcc_build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + - name: install_gcc + run: | + sudo apt update + sudo apt install gcc-10 g++-10 + shell: bash - name: cmake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On + env: + CC: gcc-10 + CXX: g++-10 + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 --output-on-failure + + clang_build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: install_gcc + run: | + sudo apt update + sudo apt install clang-10 + shell: bash + - name: cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On + env: + CC: clang-10 + CXX: clang++-10 + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 --output-on-failure + + clang_build_cxx20: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: install_gcc + run: | + sudo apt update + sudo apt install clang-10 + shell: bash + - name: cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_STANDARD_REQUIRED=ON + env: + CC: clang-10 + CXX: clang++-10 - name: build run: cmake --build build --parallel 10 - name: test diff --git a/Makefile b/Makefile index 0b9aa8213c..d3963f503e 100644 --- a/Makefile +++ b/Makefile @@ -84,6 +84,7 @@ doctest: # -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE # -Wno-padded: padding is nothing to warn about # -Wno-range-loop-analysis: items tests "for(const auto i...)" +# -Wno-extra-semi-stmt: spurious warnings for semicolons after JSON_ASSERT() # -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: @@ -100,6 +101,7 @@ pedantic_clang: -Wno-missing-prototypes \ -Wno-padded \ -Wno-range-loop-analysis \ + -Wno-extra-semi-stmt \ -Wno-switch-enum -Wno-covered-switch-default \ -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 diff --git a/include/nlohmann/detail/hash.hpp b/include/nlohmann/detail/hash.hpp index d2d5d332d3..c32d5535c5 100644 --- a/include/nlohmann/detail/hash.hpp +++ b/include/nlohmann/detail/hash.hpp @@ -3,6 +3,8 @@ #include // size_t, uint8_t #include // hash +#include + namespace nlohmann { namespace detail diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 6ae5882c7e..806e360306 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -11,6 +11,7 @@ #include // numeric_limits #include // char_traits, string #include // make_pair, move +#include // vector #include #include @@ -2340,7 +2341,7 @@ class binary_reader break; } result.push_back(static_cast(current)); - }; + } return success; } diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 63921ca55c..a78a6ec96c 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -371,15 +371,37 @@ typename iterator_input_adapter_factory::adapter_type input_adapte } // Convenience shorthand from container to iterator -template -auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container))) +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl { - // Enable ADL - using std::begin; - using std::end; +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ return input_adapter(begin(container), end(container)); } + }; + +} + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 0a9601352e..eae82eaa32 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -1541,17 +1541,17 @@ class lexer : public lexer_base // literals case 't': { - std::array true_literal = {{'t', 'r', 'u', 'e'}}; + std::array true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}}; return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); } case 'f': { - std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; + std::array false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}}; return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); } case 'n': { - std::array null_literal = {{'n', 'u', 'l', 'l'}}; + std::array null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}}; return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); } diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index b4faa88a5d..67134166e5 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -38,8 +38,10 @@ This class implements a both iterators (iterator and const_iterator) for the template class iter_impl { + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; /// allow basic_json to access private members - friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + friend other_iter_impl; friend BasicJsonType; friend iteration_proxy; friend iteration_proxy_value; @@ -390,10 +392,11 @@ class iter_impl } /*! - @brief comparison: equal + @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator==(const iter_impl& other) const + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const { // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) @@ -417,16 +420,17 @@ class iter_impl } /*! - @brief comparison: not equal + @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator!=(const iter_impl& other) const + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const { return !operator==(other); } /*! - @brief comparison: smaller + @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<(const iter_impl& other) const @@ -453,7 +457,7 @@ class iter_impl } /*! - @brief comparison: less than or equal + @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<=(const iter_impl& other) const @@ -462,7 +466,7 @@ class iter_impl } /*! - @brief comparison: greater than + @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>(const iter_impl& other) const @@ -471,7 +475,7 @@ class iter_impl } /*! - @brief comparison: greater than or equal + @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>=(const iter_impl& other) const @@ -480,7 +484,7 @@ class iter_impl } /*! - @brief add to iterator + @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator+=(difference_type i) @@ -509,7 +513,7 @@ class iter_impl } /*! - @brief subtract from iterator + @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator-=(difference_type i) @@ -518,7 +522,7 @@ class iter_impl } /*! - @brief add to iterator + @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator+(difference_type i) const @@ -529,7 +533,7 @@ class iter_impl } /*! - @brief addition of distance and iterator + @brief addition of distance and iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ friend iter_impl operator+(difference_type i, const iter_impl& it) @@ -540,7 +544,7 @@ class iter_impl } /*! - @brief subtract from iterator + @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator-(difference_type i) const @@ -551,7 +555,7 @@ class iter_impl } /*! - @brief return difference + @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ difference_type operator-(const iter_impl& other) const @@ -572,7 +576,7 @@ class iter_impl } /*! - @brief access to successor + @brief access to successor @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference operator[](difference_type n) const @@ -603,7 +607,7 @@ class iter_impl } /*! - @brief return the key of an object iterator + @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ const typename object_t::key_type& key() const @@ -619,7 +623,7 @@ class iter_impl } /*! - @brief return the value of an iterator + @brief return the value of an iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference value() const diff --git a/include/nlohmann/detail/iterators/primitive_iterator.hpp b/include/nlohmann/detail/iterators/primitive_iterator.hpp index 16dcc9f97f..ae7471ef59 100644 --- a/include/nlohmann/detail/iterators/primitive_iterator.hpp +++ b/include/nlohmann/detail/iterators/primitive_iterator.hpp @@ -3,6 +3,8 @@ #include // ptrdiff_t #include // numeric_limits +#include + namespace nlohmann { namespace detail diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 56c15a3f66..1706cbdc6a 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -3,6 +3,7 @@ #include // numeric_limits #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval +#include // tuple #include #include diff --git a/include/nlohmann/thirdparty/hedley/hedley_undef.hpp b/include/nlohmann/thirdparty/hedley/hedley_undef.hpp index 88ee044da1..2f70f13c6d 100644 --- a/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +++ b/include/nlohmann/thirdparty/hedley/hedley_undef.hpp @@ -1,3 +1,5 @@ +#pragma once + #undef JSON_HEDLEY_ALWAYS_INLINE #undef JSON_HEDLEY_ARM_VERSION #undef JSON_HEDLEY_ARM_VERSION_CHECK diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9e988ab427..05262b84c8 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2826,6 +2826,7 @@ constexpr T static_const::value; #include // numeric_limits #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval +#include // tuple // #include @@ -4710,6 +4711,9 @@ class byte_container_with_subtype : public BinaryType #include // size_t, uint8_t #include // hash +// #include + + namespace nlohmann { namespace detail @@ -4838,6 +4842,7 @@ std::size_t hash(const BasicJsonType& j) #include // numeric_limits #include // char_traits, string #include // make_pair, move +#include // vector // #include @@ -5217,15 +5222,37 @@ typename iterator_input_adapter_factory::adapter_type input_adapte } // Convenience shorthand from container to iterator -template -auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container))) +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl { - // Enable ADL - using std::begin; - using std::end; +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ return input_adapter(begin(container), end(container)); } + }; + +} + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) @@ -7545,17 +7572,17 @@ class lexer : public lexer_base // literals case 't': { - std::array true_literal = {{'t', 'r', 'u', 'e'}}; + std::array true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}}; return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); } case 'f': { - std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; + std::array false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}}; return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); } case 'n': { - std::array null_literal = {{'n', 'u', 'l', 'l'}}; + std::array null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}}; return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); } @@ -10104,7 +10131,7 @@ class binary_reader break; } result.push_back(static_cast(current)); - }; + } return success; } @@ -10746,6 +10773,9 @@ class parser #include // ptrdiff_t #include // numeric_limits +// #include + + namespace nlohmann { namespace detail @@ -10934,8 +10964,10 @@ This class implements a both iterators (iterator and const_iterator) for the template class iter_impl { + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; /// allow basic_json to access private members - friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + friend other_iter_impl; friend BasicJsonType; friend iteration_proxy; friend iteration_proxy_value; @@ -11286,10 +11318,11 @@ class iter_impl } /*! - @brief comparison: equal + @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator==(const iter_impl& other) const + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const { // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) @@ -11313,16 +11346,17 @@ class iter_impl } /*! - @brief comparison: not equal + @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator!=(const iter_impl& other) const + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const { return !operator==(other); } /*! - @brief comparison: smaller + @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<(const iter_impl& other) const @@ -11349,7 +11383,7 @@ class iter_impl } /*! - @brief comparison: less than or equal + @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<=(const iter_impl& other) const @@ -11358,7 +11392,7 @@ class iter_impl } /*! - @brief comparison: greater than + @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>(const iter_impl& other) const @@ -11367,7 +11401,7 @@ class iter_impl } /*! - @brief comparison: greater than or equal + @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>=(const iter_impl& other) const @@ -11376,7 +11410,7 @@ class iter_impl } /*! - @brief add to iterator + @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator+=(difference_type i) @@ -11405,7 +11439,7 @@ class iter_impl } /*! - @brief subtract from iterator + @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator-=(difference_type i) @@ -11414,7 +11448,7 @@ class iter_impl } /*! - @brief add to iterator + @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator+(difference_type i) const @@ -11425,7 +11459,7 @@ class iter_impl } /*! - @brief addition of distance and iterator + @brief addition of distance and iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ friend iter_impl operator+(difference_type i, const iter_impl& it) @@ -11436,7 +11470,7 @@ class iter_impl } /*! - @brief subtract from iterator + @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator-(difference_type i) const @@ -11447,7 +11481,7 @@ class iter_impl } /*! - @brief return difference + @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ difference_type operator-(const iter_impl& other) const @@ -11468,7 +11502,7 @@ class iter_impl } /*! - @brief access to successor + @brief access to successor @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference operator[](difference_type n) const @@ -11499,7 +11533,7 @@ class iter_impl } /*! - @brief return the key of an object iterator + @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ const typename object_t::key_type& key() const @@ -11515,7 +11549,7 @@ class iter_impl } /*! - @brief return the value of an iterator + @brief return the value of an iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference value() const @@ -25449,6 +25483,8 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_EXPLICIT // #include + + #undef JSON_HEDLEY_ALWAYS_INLINE #undef JSON_HEDLEY_ARM_VERSION #undef JSON_HEDLEY_ARM_VERSION_CHECK diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 1a4f8ed754..07d243a818 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -135,7 +135,7 @@ TEST_CASE("lexer class") // store scan() result const auto res = scan_string(s.c_str()); - CAPTURE(s); + CAPTURE(s) switch (c) { diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index d0335c9484..2df07d6d44 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -509,7 +509,7 @@ TEST_CASE("parser class") CHECK(parser_helper("\"€\"").get() == "€"); CHECK(parser_helper("\"🎈\"").get() == "🎈"); - CHECK(parser_helper("\"\\ud80c\\udc60\"").get() == u8"\U00013060"); + CHECK(parser_helper("\"\\ud80c\\udc60\"").get() == "\xf0\x93\x81\xa0"); CHECK(parser_helper("\"\\ud83c\\udf1e\"").get() == "🌞"); } } diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 0d5baa409d..6de003d806 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1761,3 +1761,11 @@ TEST_CASE("std::optional") } } #endif + +#ifdef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_17 +#endif + +#ifdef JSON_HAS_CPP_14 + #undef JSON_HAS_CPP_14 +#endif diff --git a/test/src/unit-items.cpp b/test/src/unit-items.cpp index 10621ce7e9..4caf76f237 100644 --- a/test/src/unit-items.cpp +++ b/test/src/unit-items.cpp @@ -1448,3 +1448,11 @@ TEST_CASE("items()") } } } + +#ifdef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_17 +#endif + +#ifdef JSON_HAS_CPP_14 + #undef JSON_HAS_CPP_14 +#endif diff --git a/test/src/unit-regression1.cpp b/test/src/unit-regression1.cpp index 9dcc75b092..df660ddb4b 100644 --- a/test/src/unit-regression1.cpp +++ b/test/src/unit-regression1.cpp @@ -400,7 +400,7 @@ TEST_CASE("regression tests 1") SECTION("issue #146 - character following a surrogate pair is skipped") { - CHECK(json::parse("\"\\ud80c\\udc60abc\"").get() == u8"\U00013060abc"); + CHECK(json::parse("\"\\ud80c\\udc60abc\"").get() == "\xf0\x93\x81\xa0\x61\x62\x63"); } SECTION("issue #171 - Cannot index by key of type static constexpr const char*") diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index ca50cdd41d..1e8c4922a7 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -51,6 +51,10 @@ using nlohmann::json; #include #endif +#ifdef JSON_HAS_CPP_20 + #include +#endif + ///////////////////////////////////////////////////////////////////// // for #1021 ///////////////////////////////////////////////////////////////////// @@ -484,4 +488,14 @@ TEST_CASE("regression tests 2") json j = json::parse(ss, nullptr, true, true); CHECK(j.dump() == "{}"); } + +#ifdef JSON_HAS_CPP_20 + SECTION("issue #2546 - parsing containers of std::byte") + { + const char DATA[] = R"("Hello, world!")"; + const auto s = std::as_bytes(std::span(DATA)); + json j = json::parse(s); + CHECK(j.dump() == "\"Hello, world!\""); + } +#endif } diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 7f74ac5f8b..b237655056 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -112,13 +112,13 @@ static void to_json(BasicJsonType& j, country c) switch (c) { case country::china: - j = u8"中华人民共和国"; + j = "中华人民共和国"; return; case country::france: j = "France"; return; case country::russia: - j = u8"Российская Федерация"; + j = "Российская Федерация"; return; default: break; @@ -201,9 +201,9 @@ static void from_json(const BasicJsonType& j, country& c) const auto str = j.template get(); static const std::map m = { - {u8"中华人民共和国", country::china}, + {"中华人民共和国", country::china}, {"France", country::france}, - {u8"Российская Федерация", country::russia} + {"Российская Федерация", country::russia} }; const auto it = m.find(str); @@ -248,7 +248,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) const udt::name n{"theo"}; const udt::country c{udt::country::france}; const udt::person sfinae_addict{a, n, c}; - const udt::person senior_programmer{{42}, {u8"王芳"}, udt::country::china}; + const udt::person senior_programmer{{42}, {"王芳"}, udt::country::china}; const udt::address addr{"Paris"}; const udt::contact cpp_programmer{sfinae_addict, addr}; const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}}; @@ -265,14 +265,14 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK( json(book) == - u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); + R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); } SECTION("conversion from json via free-functions") { const auto big_json = - u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; + R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; SECTION("via explicit calls to get") { const auto parsed_book = big_json.get(); diff --git a/test/src/unit-udt_macro.cpp b/test/src/unit-udt_macro.cpp index b56a5d15e2..a13ac006b3 100644 --- a/test/src/unit-udt_macro.cpp +++ b/test/src/unit-udt_macro.cpp @@ -106,7 +106,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, met class person_with_private_alphabet { public: - bool operator==(const person_with_private_alphabet& other) + bool operator==(const person_with_private_alphabet& other) const { return a == other.a && b == other.b && @@ -169,7 +169,7 @@ class person_with_private_alphabet class person_with_public_alphabet { public: - bool operator==(const person_with_public_alphabet& other) + bool operator==(const person_with_public_alphabet& other) const { return a == other.a && b == other.b && diff --git a/test/src/unit-user_defined_input.cpp b/test/src/unit-user_defined_input.cpp index 5a1138b004..4b84e8e71c 100644 --- a/test/src/unit-user_defined_input.cpp +++ b/test/src/unit-user_defined_input.cpp @@ -63,7 +63,7 @@ const char* end(const MyContainer& c) return c.data + strlen(c.data); } -TEST_CASE("Custom container") +TEST_CASE("Custom container non-member begin/end") { MyContainer data{"[1,2,3,4]"}; @@ -75,6 +75,31 @@ TEST_CASE("Custom container") } +TEST_CASE("Custom container member begin/end") +{ + struct MyContainer2 + { + const char* data; + + const char* begin() const + { + return data; + } + + const char* end() const + { + return data + strlen(data); + } + }; + + MyContainer2 data{"[1,2,3,4]"}; + json as_json = json::parse(data); + CHECK(as_json.at(0) == 1); + CHECK(as_json.at(1) == 2); + CHECK(as_json.at(2) == 3); + CHECK(as_json.at(3) == 4); +} + TEST_CASE("Custom iterator") { const char* raw_data = "[1,2,3,4]";