object.ipp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. //
  2. // Copyright (c) 2019 Vinnie Falco ([email protected])
  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_OBJECT_IPP
  10. #define BOOST_JSON_IMPL_OBJECT_IPP
  11. #include <boost/container_hash/hash.hpp>
  12. #include <boost/json/object.hpp>
  13. #include <boost/json/detail/digest.hpp>
  14. #include <boost/json/detail/except.hpp>
  15. #include <algorithm>
  16. #include <cmath>
  17. #include <cstdlib>
  18. #include <cstring>
  19. #include <new>
  20. #include <stdexcept>
  21. #include <type_traits>
  22. namespace boost {
  23. namespace json {
  24. namespace detail {
  25. template<class CharRange>
  26. std::pair<key_value_pair*, std::size_t>
  27. find_in_object(
  28. object const& obj,
  29. CharRange key) noexcept
  30. {
  31. BOOST_ASSERT(obj.t_->capacity > 0);
  32. if(obj.t_->is_small())
  33. {
  34. auto it = &(*obj.t_)[0];
  35. auto const last =
  36. &(*obj.t_)[obj.t_->size];
  37. for(;it != last; ++it)
  38. if( key == it->key() )
  39. return { it, 0 };
  40. return { nullptr, 0 };
  41. }
  42. std::pair<
  43. key_value_pair*,
  44. std::size_t> result;
  45. BOOST_ASSERT(obj.t_->salt != 0);
  46. result.second = detail::digest(key.begin(), key.end(), obj.t_->salt);
  47. auto i = obj.t_->bucket(
  48. result.second);
  49. while(i != object::null_index_)
  50. {
  51. auto& v = (*obj.t_)[i];
  52. if( key == v.key() )
  53. {
  54. result.first = &v;
  55. return result;
  56. }
  57. i = access::next(v);
  58. }
  59. result.first = nullptr;
  60. return result;
  61. }
  62. template
  63. std::pair<key_value_pair*, std::size_t>
  64. find_in_object<string_view>(
  65. object const& obj,
  66. string_view key) noexcept;
  67. } // namespace detail
  68. //----------------------------------------------------------
  69. constexpr object::table::table() = default;
  70. // empty objects point here
  71. BOOST_JSON_REQUIRE_CONST_INIT
  72. object::table object::empty_;
  73. std::size_t
  74. object::table::
  75. digest(string_view key) const noexcept
  76. {
  77. BOOST_ASSERT(salt != 0);
  78. return detail::digest(
  79. key.begin(), key.end(), salt);
  80. }
  81. auto
  82. object::table::
  83. bucket(std::size_t hash) noexcept ->
  84. index_t&
  85. {
  86. return reinterpret_cast<
  87. index_t*>(&(*this)[capacity])[
  88. hash % capacity];
  89. }
  90. auto
  91. object::table::
  92. bucket(string_view key) noexcept ->
  93. index_t&
  94. {
  95. return bucket(digest(key));
  96. }
  97. void
  98. object::table::
  99. clear() noexcept
  100. {
  101. BOOST_ASSERT(! is_small());
  102. // initialize buckets
  103. std::memset(
  104. reinterpret_cast<index_t*>(
  105. &(*this)[capacity]),
  106. 0xff, // null_index_
  107. capacity * sizeof(index_t));
  108. }
  109. object::table*
  110. object::table::
  111. allocate(
  112. std::size_t capacity,
  113. std::uintptr_t salt,
  114. storage_ptr const& sp)
  115. {
  116. BOOST_STATIC_ASSERT(
  117. alignof(key_value_pair) >=
  118. alignof(index_t));
  119. BOOST_ASSERT(capacity > 0);
  120. BOOST_ASSERT(capacity <= max_size());
  121. table* p;
  122. if(capacity <= detail::small_object_size_)
  123. {
  124. p = reinterpret_cast<
  125. table*>(sp->allocate(
  126. sizeof(table) + capacity *
  127. sizeof(key_value_pair)));
  128. p->capacity = static_cast<
  129. std::uint32_t>(capacity);
  130. }
  131. else
  132. {
  133. p = reinterpret_cast<
  134. table*>(sp->allocate(
  135. sizeof(table) + capacity * (
  136. sizeof(key_value_pair) +
  137. sizeof(index_t))));
  138. p->capacity = static_cast<
  139. std::uint32_t>(capacity);
  140. p->clear();
  141. }
  142. if(salt)
  143. {
  144. p->salt = salt;
  145. }
  146. else
  147. {
  148. // VFALCO This would be better if it
  149. // was random, but maybe this
  150. // is good enough.
  151. p->salt = reinterpret_cast<
  152. std::uintptr_t>(p);
  153. }
  154. return p;
  155. }
  156. //----------------------------------------------------------
  157. void
  158. object::
  159. revert_construct::
  160. destroy() noexcept
  161. {
  162. obj_->destroy();
  163. }
  164. //----------------------------------------------------------
  165. void
  166. object::
  167. revert_insert::
  168. destroy() noexcept
  169. {
  170. obj_->destroy(
  171. &(*obj_->t_)[size_],
  172. obj_->end());
  173. }
  174. //----------------------------------------------------------
  175. //
  176. // Construction
  177. //
  178. //----------------------------------------------------------
  179. object::
  180. object(detail::unchecked_object&& uo)
  181. : sp_(uo.storage())
  182. {
  183. if(uo.size() == 0)
  184. {
  185. t_ = &empty_;
  186. return;
  187. }
  188. // should already be checked
  189. BOOST_ASSERT(
  190. uo.size() <= max_size());
  191. t_ = table::allocate(
  192. uo.size(), 0, sp_);
  193. // insert all elements, keeping
  194. // the last of any duplicate keys.
  195. auto dest = begin();
  196. auto src = uo.release();
  197. auto const end = src + 2 * uo.size();
  198. if(t_->is_small())
  199. {
  200. t_->size = 0;
  201. while(src != end)
  202. {
  203. access::construct_key_value_pair(
  204. dest, pilfer(src[0]), pilfer(src[1]));
  205. src += 2;
  206. auto result = detail::find_in_object(*this, dest->key());
  207. if(! result.first)
  208. {
  209. ++dest;
  210. ++t_->size;
  211. continue;
  212. }
  213. // handle duplicate
  214. auto& v = *result.first;
  215. // don't bother to check if
  216. // storage deallocate is trivial
  217. v.~key_value_pair();
  218. // trivial relocate
  219. std::memcpy(
  220. static_cast<void*>(&v),
  221. dest, sizeof(v));
  222. }
  223. return;
  224. }
  225. while(src != end)
  226. {
  227. access::construct_key_value_pair(
  228. dest, pilfer(src[0]), pilfer(src[1]));
  229. src += 2;
  230. auto& head = t_->bucket(dest->key());
  231. auto i = head;
  232. for(;;)
  233. {
  234. if(i == null_index_)
  235. {
  236. // end of bucket
  237. access::next(
  238. *dest) = head;
  239. head = static_cast<index_t>(
  240. dest - begin());
  241. ++dest;
  242. break;
  243. }
  244. auto& v = (*t_)[i];
  245. if(v.key() != dest->key())
  246. {
  247. i = access::next(v);
  248. continue;
  249. }
  250. // handle duplicate
  251. access::next(*dest) =
  252. access::next(v);
  253. // don't bother to check if
  254. // storage deallocate is trivial
  255. v.~key_value_pair();
  256. // trivial relocate
  257. std::memcpy(
  258. static_cast<void*>(&v),
  259. dest, sizeof(v));
  260. break;
  261. }
  262. }
  263. t_->size = static_cast<
  264. index_t>(dest - begin());
  265. }
  266. object::
  267. ~object() noexcept
  268. {
  269. if(sp_.is_not_shared_and_deallocate_is_trivial())
  270. return;
  271. if(t_->capacity == 0)
  272. return;
  273. destroy();
  274. }
  275. object::
  276. object(
  277. std::size_t min_capacity,
  278. storage_ptr sp)
  279. : sp_(std::move(sp))
  280. , t_(&empty_)
  281. {
  282. reserve(min_capacity);
  283. }
  284. object::
  285. object(object&& other) noexcept
  286. : sp_(other.sp_)
  287. , t_(detail::exchange(
  288. other.t_, &empty_))
  289. {
  290. }
  291. object::
  292. object(
  293. object&& other,
  294. storage_ptr sp)
  295. : sp_(std::move(sp))
  296. {
  297. if(*sp_ == *other.sp_)
  298. {
  299. t_ = detail::exchange(
  300. other.t_, &empty_);
  301. return;
  302. }
  303. t_ = &empty_;
  304. object(other, sp_).swap(*this);
  305. }
  306. object::
  307. object(
  308. object const& other,
  309. storage_ptr sp)
  310. : sp_(std::move(sp))
  311. , t_(&empty_)
  312. {
  313. reserve(other.size());
  314. revert_construct r(*this);
  315. if(t_->is_small())
  316. {
  317. for(auto const& v : other)
  318. {
  319. ::new(end())
  320. key_value_pair(v, sp_);
  321. ++t_->size;
  322. }
  323. r.commit();
  324. return;
  325. }
  326. for(auto const& v : other)
  327. {
  328. // skip duplicate checking
  329. auto& head =
  330. t_->bucket(v.key());
  331. auto pv = ::new(end())
  332. key_value_pair(v, sp_);
  333. access::next(*pv) = head;
  334. head = t_->size;
  335. ++t_->size;
  336. }
  337. r.commit();
  338. }
  339. object::
  340. object(
  341. std::initializer_list<std::pair<
  342. string_view, value_ref>> init,
  343. std::size_t min_capacity,
  344. storage_ptr sp)
  345. : sp_(std::move(sp))
  346. , t_(&empty_)
  347. {
  348. if( min_capacity < init.size())
  349. min_capacity = init.size();
  350. reserve(min_capacity);
  351. revert_construct r(*this);
  352. insert(init);
  353. r.commit();
  354. }
  355. //----------------------------------------------------------
  356. //
  357. // Assignment
  358. //
  359. //----------------------------------------------------------
  360. object&
  361. object::
  362. operator=(object const& other)
  363. {
  364. object tmp(other, sp_);
  365. this->~object();
  366. ::new(this) object(pilfer(tmp));
  367. return *this;
  368. }
  369. object&
  370. object::
  371. operator=(object&& other)
  372. {
  373. object tmp(std::move(other), sp_);
  374. this->~object();
  375. ::new(this) object(pilfer(tmp));
  376. return *this;
  377. }
  378. object&
  379. object::
  380. operator=(
  381. std::initializer_list<std::pair<
  382. string_view, value_ref>> init)
  383. {
  384. object tmp(init, sp_);
  385. this->~object();
  386. ::new(this) object(pilfer(tmp));
  387. return *this;
  388. }
  389. //----------------------------------------------------------
  390. //
  391. // Modifiers
  392. //
  393. //----------------------------------------------------------
  394. void
  395. object::
  396. clear() noexcept
  397. {
  398. if(empty())
  399. return;
  400. if(! sp_.is_not_shared_and_deallocate_is_trivial())
  401. destroy(begin(), end());
  402. if(! t_->is_small())
  403. t_->clear();
  404. t_->size = 0;
  405. }
  406. void
  407. object::
  408. insert(
  409. std::initializer_list<std::pair<
  410. string_view, value_ref>> init)
  411. {
  412. auto const n0 = size();
  413. if(init.size() > max_size() - n0)
  414. {
  415. BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
  416. detail::throw_system_error( error::object_too_large, &loc );
  417. }
  418. revert_insert r( *this, n0 + init.size() );
  419. if(t_->is_small())
  420. {
  421. for(auto& iv : init)
  422. {
  423. auto result =
  424. detail::find_in_object(*this, iv.first);
  425. if(result.first)
  426. {
  427. // ignore duplicate
  428. continue;
  429. }
  430. ::new(end()) key_value_pair(
  431. iv.first,
  432. iv.second.make_value(sp_));
  433. ++t_->size;
  434. }
  435. r.commit();
  436. return;
  437. }
  438. for(auto& iv : init)
  439. {
  440. auto& head = t_->bucket(iv.first);
  441. auto i = head;
  442. for(;;)
  443. {
  444. if(i == null_index_)
  445. {
  446. // VFALCO value_ref should construct
  447. // a key_value_pair using placement
  448. auto& v = *::new(end())
  449. key_value_pair(
  450. iv.first,
  451. iv.second.make_value(sp_));
  452. access::next(v) = head;
  453. head = static_cast<index_t>(
  454. t_->size);
  455. ++t_->size;
  456. break;
  457. }
  458. auto& v = (*t_)[i];
  459. if(v.key() == iv.first)
  460. {
  461. // ignore duplicate
  462. break;
  463. }
  464. i = access::next(v);
  465. }
  466. }
  467. r.commit();
  468. }
  469. auto
  470. object::
  471. erase(const_iterator pos) noexcept ->
  472. iterator
  473. {
  474. return do_erase(pos,
  475. [this](iterator p) {
  476. // the casts silence warnings
  477. std::memcpy(
  478. static_cast<void*>(p),
  479. static_cast<void const*>(end()),
  480. sizeof(*p));
  481. },
  482. [this](iterator p) {
  483. reindex_relocate(end(), p);
  484. });
  485. }
  486. auto
  487. object::
  488. erase(string_view key) noexcept ->
  489. std::size_t
  490. {
  491. auto it = find(key);
  492. if(it == end())
  493. return 0;
  494. erase(it);
  495. return 1;
  496. }
  497. auto
  498. object::
  499. stable_erase(const_iterator pos) noexcept ->
  500. iterator
  501. {
  502. return do_erase(pos,
  503. [this](iterator p) {
  504. // the casts silence warnings
  505. std::memmove(
  506. static_cast<void*>(p),
  507. static_cast<void const*>(p + 1),
  508. sizeof(*p) * (end() - p));
  509. },
  510. [this](iterator p) {
  511. for (; p != end(); ++p)
  512. {
  513. reindex_relocate(p + 1, p);
  514. }
  515. });
  516. }
  517. auto
  518. object::
  519. stable_erase(string_view key) noexcept ->
  520. std::size_t
  521. {
  522. auto it = find(key);
  523. if(it == end())
  524. return 0;
  525. stable_erase(it);
  526. return 1;
  527. }
  528. void
  529. object::
  530. swap(object& other)
  531. {
  532. if(*sp_ == *other.sp_)
  533. {
  534. t_ = detail::exchange(
  535. other.t_, t_);
  536. return;
  537. }
  538. object temp1(
  539. std::move(*this),
  540. other.storage());
  541. object temp2(
  542. std::move(other),
  543. this->storage());
  544. other.~object();
  545. ::new(&other) object(pilfer(temp1));
  546. this->~object();
  547. ::new(this) object(pilfer(temp2));
  548. }
  549. //----------------------------------------------------------
  550. //
  551. // Lookup
  552. //
  553. //----------------------------------------------------------
  554. auto
  555. object::
  556. operator[](string_view key) ->
  557. value&
  558. {
  559. auto const result =
  560. emplace(key, nullptr);
  561. return result.first->value();
  562. }
  563. auto
  564. object::
  565. count(string_view key) const noexcept ->
  566. std::size_t
  567. {
  568. if(find(key) == end())
  569. return 0;
  570. return 1;
  571. }
  572. auto
  573. object::
  574. find(string_view key) noexcept ->
  575. iterator
  576. {
  577. if(empty())
  578. return end();
  579. auto const p =
  580. detail::find_in_object(*this, key).first;
  581. if(p)
  582. return p;
  583. return end();
  584. }
  585. auto
  586. object::
  587. find(string_view key) const noexcept ->
  588. const_iterator
  589. {
  590. if(empty())
  591. return end();
  592. auto const p =
  593. detail::find_in_object(*this, key).first;
  594. if(p)
  595. return p;
  596. return end();
  597. }
  598. bool
  599. object::
  600. contains(
  601. string_view key) const noexcept
  602. {
  603. if(empty())
  604. return false;
  605. return detail::find_in_object(*this, key).first
  606. != nullptr;
  607. }
  608. value const*
  609. object::
  610. if_contains(
  611. string_view key) const noexcept
  612. {
  613. auto const it = find(key);
  614. if(it != end())
  615. return &it->value();
  616. return nullptr;
  617. }
  618. value*
  619. object::
  620. if_contains(
  621. string_view key) noexcept
  622. {
  623. auto const it = find(key);
  624. if(it != end())
  625. return &it->value();
  626. return nullptr;
  627. }
  628. //----------------------------------------------------------
  629. //
  630. // (private)
  631. //
  632. //----------------------------------------------------------
  633. key_value_pair*
  634. object::
  635. insert_impl(
  636. pilfered<key_value_pair> p,
  637. std::size_t hash)
  638. {
  639. BOOST_ASSERT(
  640. capacity() > size());
  641. if(t_->is_small())
  642. {
  643. auto const pv = ::new(end())
  644. key_value_pair(p);
  645. ++t_->size;
  646. return pv;
  647. }
  648. auto& head =
  649. t_->bucket(hash);
  650. auto const pv = ::new(end())
  651. key_value_pair(p);
  652. access::next(*pv) = head;
  653. head = t_->size;
  654. ++t_->size;
  655. return pv;
  656. }
  657. // allocate new table, copy elements there, and rehash them
  658. object::table*
  659. object::
  660. reserve_impl(std::size_t new_capacity)
  661. {
  662. BOOST_ASSERT(
  663. new_capacity > t_->capacity);
  664. auto t = table::allocate(
  665. growth(new_capacity),
  666. t_->salt, sp_);
  667. if(! empty())
  668. std::memcpy(
  669. static_cast<
  670. void*>(&(*t)[0]),
  671. begin(),
  672. size() * sizeof(
  673. key_value_pair));
  674. t->size = t_->size;
  675. std::swap(t_, t);
  676. if(! t_->is_small())
  677. {
  678. // rebuild hash table,
  679. // without dup checks
  680. auto p = end();
  681. index_t i = t_->size;
  682. while(i-- > 0)
  683. {
  684. --p;
  685. auto& head =
  686. t_->bucket(p->key());
  687. access::next(*p) = head;
  688. head = i;
  689. }
  690. }
  691. return t;
  692. }
  693. bool
  694. object::
  695. equal(object const& other) const noexcept
  696. {
  697. if(size() != other.size())
  698. return false;
  699. auto const end_ = other.end();
  700. for(auto e : *this)
  701. {
  702. auto it = other.find(e.key());
  703. if(it == end_)
  704. return false;
  705. if(it->value() != e.value())
  706. return false;
  707. }
  708. return true;
  709. }
  710. std::size_t
  711. object::
  712. growth(
  713. std::size_t new_size) const
  714. {
  715. if(new_size > max_size())
  716. {
  717. BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
  718. detail::throw_system_error( error::object_too_large, &loc );
  719. }
  720. std::size_t const old = capacity();
  721. if(old > max_size() - old / 2)
  722. return new_size;
  723. std::size_t const g =
  724. old + old / 2; // 1.5x
  725. if(g < new_size)
  726. return new_size;
  727. return g;
  728. }
  729. void
  730. object::
  731. remove(
  732. index_t& head,
  733. key_value_pair& v) noexcept
  734. {
  735. BOOST_ASSERT(! t_->is_small());
  736. auto const i = static_cast<
  737. index_t>(&v - begin());
  738. if(head == i)
  739. {
  740. head = access::next(v);
  741. return;
  742. }
  743. auto* pn =
  744. &access::next((*t_)[head]);
  745. while(*pn != i)
  746. pn = &access::next((*t_)[*pn]);
  747. *pn = access::next(v);
  748. }
  749. void
  750. object::
  751. destroy() noexcept
  752. {
  753. BOOST_ASSERT(t_->capacity > 0);
  754. BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
  755. destroy(begin(), end());
  756. table::deallocate(t_, sp_);
  757. }
  758. void
  759. object::
  760. destroy(
  761. key_value_pair* first,
  762. key_value_pair* last) noexcept
  763. {
  764. BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
  765. while(last != first)
  766. (--last)->~key_value_pair();
  767. }
  768. template<class FS, class FB>
  769. auto
  770. object::
  771. do_erase(
  772. const_iterator pos,
  773. FS small_reloc,
  774. FB big_reloc) noexcept
  775. -> iterator
  776. {
  777. auto p = begin() + (pos - begin());
  778. if(t_->is_small())
  779. {
  780. p->~value_type();
  781. --t_->size;
  782. if(p != end())
  783. {
  784. small_reloc(p);
  785. }
  786. return p;
  787. }
  788. remove(t_->bucket(p->key()), *p);
  789. p->~value_type();
  790. --t_->size;
  791. if(p != end())
  792. {
  793. big_reloc(p);
  794. }
  795. return p;
  796. }
  797. void
  798. object::
  799. reindex_relocate(
  800. key_value_pair* src,
  801. key_value_pair* dst) noexcept
  802. {
  803. BOOST_ASSERT(! t_->is_small());
  804. auto& head = t_->bucket(src->key());
  805. remove(head, *src);
  806. // the casts silence warnings
  807. std::memcpy(
  808. static_cast<void*>(dst),
  809. static_cast<void const*>(src),
  810. sizeof(*dst));
  811. access::next(*dst) = head;
  812. head = static_cast<
  813. index_t>(dst - begin());
  814. }
  815. } // namespace json
  816. } // namespace boost
  817. //----------------------------------------------------------
  818. //
  819. // std::hash specialization
  820. //
  821. //----------------------------------------------------------
  822. std::size_t
  823. std::hash<::boost::json::object>::operator()(
  824. ::boost::json::object const& jo) const noexcept
  825. {
  826. return ::boost::hash< ::boost::json::object >()( jo );
  827. }
  828. //----------------------------------------------------------
  829. #endif