// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/json // #ifndef BOOST_JSON_DETAIL_VALUE_FROM_HPP #define BOOST_JSON_DETAIL_VALUE_FROM_HPP #include #include #include BOOST_JSON_NS_BEGIN struct value_from_tag { }; template struct has_value_from; namespace detail { // The integral_constant parameter here is an // rvalue reference to make the standard conversion // sequence to that parameter better, see // http://eel.is/c++draft/over.ics.rank#3.2.6 template void tuple_to_array( T&&, array&, std::integral_constant&&) { } template void tuple_to_array( T&& t, array& arr, const std::integral_constant&) { using std::get; arr.emplace_back(value_from( get(std::forward(t)), arr.storage())); return detail::tuple_to_array(std::forward(t), arr, std::integral_constant()); } //---------------------------------------------------------- // User-provided conversion template(), std::declval()))>* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<5>) { tag_invoke(value_from_tag(), jv, std::forward(from)); } //---------------------------------------------------------- // Native conversion template::value>::type* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<4>) { jv = std::forward(from); } template, std::nullptr_t>::value>::type* = nullptr> void value_from_helper( value& jv, T&&, priority_tag<4>) { // do nothing BOOST_ASSERT(jv.is_null()); (void)jv; } //---------------------------------------------------------- // Generic conversions // string-like types // NOTE: original check for size used is_convertible but // MSVC-140 selects wrong specialisation if used template, const char*, std::size_t>::value && std::is_convertible().data()), const char*>::value && std::is_integral().size())>::value >::type* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<3>) { jv.emplace_string().assign( from.data(), from.size()); } // tuple-like types template>::value > 0)>::type* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<2>) { constexpr std::size_t n = std::tuple_size>::value; array& arr = jv.emplace_array(); arr.reserve(n); detail::tuple_to_array(std::forward(from), arr, std::integral_constant()); } // map-like types template::has_unique_keys && has_value_from::pair_value_type>::value && std::is_convertible::pair_key_type, string_view>::value>::type* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<1>) { using std::get; object& obj = jv.emplace_object(); obj.reserve(container_traits::try_size(from)); for (auto&& elem : from) obj.emplace(get<0>(elem), value_from( get<1>(elem), obj.storage())); } // all other containers template:: value_type>::value>::type* = nullptr> void value_from_helper( value& jv, T&& from, priority_tag<0>) { array& result = jv.emplace_array(); result.reserve(container_traits::try_size(from)); for (auto&& elem : from) result.emplace_back( value_from(elem, result.storage())); } //---------------------------------------------------------- // Calls to value_from are forwarded to this function // so we can use ADL and hide the built-in tag_invoke // overloads in the detail namespace template(), std::declval(), priority_tag<5>()))>> value value_from_impl( T&& from, storage_ptr sp) { value jv(std::move(sp)); detail::value_from_helper(jv, std::forward(from), priority_tag<5>()); return jv; } } // detail BOOST_JSON_NS_END #endif