// // 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_TO_HPP #define BOOST_JSON_DETAIL_VALUE_TO_HPP #include #include #include BOOST_JSON_NS_BEGIN template struct value_to_tag { }; template struct has_value_to; template::value && std::is_same::value>::type> T value_to(U const&); namespace detail { //---------------------------------------------------------- // Use native conversion // identity conversion inline value tag_invoke( value_to_tag, value const& jv) { return jv; } // object inline object tag_invoke( value_to_tag, value const& jv) { return jv.as_object(); } // array inline array tag_invoke( value_to_tag, value const& jv) { return jv.as_array(); } // string inline string tag_invoke( value_to_tag, value const& jv) { return jv.as_string(); } // bool inline bool tag_invoke( value_to_tag, value const& jv) { return jv.as_bool(); } // integral and floating point template::value>::type* = nullptr> T tag_invoke( value_to_tag, value const& jv) { return jv.to_number(); } //---------------------------------------------------------- // Use generic conversion // string-like types // NOTE: original check for size used is_convertible but // MSVC-140 selects wrong specialisation if used template::value && std::is_convertible().data()), const char*>::value && std::is_integral().size())>::value >::type* = nullptr> T value_to_generic( const value& jv, priority_tag<2>) { auto& str = jv.as_string(); return T(str.data(), str.size()); } // map like containers template::pair_value_type>::value && std::is_constructible::pair_key_type, string_view>::value>::type* = nullptr> T value_to_generic( const value& jv, priority_tag<1>) { using value_type = typename container_traits::value_type; const object& obj = jv.as_object(); T result; container_traits::try_reserve( result, obj.size()); for (const auto& val : obj) result.insert(value_type{typename map_traits:: pair_key_type(val.key()), value_to::pair_value_type>(val.value())}); return result; } // all other containers template:: value_type>::value>::type* = nullptr> T value_to_generic( const value& jv, priority_tag<0>) { const array& arr = jv.as_array(); T result; container_traits::try_reserve( result, arr.size()); for (const auto& val : arr) result.insert(end(result), value_to::value_type>(val)); return result; } // Matches containers template::value && !std::is_arithmetic::value>::type, decltype( value_to_generic(std::declval(), priority_tag<2>()))>* = nullptr> T tag_invoke( value_to_tag, value const& jv) { return value_to_generic( jv, priority_tag<2>()); } //---------------------------------------------------------- // Calls to value_to 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()))>* = nullptr> T value_to_impl( value_to_tag tag, value const& jv) { return tag_invoke(tag, jv); } } // detail BOOST_JSON_NS_END #endif