value_ref.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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 lazy construction of and
  28. assignment to the container types @ref value, @ref array, and @ref object.
  29. The two types of initializer lists used are:
  30. @li `std::initializer_list< value_ref >` for constructing or assigning
  31. a @ref value or @ref array, and
  32. @li `std::initializer_list< std::pair< string_view, value_ref > >` for
  33. constructing or assigning an @ref object.
  34. A `value_ref` uses reference semantics. Creation of the actual container
  35. from the initializer list is lazily deferred until the list is used. This
  36. means that the @ref boost::container::pmr::memory_resource used to
  37. construct a container can be specified after the point where the
  38. initializer list is specified. Also, the usage of this type allows to avoid
  39. constructing a @ref value until it's necessary.
  40. @par Example
  41. This example demonstrates how a user-defined type containing a JSON value
  42. can be constructed from an initializer list:
  43. @code
  44. class my_type
  45. {
  46. value jv_;
  47. public:
  48. my_type( std::initializer_list<value_ref> init )
  49. : jv_(init)
  50. {
  51. }
  52. };
  53. @endcode
  54. @warning `value_ref` does not take ownership of the objects it was
  55. constructed with. If those objects' lifetimes end before the `value_ref`
  56. object is used, you will get undefined behavior. Because of this it is
  57. advised against declaring a variable of type
  58. `std::initializer_list<value_ref>` except in function parameter lists.
  59. @see @ref value, @ref array, @ref object, @ref value::set_at_pointer.
  60. */
  61. class value_ref
  62. {
  63. friend class value;
  64. friend class object;
  65. friend class array;
  66. friend class value_ref_test;
  67. enum class what
  68. {
  69. str,
  70. ini,
  71. func,
  72. cfunc,
  73. strfunc,
  74. };
  75. using init_list =
  76. std::initializer_list<value_ref>;
  77. struct func_type
  78. {
  79. value(*f)(void*, storage_ptr);
  80. void* p;
  81. };
  82. struct cfunc_type
  83. {
  84. value(*f)(void const*, storage_ptr);
  85. void const* p;
  86. };
  87. union arg_type
  88. {
  89. string_view str_;
  90. init_list init_list_;
  91. signed char schar_;
  92. short short_;
  93. int int_;
  94. long long_;
  95. long long long_long_;
  96. unsigned char uchar_;
  97. unsigned short ushort_;
  98. unsigned int uint_;
  99. unsigned long ulong_;
  100. unsigned long long ulong_long_;
  101. float float_;
  102. double double_;
  103. bool bool_;
  104. std::nullptr_t nullptr_;
  105. arg_type() {}
  106. explicit arg_type(string_view t) noexcept : str_(t) {}
  107. explicit arg_type(init_list t) noexcept : init_list_(t) {}
  108. explicit arg_type(signed char t) noexcept : schar_(t) {}
  109. explicit arg_type(short t) noexcept : short_(t) {}
  110. explicit arg_type(int t) noexcept : int_(t) {}
  111. explicit arg_type(long t) noexcept : long_(t) {}
  112. explicit arg_type(long long t) noexcept : long_long_(t) {}
  113. explicit arg_type(unsigned char t) noexcept : uchar_(t) {}
  114. explicit arg_type(unsigned short t) noexcept : ushort_(t) {}
  115. explicit arg_type(unsigned int t) noexcept : uint_(t) {}
  116. explicit arg_type(unsigned long t) noexcept : ulong_(t) {}
  117. explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {}
  118. explicit arg_type(float t) noexcept : float_(t) {}
  119. explicit arg_type(double t) noexcept : double_(t) {}
  120. explicit arg_type(bool t) noexcept : bool_(t) {}
  121. explicit arg_type(std::nullptr_t) noexcept : nullptr_() {}
  122. };
  123. arg_type arg_;
  124. #ifndef BOOST_JSON_DOCS
  125. // VFALCO doc toolchain erroneously
  126. // displays private, anonymous unions as public
  127. union
  128. {
  129. func_type f_;
  130. cfunc_type cf_;
  131. };
  132. #endif
  133. what what_;
  134. public:
  135. /** Constructors.
  136. @li **(1)** copy constructor.
  137. @li **(2)** move constructor.
  138. @li **(3)** the constructed value stores a reference to `t`'s character
  139. array.
  140. @li **(4)** the constructed value stores a `const` reference to `t`.
  141. @li **(5)** the constructed value stores an rvalue reference to `t`.
  142. @li **(6)** the constructed value stores a copy of `b`.
  143. @li **(7)**--**(18)** the constructed value stores a copy of `t`.
  144. @li **(19)** the constrcuted value stores `nullptr`.
  145. @li **(20)** the constrcuted value stores a copy of `init`.
  146. In addition the constructed object stores a pointer to a function that
  147. captures the type information necessary to construct a @ref value from
  148. the stored data.
  149. @warning The overloads that accept references do not take ownership of
  150. referenced objects. The caller is responsible for making sure those
  151. objects do not go out of scope before the `value_ref` object is used.
  152. It is advised you only use `value_ref` (or any type that contains a
  153. `value_ref` subobject) as function parameters or take special care to
  154. not invoke undefeined behavior.
  155. @par Complexity
  156. @li **(1)**--**(19)** constant.
  157. @li **(20)** linear in `init.size()`.
  158. @par Exception Safety
  159. No-throw guarantee.
  160. @{
  161. */
  162. value_ref(
  163. value_ref const&) = default;
  164. /// Overload
  165. value_ref(
  166. value_ref&&) = default;
  167. /// Overload
  168. #ifdef BOOST_JSON_DOCS
  169. value_ref(string_view s) noexcept;
  170. #else
  171. template<
  172. class T
  173. ,class = typename
  174. std::enable_if<
  175. std::is_constructible<
  176. string_view, T>::value>::type
  177. >
  178. value_ref(
  179. T const& t) noexcept
  180. : arg_(string_view(t))
  181. , what_(what::str)
  182. {
  183. }
  184. #endif
  185. /// Overload
  186. template<class T>
  187. value_ref(
  188. T const& t
  189. #ifndef BOOST_JSON_DOCS
  190. ,typename std::enable_if<
  191. ! std::is_constructible<
  192. string_view, T>::value &&
  193. ! std::is_same<bool, T>::value
  194. >::type* = 0
  195. #endif
  196. ) noexcept
  197. : cf_{&from_const<T>, &t}
  198. , what_(what::cfunc)
  199. {
  200. }
  201. /// Overload
  202. template<class T>
  203. value_ref(
  204. T&& t
  205. #ifndef BOOST_JSON_DOCS
  206. ,typename std::enable_if<
  207. (! std::is_constructible<
  208. string_view, T>::value ||
  209. std::is_same<string, T>::value) &&
  210. ! std::is_same<bool,
  211. detail::remove_cvref<T>>::value &&
  212. std::is_same<T, detail::remove_cvref<T>>
  213. ::value>::type* = 0
  214. #endif
  215. ) noexcept
  216. : f_{&from_rvalue<
  217. detail::remove_cvref<T>>, &t}
  218. , what_(std::is_same<string, T>::value ?
  219. what::strfunc : what::func)
  220. {
  221. }
  222. /// Overload
  223. #ifdef BOOST_JSON_DOCS
  224. value_ref(bool b) noexcept;
  225. #else
  226. template<
  227. class T
  228. ,class = typename std::enable_if<
  229. std::is_same<T, bool>::value>::type
  230. >
  231. value_ref(
  232. T b) noexcept
  233. : arg_(b)
  234. , cf_{&from_builtin<bool>, &arg_.bool_}
  235. , what_(what::cfunc)
  236. {
  237. }
  238. #endif
  239. /// Overload
  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. /// Overload
  247. value_ref(short t) noexcept
  248. : arg_(t)
  249. , cf_{&from_builtin<short>, &arg_.short_}
  250. , what_(what::cfunc)
  251. {
  252. }
  253. /// Overload
  254. value_ref(int t) noexcept
  255. : arg_(t)
  256. , cf_{&from_builtin<int>, &arg_.int_}
  257. , what_(what::cfunc)
  258. {
  259. }
  260. /// Overload
  261. value_ref(long t) noexcept
  262. : arg_(t)
  263. , cf_{&from_builtin<
  264. long>, &arg_.long_}
  265. , what_(what::cfunc)
  266. {
  267. }
  268. /// Overload
  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. /// Overload
  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. /// Overload
  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. /// Overload
  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. /// Overload
  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. /// Overload
  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. /// Overload
  317. value_ref(float t) noexcept
  318. : arg_(t)
  319. , cf_{&from_builtin<
  320. float>, &arg_.float_}
  321. , what_(what::cfunc)
  322. {
  323. }
  324. /// Overload
  325. value_ref(double t) noexcept
  326. : arg_(t)
  327. , cf_{&from_builtin<
  328. double>, &arg_.double_}
  329. , what_(what::cfunc)
  330. {
  331. }
  332. /// Overload
  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. /// Overload
  341. value_ref(
  342. std::initializer_list<value_ref> init) noexcept
  343. : arg_(init)
  344. , what_(what::ini)
  345. {
  346. }
  347. /// @}
  348. #ifndef BOOST_JSON_DOCS
  349. // Not public
  350. //private:
  351. // VFALCO Why is this needed?
  352. /** Operator conversion to @ref value
  353. This allows creation of a @ref value from
  354. an initializer list element.
  355. */
  356. BOOST_JSON_DECL
  357. operator value() const;
  358. #endif
  359. private:
  360. template<class T>
  361. static
  362. value
  363. from_builtin(
  364. void const* p,
  365. storage_ptr sp) noexcept;
  366. template<class T>
  367. static
  368. value
  369. from_const(
  370. void const* p,
  371. storage_ptr sp);
  372. template<class T>
  373. static
  374. value
  375. from_rvalue(
  376. void* p,
  377. storage_ptr sp);
  378. static
  379. BOOST_JSON_DECL
  380. value
  381. from_init_list(
  382. void const* p,
  383. storage_ptr sp);
  384. inline
  385. bool
  386. is_key_value_pair() const noexcept;
  387. static
  388. inline
  389. bool
  390. maybe_object(
  391. std::initializer_list<
  392. value_ref> init) noexcept;
  393. inline
  394. string_view
  395. get_string() const noexcept;
  396. BOOST_JSON_DECL
  397. value
  398. make_value(
  399. storage_ptr sp) const;
  400. BOOST_JSON_DECL
  401. static
  402. value
  403. make_value(
  404. std::initializer_list<
  405. value_ref> init,
  406. storage_ptr sp);
  407. BOOST_JSON_DECL
  408. static
  409. object
  410. make_object(
  411. std::initializer_list<value_ref> init,
  412. storage_ptr sp);
  413. BOOST_JSON_DECL
  414. static
  415. array
  416. make_array(
  417. std::initializer_list<
  418. value_ref> init,
  419. storage_ptr sp);
  420. BOOST_JSON_DECL
  421. static
  422. void
  423. write_array(
  424. value* dest,
  425. std::initializer_list<
  426. value_ref> init,
  427. storage_ptr const& sp);
  428. };
  429. } // namespace json
  430. } // namespace boost
  431. // Must be included here for this file to stand alone
  432. #include <boost/json/value.hpp>
  433. // includes are at the bottom of <boost/json/value.hpp>
  434. //#include <boost/json/impl/value.hpp>
  435. //#include <boost/json/impl/value.ipp>
  436. #endif