array.ipp 13 KB

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