Unverified Commit 0e694b40 authored by Théo DELRIEU's avatar Théo DELRIEU Committed by GitHub

fix std::filesystem::path regression (#3073)

* meta: rework is_compatible/is_constructible_string_type

These type traits performed an incorrect and insufficient check.

Converting to a std::filesystem::path used to work by accident thanks to
these brittle constraints, but the clean-up performed in #3020 broke them.

* support std::filesystem::path

Fixes #3070
parent 4b1cb9ee
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann namespace nlohmann
{ {
namespace detail namespace detail
...@@ -444,6 +448,18 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE ...@@ -444,6 +448,18 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
} }
} }
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, std::filesystem::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
#endif
struct from_json_fn struct from_json_fn
{ {
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
......
...@@ -9,11 +9,16 @@ ...@@ -9,11 +9,16 @@
#include <valarray> // valarray #include <valarray> // valarray
#include <vector> // vector #include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp> #include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann namespace nlohmann
{ {
namespace detail namespace detail
...@@ -386,6 +391,14 @@ void to_json(BasicJsonType& j, const T& t) ...@@ -386,6 +391,14 @@ void to_json(BasicJsonType& j, const T& t)
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
} }
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void to_json(BasicJsonType& j, const std::filesystem::path& p)
{
j = p.string();
}
#endif
struct to_json_fn struct to_json_fn
{ {
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
......
...@@ -309,44 +309,21 @@ struct is_constructible_object_type ...@@ -309,44 +309,21 @@ struct is_constructible_object_type
: is_constructible_object_type_impl<BasicJsonType, : is_constructible_object_type_impl<BasicJsonType,
ConstructibleObjectType> {}; ConstructibleObjectType> {};
template<typename BasicJsonType, typename CompatibleStringType,
typename = void>
struct is_compatible_string_type_impl : std::false_type {};
template<typename BasicJsonType, typename CompatibleStringType> template<typename BasicJsonType, typename CompatibleStringType>
struct is_compatible_string_type_impl < struct is_compatible_string_type
BasicJsonType, CompatibleStringType,
enable_if_t<is_detected_convertible<typename BasicJsonType::string_t::value_type,
range_value_t,
CompatibleStringType>::value >>
{ {
static constexpr auto value = static constexpr auto value =
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
}; };
template<typename BasicJsonType, typename ConstructibleStringType> template<typename BasicJsonType, typename ConstructibleStringType>
struct is_compatible_string_type struct is_constructible_string_type
: is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
template<typename BasicJsonType, typename ConstructibleStringType,
typename = void>
struct is_constructible_string_type_impl : std::false_type {};
template<typename BasicJsonType, typename ConstructibleStringType>
struct is_constructible_string_type_impl <
BasicJsonType, ConstructibleStringType,
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
value_type_t, ConstructibleStringType>::value >>
{ {
static constexpr auto value = static constexpr auto value =
is_constructible<ConstructibleStringType, is_constructible<ConstructibleStringType,
typename BasicJsonType::string_t>::value; typename BasicJsonType::string_t>::value;
}; };
template<typename BasicJsonType, typename ConstructibleStringType>
struct is_constructible_string_type
: is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
template<typename BasicJsonType, typename CompatibleArrayType, typename = void> template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
struct is_compatible_array_type_impl : std::false_type {}; struct is_compatible_array_type_impl : std::false_type {};
...@@ -355,7 +332,10 @@ struct is_compatible_array_type_impl < ...@@ -355,7 +332,10 @@ struct is_compatible_array_type_impl <
BasicJsonType, CompatibleArrayType, BasicJsonType, CompatibleArrayType,
enable_if_t < enable_if_t <
is_detected<iterator_t, CompatibleArrayType>::value&& is_detected<iterator_t, CompatibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value >> is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
{ {
static constexpr bool value = static constexpr bool value =
is_constructible<BasicJsonType, is_constructible<BasicJsonType,
...@@ -388,8 +368,11 @@ struct is_constructible_array_type_impl < ...@@ -388,8 +368,11 @@ struct is_constructible_array_type_impl <
is_detected<iterator_t, ConstructibleArrayType>::value&& is_detected<iterator_t, ConstructibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
is_detected<range_value_t, ConstructibleArrayType>::value&& is_detected<range_value_t, ConstructibleArrayType>::value&&
is_complete_type < // special case for types like std::filesystem::path whose iterator's value_type are themselves
detected_t<range_value_t, ConstructibleArrayType >>::value >> // c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
is_complete_type <
detected_t<range_value_t, ConstructibleArrayType >>::value >>
{ {
using value_type = range_value_t<ConstructibleArrayType>; using value_type = range_value_t<ConstructibleArrayType>;
......
...@@ -3783,44 +3783,21 @@ struct is_constructible_object_type ...@@ -3783,44 +3783,21 @@ struct is_constructible_object_type
: is_constructible_object_type_impl<BasicJsonType, : is_constructible_object_type_impl<BasicJsonType,
ConstructibleObjectType> {}; ConstructibleObjectType> {};
template<typename BasicJsonType, typename CompatibleStringType,
typename = void>
struct is_compatible_string_type_impl : std::false_type {};
template<typename BasicJsonType, typename CompatibleStringType> template<typename BasicJsonType, typename CompatibleStringType>
struct is_compatible_string_type_impl < struct is_compatible_string_type
BasicJsonType, CompatibleStringType,
enable_if_t<is_detected_convertible<typename BasicJsonType::string_t::value_type,
range_value_t,
CompatibleStringType>::value >>
{ {
static constexpr auto value = static constexpr auto value =
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
}; };
template<typename BasicJsonType, typename ConstructibleStringType> template<typename BasicJsonType, typename ConstructibleStringType>
struct is_compatible_string_type struct is_constructible_string_type
: is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
template<typename BasicJsonType, typename ConstructibleStringType,
typename = void>
struct is_constructible_string_type_impl : std::false_type {};
template<typename BasicJsonType, typename ConstructibleStringType>
struct is_constructible_string_type_impl <
BasicJsonType, ConstructibleStringType,
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
value_type_t, ConstructibleStringType>::value >>
{ {
static constexpr auto value = static constexpr auto value =
is_constructible<ConstructibleStringType, is_constructible<ConstructibleStringType,
typename BasicJsonType::string_t>::value; typename BasicJsonType::string_t>::value;
}; };
template<typename BasicJsonType, typename ConstructibleStringType>
struct is_constructible_string_type
: is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
template<typename BasicJsonType, typename CompatibleArrayType, typename = void> template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
struct is_compatible_array_type_impl : std::false_type {}; struct is_compatible_array_type_impl : std::false_type {};
...@@ -3829,7 +3806,10 @@ struct is_compatible_array_type_impl < ...@@ -3829,7 +3806,10 @@ struct is_compatible_array_type_impl <
BasicJsonType, CompatibleArrayType, BasicJsonType, CompatibleArrayType,
enable_if_t < enable_if_t <
is_detected<iterator_t, CompatibleArrayType>::value&& is_detected<iterator_t, CompatibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value >> is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
{ {
static constexpr bool value = static constexpr bool value =
is_constructible<BasicJsonType, is_constructible<BasicJsonType,
...@@ -3862,8 +3842,11 @@ struct is_constructible_array_type_impl < ...@@ -3862,8 +3842,11 @@ struct is_constructible_array_type_impl <
is_detected<iterator_t, ConstructibleArrayType>::value&& is_detected<iterator_t, ConstructibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
is_detected<range_value_t, ConstructibleArrayType>::value&& is_detected<range_value_t, ConstructibleArrayType>::value&&
is_complete_type < // special case for types like std::filesystem::path whose iterator's value_type are themselves
detected_t<range_value_t, ConstructibleArrayType >>::value >> // c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
is_complete_type <
detected_t<range_value_t, ConstructibleArrayType >>::value >>
{ {
using value_type = range_value_t<ConstructibleArrayType>; using value_type = range_value_t<ConstructibleArrayType>;
...@@ -3967,6 +3950,10 @@ T conditional_static_cast(U value) ...@@ -3967,6 +3950,10 @@ T conditional_static_cast(U value)
// #include <nlohmann/detail/value_t.hpp> // #include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann namespace nlohmann
{ {
namespace detail namespace detail
...@@ -4392,6 +4379,18 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE ...@@ -4392,6 +4379,18 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
} }
} }
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, std::filesystem::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
#endif
struct from_json_fn struct from_json_fn
{ {
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
...@@ -4425,6 +4424,8 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va ...@@ -4425,6 +4424,8 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
#include <valarray> // valarray #include <valarray> // valarray
#include <vector> // vector #include <vector> // vector
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/iterators/iteration_proxy.hpp> // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
...@@ -4625,6 +4626,10 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> ...@@ -4625,6 +4626,10 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
// #include <nlohmann/detail/value_t.hpp> // #include <nlohmann/detail/value_t.hpp>
#ifdef JSON_HAS_CPP_17
#include <filesystem>
#endif
namespace nlohmann namespace nlohmann
{ {
namespace detail namespace detail
...@@ -4997,6 +5002,14 @@ void to_json(BasicJsonType& j, const T& t) ...@@ -4997,6 +5002,14 @@ void to_json(BasicJsonType& j, const T& t)
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
} }
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType>
void to_json(BasicJsonType& j, const std::filesystem::path& p)
{
j = p.string();
}
#endif
struct to_json_fn struct to_json_fn
{ {
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
......
...@@ -37,8 +37,8 @@ SOFTWARE. ...@@ -37,8 +37,8 @@ SOFTWARE.
using json = nlohmann::json; using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json; using ordered_json = nlohmann::ordered_json;
#include <list>
#include <cstdio> #include <cstdio>
#include <list>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
...@@ -47,6 +47,7 @@ using ordered_json = nlohmann::ordered_json; ...@@ -47,6 +47,7 @@ using ordered_json = nlohmann::ordered_json;
#endif #endif
#ifdef JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17
#include <filesystem>
#include <variant> #include <variant>
#endif #endif
...@@ -69,14 +70,19 @@ using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool ...@@ -69,14 +70,19 @@ using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
namespace namespace
{ {
struct NonDefaultFromJsonStruct { }; struct NonDefaultFromJsonStruct
{};
inline bool operator== (NonDefaultFromJsonStruct const& /*unused*/, NonDefaultFromJsonStruct const& /*unused*/) inline bool operator==(NonDefaultFromJsonStruct const& /*unused*/, NonDefaultFromJsonStruct const& /*unused*/)
{ {
return true; return true;
} }
enum class for_1647 { one, two }; enum class for_1647
{
one,
two
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive
NLOHMANN_JSON_SERIALIZE_ENUM(for_1647, NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
...@@ -93,9 +99,12 @@ NLOHMANN_JSON_SERIALIZE_ENUM(for_1647, ...@@ -93,9 +99,12 @@ NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
struct Data struct Data
{ {
Data() = default; Data() = default;
Data(std::string a_, std::string b_) : a(std::move(a_)), b(std::move(b_)) {} Data(std::string a_, std::string b_)
std::string a {}; : a(std::move(a_))
std::string b {}; , b(std::move(b_))
{}
std::string a{};
std::string b{};
}; };
void from_json(const json& j, Data& data); void from_json(const json& j, Data& data);
...@@ -118,10 +127,10 @@ bool operator==(Data const& lhs, Data const& rhs) ...@@ -118,10 +127,10 @@ bool operator==(Data const& lhs, Data const& rhs)
namespace nlohmann namespace nlohmann
{ {
template <> template<>
struct adl_serializer<NonDefaultFromJsonStruct> struct adl_serializer<NonDefaultFromJsonStruct>
{ {
static NonDefaultFromJsonStruct from_json (json const& /*unused*/) noexcept static NonDefaultFromJsonStruct from_json(json const& /*unused*/) noexcept
{ {
return {}; return {};
} }
...@@ -138,23 +147,24 @@ struct NotSerializableData ...@@ -138,23 +147,24 @@ struct NotSerializableData
float myfloat; float myfloat;
}; };
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// for #2574 // for #2574
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
struct NonDefaultConstructible struct NonDefaultConstructible
{ {
explicit NonDefaultConstructible (int a) : x(a) { } explicit NonDefaultConstructible(int a)
: x(a)
{}
int x; int x;
}; };
namespace nlohmann namespace nlohmann
{ {
template <> template<>
struct adl_serializer<NonDefaultConstructible> struct adl_serializer<NonDefaultConstructible>
{ {
static NonDefaultConstructible from_json (json const& j) static NonDefaultConstructible from_json(json const& j)
{ {
return NonDefaultConstructible(j.get<int>()); return NonDefaultConstructible(j.get<int>());
} }
...@@ -168,7 +178,9 @@ struct adl_serializer<NonDefaultConstructible> ...@@ -168,7 +178,9 @@ struct adl_serializer<NonDefaultConstructible>
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json> class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
{ {
public: public:
explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser<json>(j, false) {} 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) static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
{ {
...@@ -296,9 +308,12 @@ TEST_CASE("regression tests 2") ...@@ -296,9 +308,12 @@ TEST_CASE("regression tests 2")
using it_type = decltype(p1.begin()); using it_type = decltype(p1.begin());
std::set_difference( std::set_difference(
p1.begin(), p1.end(), p1.begin(),
p2.begin(), p2.end(), p1.end(),
std::inserter(diffs, diffs.end()), [&](const it_type & e1, const it_type & e2) -> bool p2.begin(),
p2.end(),
std::inserter(diffs, diffs.end()),
[&](const it_type & e1, const it_type & e2) -> bool
{ {
using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
...@@ -311,7 +326,8 @@ TEST_CASE("regression tests 2") ...@@ -311,7 +326,8 @@ TEST_CASE("regression tests 2")
SECTION("issue #1292 - Serializing std::variant causes stack overflow") SECTION("issue #1292 - Serializing std::variant causes stack overflow")
{ {
static_assert( static_assert(
!std::is_constructible<json, std::variant<int, float>>::value, ""); !std::is_constructible<json, std::variant<int, float>>::value,
"");
} }
#endif #endif
...@@ -376,24 +392,7 @@ TEST_CASE("regression tests 2") ...@@ -376,24 +392,7 @@ TEST_CASE("regression tests 2")
nlohmann::json dump_test; nlohmann::json dump_test;
const std::array<int, 108> data = const std::array<int, 108> data =
{ {
{ {109, 108, 103, 125, -122, -53, 115, 18, 3, 0, 102, 19, 1, 15, -110, 13, -3, -1, -81, 32, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -80, 2, 0, 0, 96, -118, 46, -116, 46, 109, -84, -87, 108, 14, 109, -24, -83, 13, -18, -51, -83, -52, -115, 14, 6, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 3, 0, 0, 0, 35, -74, -73, 55, 57, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, -96, -54, -28, -26}
109, 108, 103, 125, -122, -53, 115,
18, 3, 0, 102, 19, 1, 15,
-110, 13, -3, -1, -81, 32, 2,
0, 0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -80, 2,
0, 0, 96, -118, 46, -116, 46,
109, -84, -87, 108, 14, 109, -24,
-83, 13, -18, -51, -83, -52, -115,
14, 6, 32, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
64, 3, 0, 0, 0, 35, -74,
-73, 55, 57, -128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 33, 0, 0, 0, -96,
-54, -28, -26
}
}; };
std::string s; std::string s;
for (int i : data) for (int i : data)
...@@ -453,7 +452,7 @@ TEST_CASE("regression tests 2") ...@@ -453,7 +452,7 @@ TEST_CASE("regression tests 2")
SECTION("string array") SECTION("string array")
{ {
const std::array<char, 2> input = {{ 'B', 0x00 }}; const std::array<char, 2> input = {{'B', 0x00}};
json cbor = json::from_cbor(input, true, false); json cbor = json::from_cbor(input, true, false);
CHECK(cbor.is_discarded()); CHECK(cbor.is_discarded());
} }
...@@ -495,8 +494,7 @@ TEST_CASE("regression tests 2") ...@@ -495,8 +494,7 @@ TEST_CASE("regression tests 2")
' ', // Indent char ' ', // Indent char
false, // Ensure ascii false, // Ensure ascii
json::error_handler_t::strict // Error json::error_handler_t::strict // Error
) ));
);
} }
SECTION("PR #2181 - regression bug with lvalue") SECTION("PR #2181 - regression bug with lvalue")
...@@ -512,7 +510,16 @@ TEST_CASE("regression tests 2") ...@@ -512,7 +510,16 @@ TEST_CASE("regression tests 2")
{ {
std::vector<uint8_t> data = std::vector<uint8_t> data =
{ {
0x7B, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x4F, 0x42 0x7B,
0x6F,
0x62,
0x6A,
0x65,
0x63,
0x74,
0x20,
0x4F,
0x42
}; };
json result = json::from_cbor(data, true, false); json result = json::from_cbor(data, true, false);
CHECK(result.is_discarded()); CHECK(result.is_discarded());
...@@ -562,11 +569,10 @@ TEST_CASE("regression tests 2") ...@@ -562,11 +569,10 @@ TEST_CASE("regression tests 2")
SECTION("std::array") SECTION("std::array")
{ {
{ {
json j = { 7, 4 }; json j = {7, 4};
auto arr = j.get<std::array<NonDefaultConstructible, 2>>(); auto arr = j.get<std::array<NonDefaultConstructible, 2>>();
CHECK(arr[0].x == 7); CHECK(arr[0].x == 7);
CHECK(arr[1].x == 4); CHECK(arr[1].x == 4);
} }
{ {
...@@ -578,21 +584,21 @@ TEST_CASE("regression tests 2") ...@@ -578,21 +584,21 @@ TEST_CASE("regression tests 2")
SECTION("std::pair") SECTION("std::pair")
{ {
{ {
json j = { 3, 8 }; json j = {3, 8};
auto p = j.get<std::pair<NonDefaultConstructible, NonDefaultConstructible>>(); auto p = j.get<std::pair<NonDefaultConstructible, NonDefaultConstructible>>();
CHECK(p.first.x == 3); CHECK(p.first.x == 3);
CHECK(p.second.x == 8); CHECK(p.second.x == 8);
} }
{ {
json j = { 4, 1 }; json j = {4, 1};
auto p = j.get<std::pair<int, NonDefaultConstructible>>(); auto p = j.get<std::pair<int, NonDefaultConstructible>>();
CHECK(p.first == 4); CHECK(p.first == 4);
CHECK(p.second.x == 1); CHECK(p.second.x == 1);
} }
{ {
json j = { 6, 7 }; json j = {6, 7};
auto p = j.get<std::pair<NonDefaultConstructible, int>>(); auto p = j.get<std::pair<NonDefaultConstructible, int>>();
CHECK(p.first.x == 6); CHECK(p.first.x == 6);
CHECK(p.second == 7); CHECK(p.second == 7);
...@@ -607,13 +613,13 @@ TEST_CASE("regression tests 2") ...@@ -607,13 +613,13 @@ TEST_CASE("regression tests 2")
SECTION("std::tuple") SECTION("std::tuple")
{ {
{ {
json j = { 9 }; json j = {9};
auto t = j.get<std::tuple<NonDefaultConstructible>>(); auto t = j.get<std::tuple<NonDefaultConstructible>>();
CHECK(std::get<0>(t).x == 9); CHECK(std::get<0>(t).x == 9);
} }
{ {
json j = { 9, 8, 7 }; json j = {9, 8, 7};
auto t = j.get<std::tuple<NonDefaultConstructible, int, NonDefaultConstructible>>(); auto t = j.get<std::tuple<NonDefaultConstructible, int, NonDefaultConstructible>>();
CHECK(std::get<0>(t).x == 9); CHECK(std::get<0>(t).x == 9);
CHECK(std::get<1>(t) == 8); CHECK(std::get<1>(t) == 8);
...@@ -658,7 +664,7 @@ TEST_CASE("regression tests 2") ...@@ -658,7 +664,7 @@ TEST_CASE("regression tests 2")
json j; json j;
sax_no_exception sax(j); sax_no_exception sax(j);
CHECK (!json::sax_parse("xyz", &sax)); 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'"); 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) delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
} }
...@@ -695,6 +701,17 @@ TEST_CASE("regression tests 2") ...@@ -695,6 +701,17 @@ TEST_CASE("regression tests 2")
json k = json::from_cbor(my_vector); json k = json::from_cbor(my_vector);
CHECK(j == k); CHECK(j == k);
} }
#ifdef JSON_HAS_CPP_17
SECTION("issue #3070 - Version 3.10.3 breaks backward-compatibility with 3.10.2 ")
{
std::filesystem::path text_path("/tmp/text.txt");
json j(text_path);
const auto j_path = j.get<std::filesystem::path>();
CHECK(j_path == text_path);
}
#endif
} }
DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_CLANG_SUPPRESS_WARNING_POP
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment