object.ipp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  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_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. detail::throw_length_error( "object too large" );
  415. reserve(n0 + init.size());
  416. revert_insert r(*this);
  417. if(t_->is_small())
  418. {
  419. for(auto& iv : init)
  420. {
  421. auto result =
  422. detail::find_in_object(*this, iv.first);
  423. if(result.first)
  424. {
  425. // ignore duplicate
  426. continue;
  427. }
  428. ::new(end()) key_value_pair(
  429. iv.first,
  430. iv.second.make_value(sp_));
  431. ++t_->size;
  432. }
  433. r.commit();
  434. return;
  435. }
  436. for(auto& iv : init)
  437. {
  438. auto& head = t_->bucket(iv.first);
  439. auto i = head;
  440. for(;;)
  441. {
  442. if(i == null_index_)
  443. {
  444. // VFALCO value_ref should construct
  445. // a key_value_pair using placement
  446. auto& v = *::new(end())
  447. key_value_pair(
  448. iv.first,
  449. iv.second.make_value(sp_));
  450. access::next(v) = head;
  451. head = static_cast<index_t>(
  452. t_->size);
  453. ++t_->size;
  454. break;
  455. }
  456. auto& v = (*t_)[i];
  457. if(v.key() == iv.first)
  458. {
  459. // ignore duplicate
  460. break;
  461. }
  462. i = access::next(v);
  463. }
  464. }
  465. r.commit();
  466. }
  467. auto
  468. object::
  469. erase(const_iterator pos) noexcept ->
  470. iterator
  471. {
  472. return do_erase(pos,
  473. [this](iterator p) {
  474. // the casts silence warnings
  475. std::memcpy(
  476. static_cast<void*>(p),
  477. static_cast<void const*>(end()),
  478. sizeof(*p));
  479. },
  480. [this](iterator p) {
  481. reindex_relocate(end(), p);
  482. });
  483. }
  484. auto
  485. object::
  486. erase(string_view key) noexcept ->
  487. std::size_t
  488. {
  489. auto it = find(key);
  490. if(it == end())
  491. return 0;
  492. erase(it);
  493. return 1;
  494. }
  495. auto
  496. object::
  497. stable_erase(const_iterator pos) noexcept ->
  498. iterator
  499. {
  500. return do_erase(pos,
  501. [this](iterator p) {
  502. // the casts silence warnings
  503. std::memmove(
  504. static_cast<void*>(p),
  505. static_cast<void const*>(p + 1),
  506. sizeof(*p) * (end() - p));
  507. },
  508. [this](iterator p) {
  509. for (; p != end(); ++p)
  510. {
  511. reindex_relocate(p + 1, p);
  512. }
  513. });
  514. }
  515. auto
  516. object::
  517. stable_erase(string_view key) noexcept ->
  518. std::size_t
  519. {
  520. auto it = find(key);
  521. if(it == end())
  522. return 0;
  523. stable_erase(it);
  524. return 1;
  525. }
  526. void
  527. object::
  528. swap(object& other)
  529. {
  530. if(*sp_ == *other.sp_)
  531. {
  532. t_ = detail::exchange(
  533. other.t_, t_);
  534. return;
  535. }
  536. object temp1(
  537. std::move(*this),
  538. other.storage());
  539. object temp2(
  540. std::move(other),
  541. this->storage());
  542. other.~object();
  543. ::new(&other) object(pilfer(temp1));
  544. this->~object();
  545. ::new(this) object(pilfer(temp2));
  546. }
  547. //----------------------------------------------------------
  548. //
  549. // Lookup
  550. //
  551. //----------------------------------------------------------
  552. auto
  553. object::
  554. operator[](string_view key) ->
  555. value&
  556. {
  557. auto const result =
  558. emplace(key, nullptr);
  559. return result.first->value();
  560. }
  561. auto
  562. object::
  563. count(string_view key) const noexcept ->
  564. std::size_t
  565. {
  566. if(find(key) == end())
  567. return 0;
  568. return 1;
  569. }
  570. auto
  571. object::
  572. find(string_view key) noexcept ->
  573. iterator
  574. {
  575. if(empty())
  576. return end();
  577. auto const p =
  578. detail::find_in_object(*this, key).first;
  579. if(p)
  580. return p;
  581. return end();
  582. }
  583. auto
  584. object::
  585. find(string_view key) const noexcept ->
  586. const_iterator
  587. {
  588. if(empty())
  589. return end();
  590. auto const p =
  591. detail::find_in_object(*this, key).first;
  592. if(p)
  593. return p;
  594. return end();
  595. }
  596. bool
  597. object::
  598. contains(
  599. string_view key) const noexcept
  600. {
  601. if(empty())
  602. return false;
  603. return detail::find_in_object(*this, key).first
  604. != nullptr;
  605. }
  606. value const*
  607. object::
  608. if_contains(
  609. string_view key) const noexcept
  610. {
  611. auto const it = find(key);
  612. if(it != end())
  613. return &it->value();
  614. return nullptr;
  615. }
  616. value*
  617. object::
  618. if_contains(
  619. string_view key) noexcept
  620. {
  621. auto const it = find(key);
  622. if(it != end())
  623. return &it->value();
  624. return nullptr;
  625. }
  626. //----------------------------------------------------------
  627. //
  628. // (private)
  629. //
  630. //----------------------------------------------------------
  631. auto
  632. object::
  633. insert_impl(
  634. pilfered<key_value_pair> p) ->
  635. std::pair<iterator, bool>
  636. {
  637. // caller is responsible
  638. // for preventing aliasing.
  639. reserve(size() + 1);
  640. auto const result =
  641. detail::find_in_object(*this, p.get().key());
  642. if(result.first)
  643. return { result.first, false };
  644. return { insert_impl(
  645. p, result.second), true };
  646. }
  647. key_value_pair*
  648. object::
  649. insert_impl(
  650. pilfered<key_value_pair> p,
  651. std::size_t hash)
  652. {
  653. BOOST_ASSERT(
  654. capacity() > size());
  655. if(t_->is_small())
  656. {
  657. auto const pv = ::new(end())
  658. key_value_pair(p);
  659. ++t_->size;
  660. return pv;
  661. }
  662. auto& head =
  663. t_->bucket(hash);
  664. auto const pv = ::new(end())
  665. key_value_pair(p);
  666. access::next(*pv) = head;
  667. head = t_->size;
  668. ++t_->size;
  669. return pv;
  670. }
  671. // rehash to at least `n` buckets
  672. void
  673. object::
  674. rehash(std::size_t new_capacity)
  675. {
  676. BOOST_ASSERT(
  677. new_capacity > t_->capacity);
  678. auto t = table::allocate(
  679. growth(new_capacity),
  680. t_->salt, sp_);
  681. if(! empty())
  682. std::memcpy(
  683. static_cast<
  684. void*>(&(*t)[0]),
  685. begin(),
  686. size() * sizeof(
  687. key_value_pair));
  688. t->size = t_->size;
  689. table::deallocate(t_, sp_);
  690. t_ = t;
  691. if(! t_->is_small())
  692. {
  693. // rebuild hash table,
  694. // without dup checks
  695. auto p = end();
  696. index_t i = t_->size;
  697. while(i-- > 0)
  698. {
  699. --p;
  700. auto& head =
  701. t_->bucket(p->key());
  702. access::next(*p) = head;
  703. head = i;
  704. }
  705. }
  706. }
  707. bool
  708. object::
  709. equal(object const& other) const noexcept
  710. {
  711. if(size() != other.size())
  712. return false;
  713. auto const end_ = other.end();
  714. for(auto e : *this)
  715. {
  716. auto it = other.find(e.key());
  717. if(it == end_)
  718. return false;
  719. if(it->value() != e.value())
  720. return false;
  721. }
  722. return true;
  723. }
  724. std::size_t
  725. object::
  726. growth(
  727. std::size_t new_size) const
  728. {
  729. if(new_size > max_size())
  730. detail::throw_length_error( "object too large" );
  731. std::size_t const old = capacity();
  732. if(old > max_size() - old / 2)
  733. return new_size;
  734. std::size_t const g =
  735. old + old / 2; // 1.5x
  736. if(g < new_size)
  737. return new_size;
  738. return g;
  739. }
  740. void
  741. object::
  742. remove(
  743. index_t& head,
  744. key_value_pair& v) noexcept
  745. {
  746. BOOST_ASSERT(! t_->is_small());
  747. auto const i = static_cast<
  748. index_t>(&v - begin());
  749. if(head == i)
  750. {
  751. head = access::next(v);
  752. return;
  753. }
  754. auto* pn =
  755. &access::next((*t_)[head]);
  756. while(*pn != i)
  757. pn = &access::next((*t_)[*pn]);
  758. *pn = access::next(v);
  759. }
  760. void
  761. object::
  762. destroy() noexcept
  763. {
  764. BOOST_ASSERT(t_->capacity > 0);
  765. BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
  766. destroy(begin(), end());
  767. table::deallocate(t_, sp_);
  768. }
  769. void
  770. object::
  771. destroy(
  772. key_value_pair* first,
  773. key_value_pair* last) noexcept
  774. {
  775. BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
  776. while(last != first)
  777. (--last)->~key_value_pair();
  778. }
  779. template<class FS, class FB>
  780. auto
  781. object::
  782. do_erase(
  783. const_iterator pos,
  784. FS small_reloc,
  785. FB big_reloc) noexcept
  786. -> iterator
  787. {
  788. auto p = begin() + (pos - begin());
  789. if(t_->is_small())
  790. {
  791. p->~value_type();
  792. --t_->size;
  793. if(p != end())
  794. {
  795. small_reloc(p);
  796. }
  797. return p;
  798. }
  799. remove(t_->bucket(p->key()), *p);
  800. p->~value_type();
  801. --t_->size;
  802. if(p != end())
  803. {
  804. big_reloc(p);
  805. }
  806. return p;
  807. }
  808. void
  809. object::
  810. reindex_relocate(
  811. key_value_pair* src,
  812. key_value_pair* dst) noexcept
  813. {
  814. BOOST_ASSERT(! t_->is_small());
  815. auto& head = t_->bucket(src->key());
  816. remove(head, *src);
  817. // the casts silence warnings
  818. std::memcpy(
  819. static_cast<void*>(dst),
  820. static_cast<void const*>(src),
  821. sizeof(*dst));
  822. access::next(*dst) = head;
  823. head = static_cast<
  824. index_t>(dst - begin());
  825. }
  826. } // namespace json
  827. } // namespace boost
  828. //----------------------------------------------------------
  829. //
  830. // std::hash specialization
  831. //
  832. //----------------------------------------------------------
  833. std::size_t
  834. std::hash<::boost::json::object>::operator()(
  835. ::boost::json::object const& jo) const noexcept
  836. {
  837. return ::boost::hash< ::boost::json::object >()( jo );
  838. }
  839. //----------------------------------------------------------
  840. #endif