value.ipp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  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. int parse_depth_xalloc = std::ios::xalloc();
  24. int parse_flags_xalloc = std::ios::xalloc();
  25. struct value_hasher
  26. {
  27. std::size_t& seed;
  28. template< class T >
  29. void operator()( T&& t ) const noexcept
  30. {
  31. boost::hash_combine( seed, t );
  32. }
  33. };
  34. enum class stream_parse_flags
  35. {
  36. allow_comments = 1 << 0,
  37. allow_trailing_commas = 1 << 1,
  38. allow_invalid_utf8 = 1 << 2,
  39. };
  40. long
  41. to_bitmask( parse_options const& opts )
  42. {
  43. using E = stream_parse_flags;
  44. return
  45. (opts.allow_comments ?
  46. static_cast<long>(E::allow_comments) : 0) |
  47. (opts.allow_trailing_commas ?
  48. static_cast<long>(E::allow_trailing_commas) : 0) |
  49. (opts.allow_invalid_utf8 ?
  50. static_cast<long>(E::allow_invalid_utf8) : 0);
  51. }
  52. parse_options
  53. get_parse_options( std::istream& is )
  54. {
  55. long const flags = is.iword(parse_flags_xalloc);
  56. using E = stream_parse_flags;
  57. parse_options opts;
  58. opts.allow_comments =
  59. flags & static_cast<long>(E::allow_comments) ? true : false;
  60. opts.allow_trailing_commas =
  61. flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
  62. opts.allow_invalid_utf8 =
  63. flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
  64. return opts;
  65. }
  66. } // namespace
  67. value::
  68. ~value() noexcept
  69. {
  70. switch(kind())
  71. {
  72. case json::kind::null:
  73. case json::kind::bool_:
  74. case json::kind::int64:
  75. case json::kind::uint64:
  76. case json::kind::double_:
  77. sca_.~scalar();
  78. break;
  79. case json::kind::string:
  80. str_.~string();
  81. break;
  82. case json::kind::array:
  83. arr_.~array();
  84. break;
  85. case json::kind::object:
  86. obj_.~object();
  87. break;
  88. }
  89. }
  90. value::
  91. value(
  92. value const& other,
  93. storage_ptr sp)
  94. {
  95. switch(other.kind())
  96. {
  97. case json::kind::null:
  98. ::new(&sca_) scalar(
  99. std::move(sp));
  100. break;
  101. case json::kind::bool_:
  102. ::new(&sca_) scalar(
  103. other.sca_.b,
  104. std::move(sp));
  105. break;
  106. case json::kind::int64:
  107. ::new(&sca_) scalar(
  108. other.sca_.i,
  109. std::move(sp));
  110. break;
  111. case json::kind::uint64:
  112. ::new(&sca_) scalar(
  113. other.sca_.u,
  114. std::move(sp));
  115. break;
  116. case json::kind::double_:
  117. ::new(&sca_) scalar(
  118. other.sca_.d,
  119. std::move(sp));
  120. break;
  121. case json::kind::string:
  122. ::new(&str_) string(
  123. other.str_,
  124. std::move(sp));
  125. break;
  126. case json::kind::array:
  127. ::new(&arr_) array(
  128. other.arr_,
  129. std::move(sp));
  130. break;
  131. case json::kind::object:
  132. ::new(&obj_) object(
  133. other.obj_,
  134. std::move(sp));
  135. break;
  136. }
  137. }
  138. value::
  139. value(value&& other) noexcept
  140. {
  141. relocate(this, other);
  142. ::new(&other.sca_) scalar(sp_);
  143. }
  144. value::
  145. value(
  146. value&& other,
  147. storage_ptr sp)
  148. {
  149. switch(other.kind())
  150. {
  151. case json::kind::null:
  152. ::new(&sca_) scalar(
  153. std::move(sp));
  154. break;
  155. case json::kind::bool_:
  156. ::new(&sca_) scalar(
  157. other.sca_.b, std::move(sp));
  158. break;
  159. case json::kind::int64:
  160. ::new(&sca_) scalar(
  161. other.sca_.i, std::move(sp));
  162. break;
  163. case json::kind::uint64:
  164. ::new(&sca_) scalar(
  165. other.sca_.u, std::move(sp));
  166. break;
  167. case json::kind::double_:
  168. ::new(&sca_) scalar(
  169. other.sca_.d, std::move(sp));
  170. break;
  171. case json::kind::string:
  172. ::new(&str_) string(
  173. std::move(other.str_),
  174. std::move(sp));
  175. break;
  176. case json::kind::array:
  177. ::new(&arr_) array(
  178. std::move(other.arr_),
  179. std::move(sp));
  180. break;
  181. case json::kind::object:
  182. ::new(&obj_) object(
  183. std::move(other.obj_),
  184. std::move(sp));
  185. break;
  186. }
  187. }
  188. //----------------------------------------------------------
  189. //
  190. // Conversion
  191. //
  192. //----------------------------------------------------------
  193. value::
  194. value(
  195. std::initializer_list<value_ref> init,
  196. storage_ptr sp)
  197. {
  198. if(value_ref::maybe_object(init))
  199. {
  200. ::new(&obj_) object(
  201. value_ref::make_object(
  202. init, std::move(sp)));
  203. }
  204. else
  205. {
  206. if( init.size() == 1 )
  207. {
  208. ::new(&sca_) scalar();
  209. value temp = init.begin()->make_value( std::move(sp) );
  210. swap(temp);
  211. }
  212. else
  213. {
  214. ::new(&arr_) array(
  215. value_ref::make_array(
  216. init, std::move(sp)));
  217. }
  218. }
  219. }
  220. //----------------------------------------------------------
  221. //
  222. // Assignment
  223. //
  224. //----------------------------------------------------------
  225. value&
  226. value::
  227. operator=(value const& other)
  228. {
  229. value(other,
  230. storage()).swap(*this);
  231. return *this;
  232. }
  233. value&
  234. value::
  235. operator=(value&& other)
  236. {
  237. value(std::move(other),
  238. storage()).swap(*this);
  239. return *this;
  240. }
  241. value&
  242. value::
  243. operator=(
  244. std::initializer_list<value_ref> init)
  245. {
  246. value(init,
  247. storage()).swap(*this);
  248. return *this;
  249. }
  250. value&
  251. value::
  252. operator=(string_view s)
  253. {
  254. value(s, storage()).swap(*this);
  255. return *this;
  256. }
  257. value&
  258. value::
  259. operator=(char const* s)
  260. {
  261. value(s, storage()).swap(*this);
  262. return *this;
  263. }
  264. value&
  265. value::
  266. operator=(string const& str)
  267. {
  268. value(str, storage()).swap(*this);
  269. return *this;
  270. }
  271. value&
  272. value::
  273. operator=(string&& str)
  274. {
  275. value(std::move(str),
  276. storage()).swap(*this);
  277. return *this;
  278. }
  279. value&
  280. value::
  281. operator=(array const& arr)
  282. {
  283. value(arr, storage()).swap(*this);
  284. return *this;
  285. }
  286. value&
  287. value::
  288. operator=(array&& arr)
  289. {
  290. value(std::move(arr),
  291. storage()).swap(*this);
  292. return *this;
  293. }
  294. value&
  295. value::
  296. operator=(object const& obj)
  297. {
  298. value(obj, storage()).swap(*this);
  299. return *this;
  300. }
  301. value&
  302. value::
  303. operator=(object&& obj)
  304. {
  305. value(std::move(obj),
  306. storage()).swap(*this);
  307. return *this;
  308. }
  309. //----------------------------------------------------------
  310. //
  311. // Accessors
  312. //
  313. //----------------------------------------------------------
  314. system::result<array&>
  315. value::try_as_array() noexcept
  316. {
  317. if( is_array() )
  318. return arr_;
  319. system::error_code ec;
  320. BOOST_JSON_FAIL(ec, error::not_array);
  321. return ec;
  322. }
  323. system::result<array const&>
  324. value::try_as_array() const noexcept
  325. {
  326. if( is_array() )
  327. return arr_;
  328. system::error_code ec;
  329. BOOST_JSON_FAIL(ec, error::not_array);
  330. return ec;
  331. }
  332. system::result<object&>
  333. value::try_as_object() noexcept
  334. {
  335. if( is_object() )
  336. return obj_;
  337. system::error_code ec;
  338. BOOST_JSON_FAIL(ec, error::not_object);
  339. return ec;
  340. }
  341. system::result<object const&>
  342. value::try_as_object() const noexcept
  343. {
  344. if( is_object() )
  345. return obj_;
  346. system::error_code ec;
  347. BOOST_JSON_FAIL(ec, error::not_object);
  348. return ec;
  349. }
  350. system::result<string&>
  351. value::try_as_string() noexcept
  352. {
  353. if( is_string() )
  354. return str_;
  355. system::error_code ec;
  356. BOOST_JSON_FAIL(ec, error::not_string);
  357. return ec;
  358. }
  359. system::result<string const&>
  360. value::try_as_string() const noexcept
  361. {
  362. if( is_string() )
  363. return str_;
  364. system::error_code ec;
  365. BOOST_JSON_FAIL(ec, error::not_string);
  366. return ec;
  367. }
  368. system::result<std::int64_t&>
  369. value::try_as_int64() noexcept
  370. {
  371. if( is_int64() )
  372. return sca_.i;
  373. system::error_code ec;
  374. BOOST_JSON_FAIL(ec, error::not_int64);
  375. return ec;
  376. }
  377. system::result<std::int64_t>
  378. value::try_as_int64() const noexcept
  379. {
  380. if( is_int64() )
  381. return sca_.i;
  382. system::error_code ec;
  383. BOOST_JSON_FAIL(ec, error::not_int64);
  384. return ec;
  385. }
  386. system::result<std::uint64_t&>
  387. value::try_as_uint64() noexcept
  388. {
  389. if( is_uint64() )
  390. return sca_.u;
  391. system::error_code ec;
  392. BOOST_JSON_FAIL(ec, error::not_uint64);
  393. return ec;
  394. }
  395. system::result<std::uint64_t>
  396. value::try_as_uint64() const noexcept
  397. {
  398. if( is_uint64() )
  399. return sca_.u;
  400. system::error_code ec;
  401. BOOST_JSON_FAIL(ec, error::not_uint64);
  402. return ec;
  403. }
  404. system::result<double&>
  405. value::try_as_double() noexcept
  406. {
  407. if( is_double() )
  408. return sca_.d;
  409. system::error_code ec;
  410. BOOST_JSON_FAIL(ec, error::not_double);
  411. return ec;
  412. }
  413. system::result<double>
  414. value::try_as_double() const noexcept
  415. {
  416. if( is_double() )
  417. return sca_.d;
  418. system::error_code ec;
  419. BOOST_JSON_FAIL(ec, error::not_double);
  420. return ec;
  421. }
  422. system::result<bool&>
  423. value::try_as_bool() noexcept
  424. {
  425. if( is_bool() )
  426. return sca_.b;
  427. system::error_code ec;
  428. BOOST_JSON_FAIL(ec, error::not_bool);
  429. return ec;
  430. }
  431. system::result<bool>
  432. value::try_as_bool() const noexcept
  433. {
  434. if( is_bool() )
  435. return sca_.b;
  436. system::error_code ec;
  437. BOOST_JSON_FAIL(ec, error::not_bool);
  438. return ec;
  439. }
  440. system::result<std::nullptr_t>
  441. value::try_as_null() const noexcept
  442. {
  443. if( is_null() )
  444. return nullptr;
  445. system::error_code ec;
  446. BOOST_JSON_FAIL(ec, error::not_null);
  447. return ec;
  448. }
  449. boost::system::result<value&>
  450. value::try_at(string_view key) noexcept
  451. {
  452. auto r = try_as_object();
  453. if( !r )
  454. return r.error();
  455. return r->try_at(key);
  456. }
  457. boost::system::result<value const&>
  458. value::try_at(string_view key) const noexcept
  459. {
  460. auto r = try_as_object();
  461. if( !r )
  462. return r.error();
  463. return r->try_at(key);
  464. }
  465. boost::system::result<value&>
  466. value::try_at(std::size_t pos) noexcept
  467. {
  468. auto r = try_as_array();
  469. if( !r )
  470. return r.error();
  471. return r->try_at(pos);
  472. }
  473. boost::system::result<value const&>
  474. value::try_at(std::size_t pos) const noexcept
  475. {
  476. auto r = try_as_array();
  477. if( !r )
  478. return r.error();
  479. return r->try_at(pos);
  480. }
  481. object const&
  482. value::as_object(source_location const& loc) const&
  483. {
  484. return try_as_object().value(loc);
  485. }
  486. array const&
  487. value::as_array(source_location const& loc) const&
  488. {
  489. return try_as_array().value(loc);
  490. }
  491. string const&
  492. value::as_string(source_location const& loc) const&
  493. {
  494. return try_as_string().value(loc);
  495. }
  496. std::int64_t&
  497. value::as_int64(source_location const& loc)
  498. {
  499. return try_as_int64().value(loc);
  500. }
  501. std::int64_t
  502. value::as_int64(source_location const& loc) const
  503. {
  504. return try_as_int64().value(loc);
  505. }
  506. std::uint64_t&
  507. value::as_uint64(source_location const& loc)
  508. {
  509. return try_as_uint64().value(loc);
  510. }
  511. std::uint64_t
  512. value::as_uint64(source_location const& loc) const
  513. {
  514. return try_as_uint64().value(loc);
  515. }
  516. double&
  517. value::as_double(source_location const& loc)
  518. {
  519. return try_as_double().value(loc);
  520. }
  521. double
  522. value::as_double(source_location const& loc) const
  523. {
  524. return try_as_double().value(loc);
  525. }
  526. bool&
  527. value::as_bool(source_location const& loc)
  528. {
  529. return try_as_bool().value(loc);
  530. }
  531. bool
  532. value::as_bool(source_location const& loc) const
  533. {
  534. return try_as_bool().value(loc);
  535. }
  536. //----------------------------------------------------------
  537. //
  538. // Modifiers
  539. //
  540. //----------------------------------------------------------
  541. string&
  542. value::
  543. emplace_string() noexcept
  544. {
  545. return *::new(&str_) string(destroy());
  546. }
  547. array&
  548. value::
  549. emplace_array() noexcept
  550. {
  551. return *::new(&arr_) array(destroy());
  552. }
  553. object&
  554. value::
  555. emplace_object() noexcept
  556. {
  557. return *::new(&obj_) object(destroy());
  558. }
  559. void
  560. value::
  561. swap(value& other)
  562. {
  563. if(*storage() == *other.storage())
  564. {
  565. // fast path
  566. union U
  567. {
  568. value tmp;
  569. U(){}
  570. ~U(){}
  571. };
  572. U u;
  573. relocate(&u.tmp, *this);
  574. relocate(this, other);
  575. relocate(&other, u.tmp);
  576. return;
  577. }
  578. // copy
  579. value temp1(
  580. std::move(*this),
  581. other.storage());
  582. value temp2(
  583. std::move(other),
  584. this->storage());
  585. other.~value();
  586. ::new(&other) value(pilfer(temp1));
  587. this->~value();
  588. ::new(this) value(pilfer(temp2));
  589. }
  590. std::istream&
  591. operator>>(
  592. std::istream& is,
  593. value& jv)
  594. {
  595. using Traits = std::istream::traits_type;
  596. // sentry prepares the stream for reading and finalizes it in destructor
  597. std::istream::sentry sentry(is);
  598. if( !sentry )
  599. return is;
  600. parse_options opts = get_parse_options( is );
  601. if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
  602. opts.max_depth = depth;
  603. unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
  604. stream_parser p( {}, opts, parser_buf );
  605. p.reset( jv.storage() );
  606. char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
  607. std::streambuf& buf = *is.rdbuf();
  608. std::ios::iostate err = std::ios::goodbit;
  609. #ifndef BOOST_NO_EXCEPTIONS
  610. try
  611. #endif
  612. {
  613. while( true )
  614. {
  615. system::error_code ec;
  616. // we peek the buffer; this either makes sure that there's no
  617. // more input, or makes sure there's something in the internal
  618. // buffer (so in_avail will return a positive number)
  619. std::istream::int_type c = is.rdbuf()->sgetc();
  620. // if we indeed reached EOF, we check if we parsed a full JSON
  621. // document; if not, we error out
  622. if( Traits::eq_int_type(c, Traits::eof()) )
  623. {
  624. err |= std::ios::eofbit;
  625. p.finish(ec);
  626. if( ec.failed() )
  627. break;
  628. }
  629. // regardless of reaching EOF, we might have parsed a full JSON
  630. // document; if so, we successfully finish
  631. if( p.done() )
  632. {
  633. jv = p.release();
  634. return is;
  635. }
  636. // at this point we definitely have more input, specifically in
  637. // buf's internal buffer; we also definitely haven't parsed a whole
  638. // document
  639. std::streamsize available = buf.in_avail();
  640. // if this assert fails, the streambuf is buggy
  641. BOOST_ASSERT( available > 0 );
  642. available = ( std::min )(
  643. static_cast<std::size_t>(available), sizeof(read_buf) );
  644. // we read from the internal buffer of buf into our buffer
  645. available = buf.sgetn( read_buf, available );
  646. std::size_t consumed = p.write_some(
  647. read_buf, static_cast<std::size_t>(available), ec );
  648. // if the parser hasn't consumed the entire input we've took from
  649. // buf, we put the remaining data back; this should succeed,
  650. // because we only read data from buf's internal buffer
  651. while( consumed++ < static_cast<std::size_t>(available) )
  652. {
  653. std::istream::int_type const status = buf.sungetc();
  654. BOOST_ASSERT( status != Traits::eof() );
  655. (void)status;
  656. }
  657. if( ec.failed() )
  658. break;
  659. }
  660. }
  661. #ifndef BOOST_NO_EXCEPTIONS
  662. catch(...)
  663. {
  664. try
  665. {
  666. is.setstate(std::ios::badbit);
  667. }
  668. // we ignore the exception, because we need to throw the original
  669. // exception instead
  670. catch( std::ios::failure const& ) { }
  671. if( is.exceptions() & std::ios::badbit )
  672. throw;
  673. }
  674. #endif
  675. is.setstate(err | std::ios::failbit);
  676. return is;
  677. }
  678. std::istream&
  679. operator>>(
  680. std::istream& is,
  681. parse_options const& opts)
  682. {
  683. is.iword(parse_flags_xalloc) = to_bitmask(opts);
  684. is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
  685. return is;
  686. }
  687. //----------------------------------------------------------
  688. //
  689. // private
  690. //
  691. //----------------------------------------------------------
  692. storage_ptr
  693. value::
  694. destroy() noexcept
  695. {
  696. switch(kind())
  697. {
  698. case json::kind::null:
  699. case json::kind::bool_:
  700. case json::kind::int64:
  701. case json::kind::uint64:
  702. case json::kind::double_:
  703. break;
  704. case json::kind::string:
  705. {
  706. auto sp = str_.storage();
  707. str_.~string();
  708. return sp;
  709. }
  710. case json::kind::array:
  711. {
  712. auto sp = arr_.storage();
  713. arr_.~array();
  714. return sp;
  715. }
  716. case json::kind::object:
  717. {
  718. auto sp = obj_.storage();
  719. obj_.~object();
  720. return sp;
  721. }
  722. }
  723. return std::move(sp_);
  724. }
  725. bool
  726. value::
  727. equal(value const& other) const noexcept
  728. {
  729. switch(kind())
  730. {
  731. default: // unreachable()?
  732. case json::kind::null:
  733. return other.kind() == json::kind::null;
  734. case json::kind::bool_:
  735. return
  736. other.kind() == json::kind::bool_ &&
  737. get_bool() == other.get_bool();
  738. case json::kind::int64:
  739. switch(other.kind())
  740. {
  741. case json::kind::int64:
  742. return get_int64() == other.get_int64();
  743. case json::kind::uint64:
  744. if(get_int64() < 0)
  745. return false;
  746. return static_cast<std::uint64_t>(
  747. get_int64()) == other.get_uint64();
  748. default:
  749. return false;
  750. }
  751. case json::kind::uint64:
  752. switch(other.kind())
  753. {
  754. case json::kind::uint64:
  755. return get_uint64() == other.get_uint64();
  756. case json::kind::int64:
  757. if(other.get_int64() < 0)
  758. return false;
  759. return static_cast<std::uint64_t>(
  760. other.get_int64()) == get_uint64();
  761. default:
  762. return false;
  763. }
  764. case json::kind::double_:
  765. return
  766. other.kind() == json::kind::double_ &&
  767. get_double() == other.get_double();
  768. case json::kind::string:
  769. return
  770. other.kind() == json::kind::string &&
  771. get_string() == other.get_string();
  772. case json::kind::array:
  773. return
  774. other.kind() == json::kind::array &&
  775. get_array() == other.get_array();
  776. case json::kind::object:
  777. return
  778. other.kind() == json::kind::object &&
  779. get_object() == other.get_object();
  780. }
  781. }
  782. //----------------------------------------------------------
  783. //
  784. // key_value_pair
  785. //
  786. //----------------------------------------------------------
  787. // empty keys point here
  788. BOOST_JSON_REQUIRE_CONST_INIT
  789. char const
  790. key_value_pair::empty_[1] = { 0 };
  791. key_value_pair::
  792. key_value_pair(
  793. pilfered<json::value> key,
  794. pilfered<json::value> value) noexcept
  795. : value_(value)
  796. {
  797. std::size_t len;
  798. key_ = access::release_key(key.get(), len);
  799. len_ = static_cast<std::uint32_t>(len);
  800. }
  801. key_value_pair::
  802. key_value_pair(
  803. key_value_pair const& other,
  804. storage_ptr sp)
  805. : value_(other.value_, std::move(sp))
  806. {
  807. auto p = reinterpret_cast<
  808. char*>(value_.storage()->
  809. allocate(other.len_ + 1,
  810. alignof(char)));
  811. std::memcpy(
  812. p, other.key_, other.len_);
  813. len_ = other.len_;
  814. p[len_] = 0;
  815. key_ = p;
  816. }
  817. //----------------------------------------------------------
  818. namespace detail
  819. {
  820. std::size_t
  821. hash_value_impl( value const& jv ) noexcept
  822. {
  823. std::size_t seed = 0;
  824. kind const k = jv.kind();
  825. boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
  826. visit( value_hasher{seed}, jv );
  827. return seed;
  828. }
  829. } // namespace detail
  830. } // namespace json
  831. } // namespace boost
  832. //----------------------------------------------------------
  833. //
  834. // std::hash specialization
  835. //
  836. //----------------------------------------------------------
  837. std::size_t
  838. std::hash<::boost::json::value>::operator()(
  839. ::boost::json::value const& jv) const noexcept
  840. {
  841. return ::boost::hash< ::boost::json::value >()( jv );
  842. }
  843. //----------------------------------------------------------
  844. #endif