]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/json/detail/value_from.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / json / detail / value_from.hpp
CommitLineData
20effc67
TL
1//
2// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4//
5// Distributed under the Boost Software License, Version 1.0. (See accompanying
6// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7//
8// Official repository: https://github.com/boostorg/json
9//
10
11#ifndef BOOST_JSON_DETAIL_VALUE_FROM_HPP
12#define BOOST_JSON_DETAIL_VALUE_FROM_HPP
13
14#include <boost/json/storage_ptr.hpp>
15#include <boost/json/value.hpp>
16#include <boost/json/detail/value_traits.hpp>
17
18BOOST_JSON_NS_BEGIN
19
20struct value_from_tag { };
21
22template<class T, class = void>
23struct has_value_from;
24
25namespace detail {
26
27// The integral_constant parameter here is an
28// rvalue reference to make the standard conversion
29// sequence to that parameter better, see
30// http://eel.is/c++draft/over.ics.rank#3.2.6
31template<std::size_t N, class T>
32void
33tuple_to_array(
34 T&&,
35 array&,
36 std::integral_constant<std::size_t, N>&&)
37{
38}
39
40template<std::size_t N, std::size_t I, class T>
41void
42tuple_to_array(
43 T&& t,
44 array& arr,
45 const std::integral_constant<std::size_t, I>&)
46{
47 using std::get;
48 arr.emplace_back(value_from(
49 get<I>(std::forward<T>(t)), arr.storage()));
50 return detail::tuple_to_array<N>(std::forward<T>(t),
51 arr, std::integral_constant<std::size_t, I + 1>());
52}
53
54//----------------------------------------------------------
55// Native conversion
56
57template<class T, typename std::enable_if<
58 detail::value_constructible<T>::value>::type* = nullptr>
59void
60tag_invoke(
61 value_from_tag,
62 value& jv,
63 T&& from)
64{
65 jv = std::forward<T>(from);
66}
67
68template<class T, typename std::enable_if<
69 std::is_same<detail::remove_cvref<T>,
70 std::nullptr_t>::value>::type* = nullptr>
71void
72tag_invoke(
73 value_from_tag,
74 value& jv,
75 T&&)
76{
77 // do nothing
78 BOOST_ASSERT(jv.is_null());
79 (void)jv;
80}
81
82//----------------------------------------------------------
83// Generic conversions
84
85// string-like types
86// NOTE: original check for size used is_convertible but
87// MSVC-140 selects wrong specialisation if used
88template<class T, typename std::enable_if<
89 std::is_constructible<remove_cvref<T>, const char*, std::size_t>::value &&
90 std::is_convertible<decltype(std::declval<T&>().data()), const char*>::value &&
91 std::is_integral<decltype(std::declval<T&>().size())>::value
92>::type* = nullptr>
93void
94value_from_generic(
95 value& jv,
96 T&& from,
97 priority_tag<3>)
98{
99 jv.emplace_string().assign(
100 from.data(), from.size());
101}
102
103// tuple-like types
104template<class T, typename std::enable_if<
105 (std::tuple_size<remove_cvref<T>>::value > 0)>::type* = nullptr>
106void
107value_from_generic(
108 value& jv,
109 T&& from,
110 priority_tag<2>)
111{
112 constexpr std::size_t n =
113 std::tuple_size<remove_cvref<T>>::value;
114 array& arr = jv.emplace_array();
115 arr.reserve(n);
116 detail::tuple_to_array<n>(std::forward<T>(from),
117 arr, std::integral_constant<std::size_t, 0>());
118}
119
120// map-like types
121template<class T, typename std::enable_if<
122 map_traits<T>::has_unique_keys &&
123 has_value_from<typename map_traits<T>::pair_value_type>::value &&
124 std::is_convertible<typename map_traits<T>::pair_key_type,
125 string_view>::value>::type* = nullptr>
126void
127value_from_generic(
128 value& jv,
129 T&& from,
130 priority_tag<1>)
131{
132 using std::get;
133 object& obj = jv.emplace_object();
134 obj.reserve(container_traits<T>::try_size(from));
135 for (auto&& elem : from)
136 obj.emplace(get<0>(elem), value_from(
137 get<1>(elem), obj.storage()));
138}
139
140// all other containers
141template<class T, typename std::enable_if<
142 has_value_from<typename container_traits<T>::
143 value_type>::value>::type* = nullptr>
144void
145value_from_generic(
146 value& jv,
147 T&& from,
148 priority_tag<0>)
149{
150 array& result = jv.emplace_array();
151 result.reserve(container_traits<T>::try_size(from));
152 for (auto&& elem : from)
153 result.emplace_back(
154 value_from(elem, result.storage()));
155}
156
157template<class T, void_t<typename std::enable_if<
158 ! detail::value_constructible<T>::value && ! std::is_same<
159 detail::remove_cvref<T>, std::nullptr_t>::value>::type,
160 decltype(detail::value_from_generic(std::declval<value&>(),
161 std::declval<T&&>(), priority_tag<3>()))>* = nullptr>
162void
163tag_invoke(
164 value_from_tag,
165 value& jv,
166 T&& from)
167{
168 detail::value_from_generic(jv,
169 std::forward<T>(from), priority_tag<3>());
170}
171
172//----------------------------------------------------------
173
174// Calls to value_from are forwarded to this function
175// so we can use ADL and hide the built-in tag_invoke
176// overloads in the detail namespace
177template<class T, void_t<
178 decltype(tag_invoke(std::declval<value_from_tag&>(),
179 std::declval<value&>(), std::declval<T&&>()))>* = nullptr>
180value
181value_from_impl(
182 T&& from,
183 storage_ptr sp)
184{
185 value jv(std::move(sp));
186 tag_invoke(value_from_tag(), jv, std::forward<T>(from));
187 return jv;
188}
189
190} // detail
191BOOST_JSON_NS_END
192
193#endif