value.ipp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  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_IMPL_VALUE_IPP
  10. #define BOOST_JSON_IMPL_VALUE_IPP
  11. #include <boost/container_hash/hash.hpp>
  12. #include <boost/json/value.hpp>
  13. #include <boost/json/parser.hpp>
  14. #include <cstring>
  15. #include <istream>
  16. #include <limits>
  17. #include <new>
  18. #include <utility>
  19. namespace boost {
  20. namespace json {
  21. namespace
  22. {
  23. struct value_hasher
  24. {
  25. std::size_t& seed;
  26. template< class T >
  27. void operator()( T&& t ) const noexcept
  28. {
  29. boost::hash_combine( seed, t );
  30. }
  31. };
  32. } // namespace
  33. value::
  34. ~value() noexcept
  35. {
  36. switch(kind())
  37. {
  38. case json::kind::null:
  39. case json::kind::bool_:
  40. case json::kind::int64:
  41. case json::kind::uint64:
  42. case json::kind::double_:
  43. sca_.~scalar();
  44. break;
  45. case json::kind::string:
  46. str_.~string();
  47. break;
  48. case json::kind::array:
  49. arr_.~array();
  50. break;
  51. case json::kind::object:
  52. obj_.~object();
  53. break;
  54. }
  55. }
  56. value::
  57. value(
  58. value const& other,
  59. storage_ptr sp)
  60. {
  61. switch(other.kind())
  62. {
  63. case json::kind::null:
  64. ::new(&sca_) scalar(
  65. std::move(sp));
  66. break;
  67. case json::kind::bool_:
  68. ::new(&sca_) scalar(
  69. other.sca_.b,
  70. std::move(sp));
  71. break;
  72. case json::kind::int64:
  73. ::new(&sca_) scalar(
  74. other.sca_.i,
  75. std::move(sp));
  76. break;
  77. case json::kind::uint64:
  78. ::new(&sca_) scalar(
  79. other.sca_.u,
  80. std::move(sp));
  81. break;
  82. case json::kind::double_:
  83. ::new(&sca_) scalar(
  84. other.sca_.d,
  85. std::move(sp));
  86. break;
  87. case json::kind::string:
  88. ::new(&str_) string(
  89. other.str_,
  90. std::move(sp));
  91. break;
  92. case json::kind::array:
  93. ::new(&arr_) array(
  94. other.arr_,
  95. std::move(sp));
  96. break;
  97. case json::kind::object:
  98. ::new(&obj_) object(
  99. other.obj_,
  100. std::move(sp));
  101. break;
  102. }
  103. }
  104. value::
  105. value(value&& other) noexcept
  106. {
  107. relocate(this, other);
  108. ::new(&other.sca_) scalar(sp_);
  109. }
  110. value::
  111. value(
  112. value&& other,
  113. storage_ptr sp)
  114. {
  115. switch(other.kind())
  116. {
  117. case json::kind::null:
  118. ::new(&sca_) scalar(
  119. std::move(sp));
  120. break;
  121. case json::kind::bool_:
  122. ::new(&sca_) scalar(
  123. other.sca_.b, std::move(sp));
  124. break;
  125. case json::kind::int64:
  126. ::new(&sca_) scalar(
  127. other.sca_.i, std::move(sp));
  128. break;
  129. case json::kind::uint64:
  130. ::new(&sca_) scalar(
  131. other.sca_.u, std::move(sp));
  132. break;
  133. case json::kind::double_:
  134. ::new(&sca_) scalar(
  135. other.sca_.d, std::move(sp));
  136. break;
  137. case json::kind::string:
  138. ::new(&str_) string(
  139. std::move(other.str_),
  140. std::move(sp));
  141. break;
  142. case json::kind::array:
  143. ::new(&arr_) array(
  144. std::move(other.arr_),
  145. std::move(sp));
  146. break;
  147. case json::kind::object:
  148. ::new(&obj_) object(
  149. std::move(other.obj_),
  150. std::move(sp));
  151. break;
  152. }
  153. }
  154. //----------------------------------------------------------
  155. //
  156. // Conversion
  157. //
  158. //----------------------------------------------------------
  159. value::
  160. value(
  161. std::initializer_list<value_ref> init,
  162. storage_ptr sp)
  163. {
  164. if(value_ref::maybe_object(init))
  165. ::new(&obj_) object(
  166. value_ref::make_object(
  167. init, std::move(sp)));
  168. else
  169. ::new(&arr_) array(
  170. value_ref::make_array(
  171. init, std::move(sp)));
  172. }
  173. //----------------------------------------------------------
  174. //
  175. // Assignment
  176. //
  177. //----------------------------------------------------------
  178. value&
  179. value::
  180. operator=(value const& other)
  181. {
  182. value(other,
  183. storage()).swap(*this);
  184. return *this;
  185. }
  186. value&
  187. value::
  188. operator=(value&& other)
  189. {
  190. value(std::move(other),
  191. storage()).swap(*this);
  192. return *this;
  193. }
  194. value&
  195. value::
  196. operator=(
  197. std::initializer_list<value_ref> init)
  198. {
  199. value(init,
  200. storage()).swap(*this);
  201. return *this;
  202. }
  203. value&
  204. value::
  205. operator=(string_view s)
  206. {
  207. value(s, storage()).swap(*this);
  208. return *this;
  209. }
  210. value&
  211. value::
  212. operator=(char const* s)
  213. {
  214. value(s, storage()).swap(*this);
  215. return *this;
  216. }
  217. value&
  218. value::
  219. operator=(string const& str)
  220. {
  221. value(str, storage()).swap(*this);
  222. return *this;
  223. }
  224. value&
  225. value::
  226. operator=(string&& str)
  227. {
  228. value(std::move(str),
  229. storage()).swap(*this);
  230. return *this;
  231. }
  232. value&
  233. value::
  234. operator=(array const& arr)
  235. {
  236. value(arr, storage()).swap(*this);
  237. return *this;
  238. }
  239. value&
  240. value::
  241. operator=(array&& arr)
  242. {
  243. value(std::move(arr),
  244. storage()).swap(*this);
  245. return *this;
  246. }
  247. value&
  248. value::
  249. operator=(object const& obj)
  250. {
  251. value(obj, storage()).swap(*this);
  252. return *this;
  253. }
  254. value&
  255. value::
  256. operator=(object&& obj)
  257. {
  258. value(std::move(obj),
  259. storage()).swap(*this);
  260. return *this;
  261. }
  262. //----------------------------------------------------------
  263. //
  264. // Modifiers
  265. //
  266. //----------------------------------------------------------
  267. string&
  268. value::
  269. emplace_string() noexcept
  270. {
  271. return *::new(&str_) string(destroy());
  272. }
  273. array&
  274. value::
  275. emplace_array() noexcept
  276. {
  277. return *::new(&arr_) array(destroy());
  278. }
  279. object&
  280. value::
  281. emplace_object() noexcept
  282. {
  283. return *::new(&obj_) object(destroy());
  284. }
  285. void
  286. value::
  287. swap(value& other)
  288. {
  289. if(*storage() == *other.storage())
  290. {
  291. // fast path
  292. union U
  293. {
  294. value tmp;
  295. U(){}
  296. ~U(){}
  297. };
  298. U u;
  299. relocate(&u.tmp, *this);
  300. relocate(this, other);
  301. relocate(&other, u.tmp);
  302. return;
  303. }
  304. // copy
  305. value temp1(
  306. std::move(*this),
  307. other.storage());
  308. value temp2(
  309. std::move(other),
  310. this->storage());
  311. other.~value();
  312. ::new(&other) value(pilfer(temp1));
  313. this->~value();
  314. ::new(this) value(pilfer(temp2));
  315. }
  316. std::istream&
  317. operator>>(
  318. std::istream& is,
  319. value& jv)
  320. {
  321. using Traits = std::istream::traits_type;
  322. // sentry prepares the stream for reading and finalizes it in destructor
  323. std::istream::sentry sentry(is);
  324. if( !sentry )
  325. return is;
  326. unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
  327. stream_parser p({}, {}, parser_buf);
  328. p.reset( jv.storage() );
  329. char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
  330. std::streambuf& buf = *is.rdbuf();
  331. std::ios::iostate err = std::ios::goodbit;
  332. try
  333. {
  334. while( true )
  335. {
  336. error_code ec;
  337. // we peek the buffer; this either makes sure that there's no
  338. // more input, or makes sure there's something in the internal
  339. // buffer (so in_avail will return a positive number)
  340. std::istream::int_type c = is.rdbuf()->sgetc();
  341. // if we indeed reached EOF, we check if we parsed a full JSON
  342. // document; if not, we error out
  343. if( Traits::eq_int_type(c, Traits::eof()) )
  344. {
  345. err |= std::ios::eofbit;
  346. p.finish(ec);
  347. if( ec.failed() )
  348. break;
  349. }
  350. // regardless of reaching EOF, we might have parsed a full JSON
  351. // document; if so, we successfully finish
  352. if( p.done() )
  353. {
  354. jv = p.release();
  355. return is;
  356. }
  357. // at this point we definitely have more input, specifically in
  358. // buf's internal buffer; we also definitely haven't parsed a whole
  359. // document
  360. std::streamsize available = buf.in_avail();
  361. // if this assert fails, the streambuf is buggy
  362. BOOST_ASSERT( available > 0 );
  363. available = ( std::min )(
  364. static_cast<std::size_t>(available), sizeof(read_buf) );
  365. // we read from the internal buffer of buf into our buffer
  366. available = buf.sgetn( read_buf, available );
  367. std::size_t consumed = p.write_some(
  368. read_buf, static_cast<std::size_t>(available), ec );
  369. // if the parser hasn't consumed the entire input we've took from
  370. // buf, we put the remaining data back; this should succeed,
  371. // because we only read data from buf's internal buffer
  372. while( consumed++ < static_cast<std::size_t>(available) )
  373. {
  374. std::istream::int_type const status = buf.sungetc();
  375. BOOST_ASSERT( status != Traits::eof() );
  376. (void)status;
  377. }
  378. if( ec.failed() )
  379. break;
  380. }
  381. }
  382. catch(...)
  383. {
  384. try
  385. {
  386. is.setstate(std::ios::badbit);
  387. }
  388. // we ignore the exception, because we need to throw the original
  389. // exception instead
  390. catch( std::ios::failure const& ) { }
  391. if( is.exceptions() & std::ios::badbit )
  392. throw;
  393. }
  394. is.setstate(err | std::ios::failbit);
  395. return is;
  396. }
  397. //----------------------------------------------------------
  398. //
  399. // private
  400. //
  401. //----------------------------------------------------------
  402. storage_ptr
  403. value::
  404. destroy() noexcept
  405. {
  406. switch(kind())
  407. {
  408. case json::kind::null:
  409. case json::kind::bool_:
  410. case json::kind::int64:
  411. case json::kind::uint64:
  412. case json::kind::double_:
  413. break;
  414. case json::kind::string:
  415. {
  416. auto sp = str_.storage();
  417. str_.~string();
  418. return sp;
  419. }
  420. case json::kind::array:
  421. {
  422. auto sp = arr_.storage();
  423. arr_.~array();
  424. return sp;
  425. }
  426. case json::kind::object:
  427. {
  428. auto sp = obj_.storage();
  429. obj_.~object();
  430. return sp;
  431. }
  432. }
  433. return std::move(sp_);
  434. }
  435. bool
  436. value::
  437. equal(value const& other) const noexcept
  438. {
  439. switch(kind())
  440. {
  441. default: // unreachable()?
  442. case json::kind::null:
  443. return other.kind() == json::kind::null;
  444. case json::kind::bool_:
  445. return
  446. other.kind() == json::kind::bool_ &&
  447. get_bool() == other.get_bool();
  448. case json::kind::int64:
  449. switch(other.kind())
  450. {
  451. case json::kind::int64:
  452. return get_int64() == other.get_int64();
  453. case json::kind::uint64:
  454. if(get_int64() < 0)
  455. return false;
  456. return static_cast<std::uint64_t>(
  457. get_int64()) == other.get_uint64();
  458. default:
  459. return false;
  460. }
  461. case json::kind::uint64:
  462. switch(other.kind())
  463. {
  464. case json::kind::uint64:
  465. return get_uint64() == other.get_uint64();
  466. case json::kind::int64:
  467. if(other.get_int64() < 0)
  468. return false;
  469. return static_cast<std::uint64_t>(
  470. other.get_int64()) == get_uint64();
  471. default:
  472. return false;
  473. }
  474. case json::kind::double_:
  475. return
  476. other.kind() == json::kind::double_ &&
  477. get_double() == other.get_double();
  478. case json::kind::string:
  479. return
  480. other.kind() == json::kind::string &&
  481. get_string() == other.get_string();
  482. case json::kind::array:
  483. return
  484. other.kind() == json::kind::array &&
  485. get_array() == other.get_array();
  486. case json::kind::object:
  487. return
  488. other.kind() == json::kind::object &&
  489. get_object() == other.get_object();
  490. }
  491. }
  492. //----------------------------------------------------------
  493. //
  494. // key_value_pair
  495. //
  496. //----------------------------------------------------------
  497. // empty keys point here
  498. BOOST_JSON_REQUIRE_CONST_INIT
  499. char const
  500. key_value_pair::empty_[1] = { 0 };
  501. key_value_pair::
  502. key_value_pair(
  503. pilfered<json::value> key,
  504. pilfered<json::value> value) noexcept
  505. : value_(value)
  506. {
  507. std::size_t len;
  508. key_ = access::release_key(key.get(), len);
  509. len_ = static_cast<std::uint32_t>(len);
  510. }
  511. key_value_pair::
  512. key_value_pair(
  513. key_value_pair const& other,
  514. storage_ptr sp)
  515. : value_(other.value_, std::move(sp))
  516. {
  517. auto p = reinterpret_cast<
  518. char*>(value_.storage()->
  519. allocate(other.len_ + 1,
  520. alignof(char)));
  521. std::memcpy(
  522. p, other.key_, other.len_);
  523. len_ = other.len_;
  524. p[len_] = 0;
  525. key_ = p;
  526. }
  527. //----------------------------------------------------------
  528. namespace detail
  529. {
  530. std::size_t
  531. hash_value_impl( value const& jv ) noexcept
  532. {
  533. std::size_t seed = 0;
  534. kind const k = jv.kind();
  535. boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
  536. visit( value_hasher{seed}, jv );
  537. return seed;
  538. }
  539. } // namespace detail
  540. } // namespace json
  541. } // namespace boost
  542. //----------------------------------------------------------
  543. //
  544. // std::hash specialization
  545. //
  546. //----------------------------------------------------------
  547. std::size_t
  548. std::hash<::boost::json::value>::operator()(
  549. ::boost::json::value const& jv) const noexcept
  550. {
  551. return ::boost::hash< ::boost::json::value >()( jv );
  552. }
  553. //----------------------------------------------------------
  554. #endif