value_ref.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
  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. BOOST_JSON_NS_BEGIN
  18. #ifndef BOOST_JSON_DOCS
  19. class value;
  20. class object;
  21. class array;
  22. class string;
  23. #endif
  24. //----------------------------------------------------------
  25. /** The type used in initializer lists.
  26. This type is used in initializer lists for
  27. lazy construction of and assignment to the
  28. container types @ref value, @ref array,
  29. and @ref object. The two types of initializer
  30. lists used are:
  31. @li `std::initializer_list< value_ref >` for
  32. constructing or assigning a @ref value or
  33. @ref array, and
  34. @li `std::initializer_list< std::pair< string_view, value_ref > >`
  35. for constructing or assigning an @ref object.
  36. A `value_ref` uses reference semantics. Creation
  37. of the actual container from the initializer
  38. list is lazily deferred until the list is used.
  39. This means that the @ref memory_resource used to
  40. construct a container can be specified after the
  41. point where the initializer list is 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. template<class T>
  129. using is_builtin =
  130. std::integral_constant<bool,
  131. std::is_same<T, signed char>::value ||
  132. std::is_same<T, short>::value ||
  133. std::is_same<T, int>::value ||
  134. std::is_same<T, long>::value ||
  135. std::is_same<T, long long>::value ||
  136. std::is_same<T, unsigned char>::value ||
  137. std::is_same<T, unsigned short>::value ||
  138. std::is_same<T, unsigned int>::value ||
  139. std::is_same<T, unsigned long>::value ||
  140. std::is_same<T, unsigned long long>::value ||
  141. std::is_same<T, float>::value ||
  142. std::is_same<T, double>::value ||
  143. std::is_same<T, std::nullptr_t>::value>;
  144. arg_type arg_;
  145. #ifndef BOOST_JSON_DOCS
  146. // VFALCO doc toolchain erroneously
  147. // displays private, anonymous unions as public
  148. union
  149. {
  150. func_type f_;
  151. cfunc_type cf_;
  152. };
  153. #endif
  154. what what_;
  155. public:
  156. /// Constructor
  157. value_ref(
  158. value_ref const&) = default;
  159. /// Constructor
  160. #ifdef BOOST_JSON_DOCS
  161. value_ref(string_view s) noexcept;
  162. #else
  163. template<
  164. class T
  165. ,class = typename
  166. std::enable_if<
  167. std::is_constructible<
  168. string_view, T>::value>::type
  169. >
  170. value_ref(
  171. T const& t) noexcept
  172. : arg_(string_view(t))
  173. , what_(what::str)
  174. {
  175. }
  176. #endif
  177. /// Constructor
  178. template<class T>
  179. value_ref(
  180. T const& t
  181. #ifndef BOOST_JSON_DOCS
  182. ,typename std::enable_if<
  183. ! std::is_constructible<
  184. string_view, T>::value &&
  185. ! std::is_same<bool, T>::value
  186. >::type* = 0
  187. #endif
  188. ) noexcept
  189. : cf_{&from_const<T>, &t}
  190. , what_(what::cfunc)
  191. {
  192. }
  193. /// Constructor
  194. template<class T>
  195. value_ref(
  196. T&& t
  197. #ifndef BOOST_JSON_DOCS
  198. ,typename std::enable_if<
  199. (! std::is_constructible<
  200. string_view, T>::value ||
  201. std::is_same<string, T>::value) &&
  202. ! std::is_same<bool,
  203. detail::remove_cvref<T>>::value &&
  204. std::is_same<T, detail::remove_cvref<T>>
  205. ::value>::type* = 0
  206. #endif
  207. ) noexcept
  208. : f_{&from_rvalue<
  209. detail::remove_cvref<T>>, &t}
  210. , what_(std::is_same<string, T>::value ?
  211. what::strfunc : what::func)
  212. {
  213. }
  214. /// Constructor
  215. #ifdef BOOST_JSON_DOCS
  216. value_ref(bool b) noexcept;
  217. #else
  218. template<
  219. class Bool
  220. ,class = typename std::enable_if<
  221. std::is_same<Bool, bool>::value>::type
  222. >
  223. value_ref(
  224. Bool b) noexcept
  225. : arg_(b)
  226. , cf_{&from_builtin<bool>, &arg_.bool_}
  227. , what_(what::cfunc)
  228. {
  229. }
  230. #endif
  231. /// Constructor
  232. value_ref(
  233. std::initializer_list<
  234. value_ref> t) noexcept
  235. : arg_(t)
  236. , what_(what::ini)
  237. {
  238. }
  239. /// Constructor
  240. value_ref(signed char t) noexcept
  241. : arg_(t)
  242. , cf_{&from_builtin<signed char>, &arg_.schar_}
  243. , what_(what::cfunc)
  244. {
  245. }
  246. /// Constructor
  247. value_ref(short t) noexcept
  248. : arg_(t)
  249. , cf_{&from_builtin<short>, &arg_.short_}
  250. , what_(what::cfunc)
  251. {
  252. }
  253. /// Constructor
  254. value_ref(int t) noexcept
  255. : arg_(t)
  256. , cf_{&from_builtin<int>, &arg_.int_}
  257. , what_(what::cfunc)
  258. {
  259. }
  260. /// Constructor
  261. value_ref(long t) noexcept
  262. : arg_(t)
  263. , cf_{&from_builtin<
  264. long>, &arg_.long_}
  265. , what_(what::cfunc)
  266. {
  267. }
  268. /// Constructor
  269. value_ref(long long t) noexcept
  270. : arg_(t)
  271. , cf_{&from_builtin<
  272. long long>, &arg_.long_long_}
  273. , what_(what::cfunc)
  274. {
  275. }
  276. /// Constructor
  277. value_ref(unsigned char t) noexcept
  278. : arg_(t)
  279. , cf_{&from_builtin<
  280. unsigned char>, &arg_.uchar_}
  281. , what_(what::cfunc)
  282. {
  283. }
  284. /// Constructor
  285. value_ref(unsigned short t) noexcept
  286. : arg_(t)
  287. , cf_{&from_builtin<
  288. unsigned short>, &arg_.ushort_}
  289. , what_(what::cfunc)
  290. {
  291. }
  292. /// Constructor
  293. value_ref(unsigned int t) noexcept
  294. : arg_(t)
  295. , cf_{&from_builtin<
  296. unsigned int>, &arg_.uint_}
  297. , what_(what::cfunc)
  298. {
  299. }
  300. /// Constructor
  301. value_ref(unsigned long t) noexcept
  302. : arg_(t)
  303. , cf_{&from_builtin<
  304. unsigned long>, &arg_.ulong_}
  305. , what_(what::cfunc)
  306. {
  307. }
  308. /// Constructor
  309. value_ref(unsigned long long t) noexcept
  310. : arg_(t)
  311. , cf_{&from_builtin<
  312. unsigned long long>, &arg_.ulong_long_}
  313. , what_(what::cfunc)
  314. {
  315. }
  316. /// Constructor
  317. value_ref(float t) noexcept
  318. : arg_(t)
  319. , cf_{&from_builtin<
  320. float>, &arg_.float_}
  321. , what_(what::cfunc)
  322. {
  323. }
  324. /// Constructor
  325. value_ref(double t) noexcept
  326. : arg_(t)
  327. , cf_{&from_builtin<
  328. double>, &arg_.double_}
  329. , what_(what::cfunc)
  330. {
  331. }
  332. /// Constructor
  333. value_ref(std::nullptr_t) noexcept
  334. : arg_(nullptr)
  335. , cf_{&from_builtin<
  336. std::nullptr_t>, &arg_.nullptr_}
  337. , what_(what::cfunc)
  338. {
  339. }
  340. #ifndef BOOST_JSON_DOCS
  341. // Not public
  342. //private:
  343. // VFALCO Why is this needed?
  344. /** Operator conversion to @ref value
  345. This allows creation of a @ref value from
  346. an initializer list element.
  347. */
  348. BOOST_JSON_DECL
  349. operator value() const;
  350. #endif
  351. private:
  352. template<class T>
  353. static
  354. value
  355. from_builtin(
  356. void const* p,
  357. storage_ptr sp) noexcept;
  358. template<class T>
  359. static
  360. value
  361. from_const(
  362. void const* p,
  363. storage_ptr sp);
  364. template<class T>
  365. static
  366. value
  367. from_rvalue(
  368. void* p,
  369. storage_ptr sp);
  370. static
  371. BOOST_JSON_DECL
  372. value
  373. from_init_list(
  374. void const* p,
  375. storage_ptr sp);
  376. inline
  377. bool
  378. is_key_value_pair() const noexcept;
  379. static
  380. inline
  381. bool
  382. maybe_object(
  383. std::initializer_list<
  384. value_ref> init) noexcept;
  385. inline
  386. string_view
  387. get_string() const noexcept;
  388. BOOST_JSON_DECL
  389. value
  390. make_value(
  391. storage_ptr sp) const;
  392. BOOST_JSON_DECL
  393. static
  394. value
  395. make_value(
  396. std::initializer_list<
  397. value_ref> init,
  398. storage_ptr sp);
  399. BOOST_JSON_DECL
  400. static
  401. object
  402. make_object(
  403. std::initializer_list<value_ref> init,
  404. storage_ptr sp);
  405. BOOST_JSON_DECL
  406. static
  407. array
  408. make_array(
  409. std::initializer_list<
  410. value_ref> init,
  411. storage_ptr sp);
  412. BOOST_JSON_DECL
  413. static
  414. void
  415. write_array(
  416. value* dest,
  417. std::initializer_list<
  418. value_ref> init,
  419. storage_ptr const& sp);
  420. };
  421. BOOST_JSON_NS_END
  422. // Must be included here for this file to stand alone
  423. #include <boost/json/value.hpp>
  424. // includes are at the bottom of <boost/json/value.hpp>
  425. //#include <boost/json/impl/value.hpp>
  426. //#include <boost/json/impl/value.ipp>
  427. #endif