array.ipp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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_ARRAY_IPP
  10. #define BOOST_JSON_IMPL_ARRAY_IPP
  11. #include <boost/container_hash/hash.hpp>
  12. #include <boost/json/array.hpp>
  13. #include <boost/json/pilfer.hpp>
  14. #include <boost/json/detail/except.hpp>
  15. #include <cstdlib>
  16. #include <limits>
  17. #include <new>
  18. #include <utility>
  19. namespace boost {
  20. namespace json {
  21. //----------------------------------------------------------
  22. constexpr array::table::table() = default;
  23. // empty arrays point here
  24. BOOST_JSON_REQUIRE_CONST_INIT
  25. array::table array::empty_;
  26. auto
  27. array::
  28. table::
  29. allocate(
  30. std::size_t capacity,
  31. storage_ptr const& sp) ->
  32. table*
  33. {
  34. BOOST_ASSERT(capacity > 0);
  35. if(capacity > array::max_size())
  36. detail::throw_length_error( "array too large" );
  37. auto p = reinterpret_cast<
  38. table*>(sp->allocate(
  39. sizeof(table) +
  40. capacity * sizeof(value),
  41. alignof(value)));
  42. p->capacity = static_cast<
  43. std::uint32_t>(capacity);
  44. return p;
  45. }
  46. void
  47. array::
  48. table::
  49. deallocate(
  50. table* p,
  51. storage_ptr const& sp)
  52. {
  53. if(p->capacity == 0)
  54. return;
  55. sp->deallocate(p,
  56. sizeof(table) +
  57. p->capacity * sizeof(value),
  58. alignof(value));
  59. }
  60. //----------------------------------------------------------
  61. array::
  62. revert_insert::
  63. revert_insert(
  64. const_iterator pos,
  65. std::size_t n,
  66. array& arr)
  67. : arr_(&arr)
  68. , i_(pos - arr_->data())
  69. , n_(n)
  70. {
  71. BOOST_ASSERT(
  72. pos >= arr_->begin() &&
  73. pos <= arr_->end());
  74. if( n_ <= arr_->capacity() -
  75. arr_->size())
  76. {
  77. // fast path
  78. p = arr_->data() + i_;
  79. if(n_ == 0)
  80. return;
  81. relocate(
  82. p + n_,
  83. p,
  84. arr_->size() - i_);
  85. arr_->t_->size = static_cast<
  86. std::uint32_t>(
  87. arr_->t_->size + n_);
  88. return;
  89. }
  90. if(n_ > max_size() - arr_->size())
  91. detail::throw_length_error( "array too large" );
  92. auto t = table::allocate(
  93. arr_->growth(arr_->size() + n_),
  94. arr_->sp_);
  95. t->size = static_cast<std::uint32_t>(
  96. arr_->size() + n_);
  97. p = &(*t)[0] + i_;
  98. relocate(
  99. &(*t)[0],
  100. arr_->data(),
  101. i_);
  102. relocate(
  103. &(*t)[i_ + n_],
  104. arr_->data() + i_,
  105. arr_->size() - i_);
  106. t = detail::exchange(arr_->t_, t);
  107. table::deallocate(t, arr_->sp_);
  108. }
  109. array::
  110. revert_insert::
  111. ~revert_insert()
  112. {
  113. if(! arr_)
  114. return;
  115. BOOST_ASSERT(n_ != 0);
  116. auto const pos =
  117. arr_->data() + i_;
  118. arr_->destroy(pos, p);
  119. arr_->t_->size = static_cast<
  120. std::uint32_t>(
  121. arr_->t_->size - n_);
  122. relocate(
  123. pos,
  124. pos + n_,
  125. arr_->size() - i_);
  126. }
  127. //----------------------------------------------------------
  128. void
  129. array::
  130. destroy(
  131. value* first, value* last) noexcept
  132. {
  133. if(sp_.is_not_shared_and_deallocate_is_trivial())
  134. return;
  135. while(last-- != first)
  136. last->~value();
  137. }
  138. void
  139. array::
  140. destroy() noexcept
  141. {
  142. if(sp_.is_not_shared_and_deallocate_is_trivial())
  143. return;
  144. auto last = end();
  145. auto const first = begin();
  146. while(last-- != first)
  147. last->~value();
  148. table::deallocate(t_, sp_);
  149. }
  150. //----------------------------------------------------------
  151. //
  152. // Special Members
  153. //
  154. //----------------------------------------------------------
  155. array::
  156. array(detail::unchecked_array&& ua)
  157. : sp_(ua.storage())
  158. {
  159. BOOST_STATIC_ASSERT(
  160. alignof(table) == alignof(value));
  161. if(ua.size() == 0)
  162. {
  163. t_ = &empty_;
  164. return;
  165. }
  166. t_= table::allocate(
  167. ua.size(), sp_);
  168. t_->size = static_cast<
  169. std::uint32_t>(ua.size());
  170. ua.relocate(data());
  171. }
  172. array::
  173. ~array() noexcept
  174. {
  175. destroy();
  176. }
  177. array::
  178. array(
  179. std::size_t count,
  180. value const& v,
  181. storage_ptr sp)
  182. : sp_(std::move(sp))
  183. {
  184. if(count == 0)
  185. {
  186. t_ = &empty_;
  187. return;
  188. }
  189. t_= table::allocate(
  190. count, sp_);
  191. t_->size = 0;
  192. revert_construct r(*this);
  193. while(count--)
  194. {
  195. ::new(end()) value(v, sp_);
  196. ++t_->size;
  197. }
  198. r.commit();
  199. }
  200. array::
  201. array(
  202. std::size_t count,
  203. storage_ptr sp)
  204. : sp_(std::move(sp))
  205. {
  206. if(count == 0)
  207. {
  208. t_ = &empty_;
  209. return;
  210. }
  211. t_ = table::allocate(
  212. count, sp_);
  213. t_->size = static_cast<
  214. std::uint32_t>(count);
  215. auto p = data();
  216. do
  217. {
  218. ::new(p++) value(sp_);
  219. }
  220. while(--count);
  221. }
  222. array::
  223. array(array const& other)
  224. : array(other, other.sp_)
  225. {
  226. }
  227. array::
  228. array(
  229. array const& other,
  230. storage_ptr sp)
  231. : sp_(std::move(sp))
  232. {
  233. if(other.empty())
  234. {
  235. t_ = &empty_;
  236. return;
  237. }
  238. t_ = table::allocate(
  239. other.size(), sp_);
  240. t_->size = 0;
  241. revert_construct r(*this);
  242. auto src = other.data();
  243. auto dest = data();
  244. auto const n = other.size();
  245. do
  246. {
  247. ::new(dest++) value(
  248. *src++, sp_);
  249. ++t_->size;
  250. }
  251. while(t_->size < n);
  252. r.commit();
  253. }
  254. array::
  255. array(
  256. array&& other,
  257. storage_ptr sp)
  258. : sp_(std::move(sp))
  259. {
  260. if(*sp_ == *other.sp_)
  261. {
  262. // same resource
  263. t_ = detail::exchange(
  264. other.t_, &empty_);
  265. return;
  266. }
  267. else if(other.empty())
  268. {
  269. t_ = &empty_;
  270. return;
  271. }
  272. // copy
  273. t_ = table::allocate(
  274. other.size(), sp_);
  275. t_->size = 0;
  276. revert_construct r(*this);
  277. auto src = other.data();
  278. auto dest = data();
  279. auto const n = other.size();
  280. do
  281. {
  282. ::new(dest++) value(
  283. *src++, sp_);
  284. ++t_->size;
  285. }
  286. while(t_->size < n);
  287. r.commit();
  288. }
  289. array::
  290. array(
  291. std::initializer_list<
  292. value_ref> init,
  293. storage_ptr sp)
  294. : sp_(std::move(sp))
  295. {
  296. if(init.size() == 0)
  297. {
  298. t_ = &empty_;
  299. return;
  300. }
  301. t_ = table::allocate(
  302. init.size(), sp_);
  303. t_->size = 0;
  304. revert_construct r(*this);
  305. value_ref::write_array(
  306. data(), init, sp_);
  307. t_->size = static_cast<
  308. std::uint32_t>(init.size());
  309. r.commit();
  310. }
  311. //----------------------------------------------------------
  312. array&
  313. array::
  314. operator=(array const& other)
  315. {
  316. array(other,
  317. storage()).swap(*this);
  318. return *this;
  319. }
  320. array&
  321. array::
  322. operator=(array&& other)
  323. {
  324. array(std::move(other),
  325. storage()).swap(*this);
  326. return *this;
  327. }
  328. array&
  329. array::
  330. operator=(
  331. std::initializer_list<value_ref> init)
  332. {
  333. array(init,
  334. storage()).swap(*this);
  335. return *this;
  336. }
  337. //----------------------------------------------------------
  338. //
  339. // Capacity
  340. //
  341. //----------------------------------------------------------
  342. void
  343. array::
  344. shrink_to_fit() noexcept
  345. {
  346. if(capacity() <= size())
  347. return;
  348. if(size() == 0)
  349. {
  350. table::deallocate(t_, sp_);
  351. t_ = &empty_;
  352. return;
  353. }
  354. #ifndef BOOST_NO_EXCEPTIONS
  355. try
  356. {
  357. #endif
  358. auto t = table::allocate(
  359. size(), sp_);
  360. relocate(
  361. &(*t)[0],
  362. data(),
  363. size());
  364. t->size = static_cast<
  365. std::uint32_t>(size());
  366. t = detail::exchange(
  367. t_, t);
  368. table::deallocate(t, sp_);
  369. #ifndef BOOST_NO_EXCEPTIONS
  370. }
  371. catch(...)
  372. {
  373. // eat the exception
  374. return;
  375. }
  376. #endif
  377. }
  378. //----------------------------------------------------------
  379. //
  380. // Modifiers
  381. //
  382. //----------------------------------------------------------
  383. void
  384. array::
  385. clear() noexcept
  386. {
  387. if(size() == 0)
  388. return;
  389. destroy(
  390. begin(), end());
  391. t_->size = 0;
  392. }
  393. auto
  394. array::
  395. insert(
  396. const_iterator pos,
  397. value const& v) ->
  398. iterator
  399. {
  400. return emplace(pos, v);
  401. }
  402. auto
  403. array::
  404. insert(
  405. const_iterator pos,
  406. value&& v) ->
  407. iterator
  408. {
  409. return emplace(pos, std::move(v));
  410. }
  411. auto
  412. array::
  413. insert(
  414. const_iterator pos,
  415. std::size_t count,
  416. value const& v) ->
  417. iterator
  418. {
  419. revert_insert r(
  420. pos, count, *this);
  421. while(count--)
  422. {
  423. ::new(r.p) value(v, sp_);
  424. ++r.p;
  425. }
  426. return r.commit();
  427. }
  428. auto
  429. array::
  430. insert(
  431. const_iterator pos,
  432. std::initializer_list<
  433. value_ref> init) ->
  434. iterator
  435. {
  436. revert_insert r(
  437. pos, init.size(), *this);
  438. value_ref::write_array(
  439. r.p, init, sp_);
  440. return r.commit();
  441. }
  442. auto
  443. array::
  444. erase(
  445. const_iterator pos) noexcept ->
  446. iterator
  447. {
  448. BOOST_ASSERT(
  449. pos >= begin() &&
  450. pos <= end());
  451. return erase(pos, pos + 1);
  452. }
  453. auto
  454. array::
  455. erase(
  456. const_iterator first,
  457. const_iterator last) noexcept ->
  458. iterator
  459. {
  460. BOOST_ASSERT(
  461. first >= begin() &&
  462. last >= first &&
  463. last <= end());
  464. std::size_t const n =
  465. last - first;
  466. auto const p = &(*t_)[0] +
  467. (first - &(*t_)[0]);
  468. destroy(p, p + n);
  469. relocate(p, p + n,
  470. t_->size - (last -
  471. &(*t_)[0]));
  472. t_->size = static_cast<
  473. std::uint32_t>(t_->size - n);
  474. return p;
  475. }
  476. void
  477. array::
  478. push_back(value const& v)
  479. {
  480. emplace_back(v);
  481. }
  482. void
  483. array::
  484. push_back(value&& v)
  485. {
  486. emplace_back(std::move(v));
  487. }
  488. void
  489. array::
  490. pop_back() noexcept
  491. {
  492. auto const p = &back();
  493. destroy(p, p + 1);
  494. --t_->size;
  495. }
  496. void
  497. array::
  498. resize(std::size_t count)
  499. {
  500. if(count <= t_->size)
  501. {
  502. // shrink
  503. destroy(
  504. &(*t_)[0] + count,
  505. &(*t_)[0] + t_->size);
  506. t_->size = static_cast<
  507. std::uint32_t>(count);
  508. return;
  509. }
  510. reserve(count);
  511. auto p = &(*t_)[t_->size];
  512. auto const end = &(*t_)[count];
  513. while(p != end)
  514. ::new(p++) value(sp_);
  515. t_->size = static_cast<
  516. std::uint32_t>(count);
  517. }
  518. void
  519. array::
  520. resize(
  521. std::size_t count,
  522. value const& v)
  523. {
  524. if(count <= size())
  525. {
  526. // shrink
  527. destroy(
  528. data() + count,
  529. data() + size());
  530. t_->size = static_cast<
  531. std::uint32_t>(count);
  532. return;
  533. }
  534. count -= size();
  535. revert_insert r(
  536. end(), count, *this);
  537. while(count--)
  538. {
  539. ::new(r.p) value(v, sp_);
  540. ++r.p;
  541. }
  542. r.commit();
  543. }
  544. void
  545. array::
  546. swap(array& other)
  547. {
  548. if(*sp_ == *other.sp_)
  549. {
  550. t_ = detail::exchange(
  551. other.t_, t_);
  552. return;
  553. }
  554. array temp1(
  555. std::move(*this),
  556. other.storage());
  557. array temp2(
  558. std::move(other),
  559. this->storage());
  560. this->~array();
  561. ::new(this) array(
  562. pilfer(temp2));
  563. other.~array();
  564. ::new(&other) array(
  565. pilfer(temp1));
  566. }
  567. //----------------------------------------------------------
  568. //
  569. // Private
  570. //
  571. //----------------------------------------------------------
  572. std::size_t
  573. array::
  574. growth(
  575. std::size_t new_size) const
  576. {
  577. if(new_size > max_size())
  578. detail::throw_length_error( "array too large" );
  579. std::size_t const old = capacity();
  580. if(old > max_size() - old / 2)
  581. return new_size;
  582. std::size_t const g =
  583. old + old / 2; // 1.5x
  584. if(g < new_size)
  585. return new_size;
  586. return g;
  587. }
  588. // precondition: new_capacity > capacity()
  589. void
  590. array::
  591. reserve_impl(
  592. std::size_t new_capacity)
  593. {
  594. BOOST_ASSERT(
  595. new_capacity > t_->capacity);
  596. auto t = table::allocate(
  597. growth(new_capacity), sp_);
  598. relocate(
  599. &(*t)[0],
  600. &(*t_)[0],
  601. t_->size);
  602. t->size = t_->size;
  603. t = detail::exchange(t_, t);
  604. table::deallocate(t, sp_);
  605. }
  606. // precondition: pv is not aliased
  607. value&
  608. array::
  609. push_back(
  610. pilfered<value> pv)
  611. {
  612. auto const n = t_->size;
  613. if(n < t_->capacity)
  614. {
  615. // fast path
  616. auto& v = *::new(
  617. &(*t_)[n]) value(pv);
  618. ++t_->size;
  619. return v;
  620. }
  621. auto const t =
  622. detail::exchange(t_,
  623. table::allocate(
  624. growth(n + 1),
  625. sp_));
  626. auto& v = *::new(
  627. &(*t_)[n]) value(pv);
  628. relocate(
  629. &(*t_)[0],
  630. &(*t)[0],
  631. n);
  632. t_->size = n + 1;
  633. table::deallocate(t, sp_);
  634. return v;
  635. }
  636. // precondition: pv is not aliased
  637. auto
  638. array::
  639. insert(
  640. const_iterator pos,
  641. pilfered<value> pv) ->
  642. iterator
  643. {
  644. BOOST_ASSERT(
  645. pos >= begin() &&
  646. pos <= end());
  647. std::size_t const n =
  648. t_->size;
  649. std::size_t const i =
  650. pos - &(*t_)[0];
  651. if(n < t_->capacity)
  652. {
  653. // fast path
  654. auto const p =
  655. &(*t_)[i];
  656. relocate(
  657. p + 1,
  658. p,
  659. n - i);
  660. ::new(p) value(pv);
  661. ++t_->size;
  662. return p;
  663. }
  664. auto t =
  665. table::allocate(
  666. growth(n + 1), sp_);
  667. auto const p = &(*t)[i];
  668. ::new(p) value(pv);
  669. relocate(
  670. &(*t)[0],
  671. &(*t_)[0],
  672. i);
  673. relocate(
  674. p + 1,
  675. &(*t_)[i],
  676. n - i);
  677. t->size = static_cast<
  678. std::uint32_t>(size() + 1);
  679. t = detail::exchange(t_, t);
  680. table::deallocate(t, sp_);
  681. return p;
  682. }
  683. //----------------------------------------------------------
  684. bool
  685. array::
  686. equal(
  687. array const& other) const noexcept
  688. {
  689. if(size() != other.size())
  690. return false;
  691. for(std::size_t i = 0; i < size(); ++i)
  692. if((*this)[i] != other[i])
  693. return false;
  694. return true;
  695. }
  696. } // namespace json
  697. } // namespace boost
  698. //----------------------------------------------------------
  699. //
  700. // std::hash specialization
  701. //
  702. //----------------------------------------------------------
  703. std::size_t
  704. std::hash<::boost::json::array>::operator()(
  705. ::boost::json::array const& ja) const noexcept
  706. {
  707. return ::boost::hash< ::boost::json::array >()( ja );
  708. }
  709. //----------------------------------------------------------
  710. #endif