value_ref.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. //
  2. // Copyright (c) 2019 Vinnie Falco ([email protected])
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/json
  8. //
  9. #ifndef BOOST_JSON_VALUE_REF_HPP
  10. #define BOOST_JSON_VALUE_REF_HPP
  11. #include <boost/json/detail/config.hpp>
  12. #include <boost/json/storage_ptr.hpp>
  13. #include <boost/json/string.hpp>
  14. #include <initializer_list>
  15. #include <type_traits>
  16. #include <utility>
  17. namespace boost {
  18. namespace json {
  19. #ifndef BOOST_JSON_DOCS
  20. class value;
  21. class object;
  22. class array;
  23. class string;
  24. #endif
  25. //----------------------------------------------------------
  26. /** The type used in initializer lists.
  27. This type is used in initializer lists for
  28. lazy construction of and assignment to the
  29. container types @ref value, @ref array,
  30. and @ref object. The two types of initializer
  31. lists used are:
  32. @li `std::initializer_list< value_ref >` for
  33. constructing or assigning a @ref value or
  34. @ref array, and
  35. @li `std::initializer_list< std::pair< string_view, value_ref > >`
  36. for constructing or assigning an @ref object.
  37. A `value_ref` uses reference semantics. Creation of the actual container
  38. from the initializer list is lazily deferred until the list is used. This
  39. means that the `boost::container::pmr::memory_resource` used to construct a
  40. container can be specified after the point where the initializer list is
  41. specified.
  42. @par Example
  43. This example demonstrates how a user-defined type
  44. containing a JSON value can be constructed from
  45. an initializer list:
  46. @code
  47. class my_type
  48. {
  49. value jv_;
  50. public:
  51. my_type( std::initializer_list< value_ref > init )
  52. : jv_(init)
  53. {
  54. }
  55. };
  56. @endcode
  57. @note Never declare a variable of type
  58. `std::initializer_list` except in function
  59. parameter lists, otherwise the behavior may
  60. be undefined.
  61. @see
  62. @ref value,
  63. @ref array,
  64. @ref object
  65. */
  66. class value_ref
  67. {
  68. friend class value;
  69. friend class object;
  70. friend class array;
  71. friend class value_ref_test;
  72. enum class what
  73. {
  74. str,
  75. ini,
  76. func,
  77. cfunc,
  78. strfunc,
  79. };
  80. using init_list =
  81. std::initializer_list<value_ref>;
  82. struct func_type
  83. {
  84. value(*f)(void*, storage_ptr);
  85. void* p;
  86. };
  87. struct cfunc_type
  88. {
  89. value(*f)(void const*, storage_ptr);
  90. void const* p;
  91. };
  92. union arg_type
  93. {
  94. string_view str_;
  95. init_list init_list_;
  96. signed char schar_;
  97. short short_;
  98. int int_;
  99. long long_;
  100. long long long_long_;
  101. unsigned char uchar_;
  102. unsigned short ushort_;
  103. unsigned int uint_;
  104. unsigned long ulong_;
  105. unsigned long long ulong_long_;
  106. float float_;
  107. double double_;
  108. bool bool_;
  109. std::nullptr_t nullptr_;
  110. arg_type() {}
  111. explicit arg_type(string_view t) noexcept : str_(t) {}
  112. explicit arg_type(init_list t) noexcept : init_list_(t) {}
  113. explicit arg_type(signed char t) noexcept : schar_(t) {}
  114. explicit arg_type(short t) noexcept : short_(t) {}
  115. explicit arg_type(int t) noexcept : int_(t) {}
  116. explicit arg_type(long t) noexcept : long_(t) {}
  117. explicit arg_type(long long t) noexcept : long_long_(t) {}
  118. explicit arg_type(unsigned char t) noexcept : uchar_(t) {}
  119. explicit arg_type(unsigned short t) noexcept : ushort_(t) {}
  120. explicit arg_type(unsigned int t) noexcept : uint_(t) {}
  121. explicit arg_type(unsigned long t) noexcept : ulong_(t) {}
  122. explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {}
  123. explicit arg_type(float t) noexcept : float_(t) {}
  124. explicit arg_type(double t) noexcept : double_(t) {}
  125. explicit arg_type(bool t) noexcept : bool_(t) {}
  126. explicit arg_type(std::nullptr_t) noexcept : nullptr_() {}
  127. };
  128. arg_type arg_;
  129. #ifndef BOOST_JSON_DOCS
  130. // VFALCO doc toolchain erroneously
  131. // displays private, anonymous unions as public
  132. union
  133. {
  134. func_type f_;
  135. cfunc_type cf_;
  136. };
  137. #endif
  138. what what_;
  139. public:
  140. /// Constructor
  141. value_ref(
  142. value_ref const&) = default;
  143. /// Constructor
  144. #ifdef BOOST_JSON_DOCS
  145. value_ref(string_view s) noexcept;
  146. #else
  147. template<
  148. class T
  149. ,class = typename
  150. std::enable_if<
  151. std::is_constructible<
  152. string_view, T>::value>::type
  153. >
  154. value_ref(
  155. T const& t) noexcept
  156. : arg_(string_view(t))
  157. , what_(what::str)
  158. {
  159. }
  160. #endif
  161. /// Constructor
  162. template<class T>
  163. value_ref(
  164. T const& t
  165. #ifndef BOOST_JSON_DOCS
  166. ,typename std::enable_if<
  167. ! std::is_constructible<
  168. string_view, T>::value &&
  169. ! std::is_same<bool, T>::value
  170. >::type* = 0
  171. #endif
  172. ) noexcept
  173. : cf_{&from_const<T>, &t}
  174. , what_(what::cfunc)
  175. {
  176. }
  177. /// Constructor
  178. template<class T>
  179. value_ref(
  180. T&& t
  181. #ifndef BOOST_JSON_DOCS
  182. ,typename std::enable_if<
  183. (! std::is_constructible<
  184. string_view, T>::value ||
  185. std::is_same<string, T>::value) &&
  186. ! std::is_same<bool,
  187. detail::remove_cvref<T>>::value &&
  188. std::is_same<T, detail::remove_cvref<T>>
  189. ::value>::type* = 0
  190. #endif
  191. ) noexcept
  192. : f_{&from_rvalue<
  193. detail::remove_cvref<T>>, &t}
  194. , what_(std::is_same<string, T>::value ?
  195. what::strfunc : what::func)
  196. {
  197. }
  198. /// Constructor
  199. #ifdef BOOST_JSON_DOCS
  200. value_ref(bool b) noexcept;
  201. #else
  202. template<
  203. class T
  204. ,class = typename std::enable_if<
  205. std::is_same<T, bool>::value>::type
  206. >
  207. value_ref(
  208. T b) noexcept
  209. : arg_(b)
  210. , cf_{&from_builtin<bool>, &arg_.bool_}
  211. , what_(what::cfunc)
  212. {
  213. }
  214. #endif
  215. /// Constructor
  216. value_ref(
  217. std::initializer_list<
  218. value_ref> t) noexcept
  219. : arg_(t)
  220. , what_(what::ini)
  221. {
  222. }
  223. /// Constructor
  224. value_ref(signed char t) noexcept
  225. : arg_(t)
  226. , cf_{&from_builtin<signed char>, &arg_.schar_}
  227. , what_(what::cfunc)
  228. {
  229. }
  230. /// Constructor
  231. value_ref(short t) noexcept
  232. : arg_(t)
  233. , cf_{&from_builtin<short>, &arg_.short_}
  234. , what_(what::cfunc)
  235. {
  236. }
  237. /// Constructor
  238. value_ref(int t) noexcept
  239. : arg_(t)
  240. , cf_{&from_builtin<int>, &arg_.int_}
  241. , what_(what::cfunc)
  242. {
  243. }
  244. /// Constructor
  245. value_ref(long t) noexcept
  246. : arg_(t)
  247. , cf_{&from_builtin<
  248. long>, &arg_.long_}
  249. , what_(what::cfunc)
  250. {
  251. }
  252. /// Constructor
  253. value_ref(long long t) noexcept
  254. : arg_(t)
  255. , cf_{&from_builtin<
  256. long long>, &arg_.long_long_}
  257. , what_(what::cfunc)
  258. {
  259. }
  260. /// Constructor
  261. value_ref(unsigned char t) noexcept
  262. : arg_(t)
  263. , cf_{&from_builtin<
  264. unsigned char>, &arg_.uchar_}
  265. , what_(what::cfunc)
  266. {
  267. }
  268. /// Constructor
  269. value_ref(unsigned short t) noexcept
  270. : arg_(t)
  271. , cf_{&from_builtin<
  272. unsigned short>, &arg_.ushort_}
  273. , what_(what::cfunc)
  274. {
  275. }
  276. /// Constructor
  277. value_ref(unsigned int t) noexcept
  278. : arg_(t)
  279. , cf_{&from_builtin<
  280. unsigned int>, &arg_.uint_}
  281. , what_(what::cfunc)
  282. {
  283. }
  284. /// Constructor
  285. value_ref(unsigned long t) noexcept
  286. : arg_(t)
  287. , cf_{&from_builtin<
  288. unsigned long>, &arg_.ulong_}
  289. , what_(what::cfunc)
  290. {
  291. }
  292. /// Constructor
  293. value_ref(unsigned long long t) noexcept
  294. : arg_(t)
  295. , cf_{&from_builtin<
  296. unsigned long long>, &arg_.ulong_long_}
  297. , what_(what::cfunc)
  298. {
  299. }
  300. /// Constructor
  301. value_ref(float t) noexcept
  302. : arg_(t)
  303. , cf_{&from_builtin<
  304. float>, &arg_.float_}
  305. , what_(what::cfunc)
  306. {
  307. }
  308. /// Constructor
  309. value_ref(double t) noexcept
  310. : arg_(t)
  311. , cf_{&from_builtin<
  312. double>, &arg_.double_}
  313. , what_(what::cfunc)
  314. {
  315. }
  316. /// Constructor
  317. value_ref(std::nullptr_t) noexcept
  318. : arg_(nullptr)
  319. , cf_{&from_builtin<
  320. std::nullptr_t>, &arg_.nullptr_}
  321. , what_(what::cfunc)
  322. {
  323. }
  324. #ifndef BOOST_JSON_DOCS
  325. // Not public
  326. //private:
  327. // VFALCO Why is this needed?
  328. /** Operator conversion to @ref value
  329. This allows creation of a @ref value from
  330. an initializer list element.
  331. */
  332. BOOST_JSON_DECL
  333. operator value() const;
  334. #endif
  335. private:
  336. template<class T>
  337. static
  338. value
  339. from_builtin(
  340. void const* p,
  341. storage_ptr sp) noexcept;
  342. template<class T>
  343. static
  344. value
  345. from_const(
  346. void const* p,
  347. storage_ptr sp);
  348. template<class T>
  349. static
  350. value
  351. from_rvalue(
  352. void* p,
  353. storage_ptr sp);
  354. static
  355. BOOST_JSON_DECL
  356. value
  357. from_init_list(
  358. void const* p,
  359. storage_ptr sp);
  360. inline
  361. bool
  362. is_key_value_pair() const noexcept;
  363. static
  364. inline
  365. bool
  366. maybe_object(
  367. std::initializer_list<
  368. value_ref> init) noexcept;
  369. inline
  370. string_view
  371. get_string() const noexcept;
  372. BOOST_JSON_DECL
  373. value
  374. make_value(
  375. storage_ptr sp) const;
  376. BOOST_JSON_DECL
  377. static
  378. value
  379. make_value(
  380. std::initializer_list<
  381. value_ref> init,
  382. storage_ptr sp);
  383. BOOST_JSON_DECL
  384. static
  385. object
  386. make_object(
  387. std::initializer_list<value_ref> init,
  388. storage_ptr sp);
  389. BOOST_JSON_DECL
  390. static
  391. array
  392. make_array(
  393. std::initializer_list<
  394. value_ref> init,
  395. storage_ptr sp);
  396. BOOST_JSON_DECL
  397. static
  398. void
  399. write_array(
  400. value* dest,
  401. std::initializer_list<
  402. value_ref> init,
  403. storage_ptr const& sp);
  404. };
  405. } // namespace json
  406. } // namespace boost
  407. // Must be included here for this file to stand alone
  408. #include <boost/json/value.hpp>
  409. // includes are at the bottom of <boost/json/value.hpp>
  410. //#include <boost/json/impl/value.hpp>
  411. //#include <boost/json/impl/value.ipp>
  412. #endif