value_ref.hpp 11 KB

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