array.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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_HPP
  10. #define BOOST_JSON_IMPL_ARRAY_HPP
  11. #include <boost/json/value.hpp>
  12. #include <boost/json/detail/except.hpp>
  13. #include <algorithm>
  14. #include <stdexcept>
  15. #include <type_traits>
  16. namespace boost {
  17. namespace json {
  18. //----------------------------------------------------------
  19. struct alignas(value)
  20. array::table
  21. {
  22. std::uint32_t size = 0;
  23. std::uint32_t capacity = 0;
  24. constexpr table();
  25. value&
  26. operator[](std::size_t pos) noexcept
  27. {
  28. return (reinterpret_cast<
  29. value*>(this + 1))[pos];
  30. }
  31. BOOST_JSON_DECL
  32. static
  33. table*
  34. allocate(
  35. std::size_t capacity,
  36. storage_ptr const& sp);
  37. BOOST_JSON_DECL
  38. static
  39. void
  40. deallocate(
  41. table* p,
  42. storage_ptr const& sp);
  43. };
  44. //----------------------------------------------------------
  45. class array::revert_construct
  46. {
  47. array* arr_;
  48. public:
  49. explicit
  50. revert_construct(
  51. array& arr) noexcept
  52. : arr_(&arr)
  53. {
  54. }
  55. ~revert_construct()
  56. {
  57. if(! arr_)
  58. return;
  59. arr_->destroy();
  60. }
  61. void
  62. commit() noexcept
  63. {
  64. arr_ = nullptr;
  65. }
  66. };
  67. //----------------------------------------------------------
  68. class array::revert_insert
  69. {
  70. array* arr_;
  71. std::size_t const i_;
  72. std::size_t const n_;
  73. public:
  74. value* p;
  75. BOOST_JSON_DECL
  76. revert_insert(
  77. const_iterator pos,
  78. std::size_t n,
  79. array& arr);
  80. BOOST_JSON_DECL
  81. ~revert_insert();
  82. value*
  83. commit() noexcept
  84. {
  85. auto it =
  86. arr_->data() + i_;
  87. arr_ = nullptr;
  88. return it;
  89. }
  90. };
  91. //----------------------------------------------------------
  92. void
  93. array::
  94. relocate(
  95. value* dest,
  96. value* src,
  97. std::size_t n) noexcept
  98. {
  99. if(n == 0)
  100. return;
  101. std::memmove(
  102. static_cast<void*>(dest),
  103. static_cast<void const*>(src),
  104. n * sizeof(value));
  105. }
  106. //----------------------------------------------------------
  107. //
  108. // Construction
  109. //
  110. //----------------------------------------------------------
  111. template<class InputIt, class>
  112. array::
  113. array(
  114. InputIt first, InputIt last,
  115. storage_ptr sp)
  116. : array(
  117. first, last,
  118. std::move(sp),
  119. iter_cat<InputIt>{})
  120. {
  121. BOOST_STATIC_ASSERT(
  122. std::is_constructible<value,
  123. decltype(*first)>::value);
  124. }
  125. //----------------------------------------------------------
  126. //
  127. // Modifiers
  128. //
  129. //----------------------------------------------------------
  130. template<class InputIt, class>
  131. auto
  132. array::
  133. insert(
  134. const_iterator pos,
  135. InputIt first, InputIt last) ->
  136. iterator
  137. {
  138. BOOST_STATIC_ASSERT(
  139. std::is_constructible<value,
  140. decltype(*first)>::value);
  141. return insert(pos, first, last,
  142. iter_cat<InputIt>{});
  143. }
  144. template<class Arg>
  145. auto
  146. array::
  147. emplace(
  148. const_iterator pos,
  149. Arg&& arg) ->
  150. iterator
  151. {
  152. BOOST_ASSERT(
  153. pos >= begin() &&
  154. pos <= end());
  155. value jv(
  156. std::forward<Arg>(arg),
  157. storage());
  158. return insert(pos, pilfer(jv));
  159. }
  160. template<class Arg>
  161. value&
  162. array::
  163. emplace_back(Arg&& arg)
  164. {
  165. value jv(
  166. std::forward<Arg>(arg),
  167. storage());
  168. return push_back(pilfer(jv));
  169. }
  170. //----------------------------------------------------------
  171. //
  172. // Element access
  173. //
  174. //----------------------------------------------------------
  175. value&
  176. array::
  177. at(std::size_t pos, source_location const& loc) &
  178. {
  179. auto const& self = *this;
  180. return const_cast< value& >( self.at(pos, loc) );
  181. }
  182. value&&
  183. array::
  184. at(std::size_t pos, source_location const& loc) &&
  185. {
  186. return std::move( at(pos, loc) );
  187. }
  188. value&
  189. array::
  190. operator[](std::size_t pos) & noexcept
  191. {
  192. BOOST_ASSERT(pos < t_->size);
  193. return (*t_)[pos];
  194. }
  195. value&&
  196. array::
  197. operator[](std::size_t pos) && noexcept
  198. {
  199. return std::move( (*this)[pos] );
  200. }
  201. value const&
  202. array::
  203. operator[](std::size_t pos) const& noexcept
  204. {
  205. BOOST_ASSERT(pos < t_->size);
  206. return (*t_)[pos];
  207. }
  208. value&
  209. array::
  210. front() & noexcept
  211. {
  212. BOOST_ASSERT(t_->size > 0);
  213. return (*t_)[0];
  214. }
  215. value&&
  216. array::
  217. front() && noexcept
  218. {
  219. return std::move( front() );
  220. }
  221. value const&
  222. array::
  223. front() const& noexcept
  224. {
  225. BOOST_ASSERT(t_->size > 0);
  226. return (*t_)[0];
  227. }
  228. value&
  229. array::
  230. back() & noexcept
  231. {
  232. BOOST_ASSERT(
  233. t_->size > 0);
  234. return (*t_)[t_->size - 1];
  235. }
  236. value&&
  237. array::
  238. back() && noexcept
  239. {
  240. return std::move( back() );
  241. }
  242. value const&
  243. array::
  244. back() const& noexcept
  245. {
  246. BOOST_ASSERT(
  247. t_->size > 0);
  248. return (*t_)[t_->size - 1];
  249. }
  250. value*
  251. array::
  252. data() noexcept
  253. {
  254. return &(*t_)[0];
  255. }
  256. value const*
  257. array::
  258. data() const noexcept
  259. {
  260. return &(*t_)[0];
  261. }
  262. value const*
  263. array::
  264. if_contains(
  265. std::size_t pos) const noexcept
  266. {
  267. if( pos < t_->size )
  268. return &(*t_)[pos];
  269. return nullptr;
  270. }
  271. value*
  272. array::
  273. if_contains(
  274. std::size_t pos) noexcept
  275. {
  276. if( pos < t_->size )
  277. return &(*t_)[pos];
  278. return nullptr;
  279. }
  280. //----------------------------------------------------------
  281. //
  282. // Iterators
  283. //
  284. //----------------------------------------------------------
  285. auto
  286. array::
  287. begin() noexcept ->
  288. iterator
  289. {
  290. return &(*t_)[0];
  291. }
  292. auto
  293. array::
  294. begin() const noexcept ->
  295. const_iterator
  296. {
  297. return &(*t_)[0];
  298. }
  299. auto
  300. array::
  301. cbegin() const noexcept ->
  302. const_iterator
  303. {
  304. return &(*t_)[0];
  305. }
  306. auto
  307. array::
  308. end() noexcept ->
  309. iterator
  310. {
  311. return &(*t_)[t_->size];
  312. }
  313. auto
  314. array::
  315. end() const noexcept ->
  316. const_iterator
  317. {
  318. return &(*t_)[t_->size];
  319. }
  320. auto
  321. array::
  322. cend() const noexcept ->
  323. const_iterator
  324. {
  325. return &(*t_)[t_->size];
  326. }
  327. auto
  328. array::
  329. rbegin() noexcept ->
  330. reverse_iterator
  331. {
  332. return reverse_iterator(end());
  333. }
  334. auto
  335. array::
  336. rbegin() const noexcept ->
  337. const_reverse_iterator
  338. {
  339. return const_reverse_iterator(end());
  340. }
  341. auto
  342. array::
  343. crbegin() const noexcept ->
  344. const_reverse_iterator
  345. {
  346. return const_reverse_iterator(end());
  347. }
  348. auto
  349. array::
  350. rend() noexcept ->
  351. reverse_iterator
  352. {
  353. return reverse_iterator(begin());
  354. }
  355. auto
  356. array::
  357. rend() const noexcept ->
  358. const_reverse_iterator
  359. {
  360. return const_reverse_iterator(begin());
  361. }
  362. auto
  363. array::
  364. crend() const noexcept ->
  365. const_reverse_iterator
  366. {
  367. return const_reverse_iterator(begin());
  368. }
  369. //----------------------------------------------------------
  370. //
  371. // Capacity
  372. //
  373. //----------------------------------------------------------
  374. std::size_t
  375. array::
  376. size() const noexcept
  377. {
  378. return t_->size;
  379. }
  380. constexpr
  381. std::size_t
  382. array::
  383. max_size() noexcept
  384. {
  385. // max_size depends on the address model
  386. using min = std::integral_constant<std::size_t,
  387. (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
  388. return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
  389. min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
  390. }
  391. std::size_t
  392. array::
  393. capacity() const noexcept
  394. {
  395. return t_->capacity;
  396. }
  397. bool
  398. array::
  399. empty() const noexcept
  400. {
  401. return t_->size == 0;
  402. }
  403. void
  404. array::
  405. reserve(
  406. std::size_t new_capacity)
  407. {
  408. // never shrink
  409. if(new_capacity <= t_->capacity)
  410. return;
  411. reserve_impl(new_capacity);
  412. }
  413. //----------------------------------------------------------
  414. //
  415. // private
  416. //
  417. //----------------------------------------------------------
  418. template<class InputIt>
  419. array::
  420. array(
  421. InputIt first, InputIt last,
  422. storage_ptr sp,
  423. std::input_iterator_tag)
  424. : sp_(std::move(sp))
  425. , t_(&empty_)
  426. {
  427. revert_construct r(*this);
  428. while(first != last)
  429. {
  430. reserve(size() + 1);
  431. ::new(end()) value(
  432. *first++, sp_);
  433. ++t_->size;
  434. }
  435. r.commit();
  436. }
  437. template<class InputIt>
  438. array::
  439. array(
  440. InputIt first, InputIt last,
  441. storage_ptr sp,
  442. std::forward_iterator_tag)
  443. : sp_(std::move(sp))
  444. {
  445. std::size_t n =
  446. std::distance(first, last);
  447. if( n == 0 )
  448. {
  449. t_ = &empty_;
  450. return;
  451. }
  452. t_ = table::allocate(n, sp_);
  453. t_->size = 0;
  454. revert_construct r(*this);
  455. while(n--)
  456. {
  457. ::new(end()) value(
  458. *first++, sp_);
  459. ++t_->size;
  460. }
  461. r.commit();
  462. }
  463. template<class InputIt>
  464. auto
  465. array::
  466. insert(
  467. const_iterator pos,
  468. InputIt first, InputIt last,
  469. std::input_iterator_tag) ->
  470. iterator
  471. {
  472. BOOST_ASSERT(
  473. pos >= begin() && pos <= end());
  474. if(first == last)
  475. return data() + (pos - data());
  476. array temp(first, last, sp_);
  477. revert_insert r(
  478. pos, temp.size(), *this);
  479. relocate(
  480. r.p,
  481. temp.data(),
  482. temp.size());
  483. temp.t_->size = 0;
  484. return r.commit();
  485. }
  486. template<class InputIt>
  487. auto
  488. array::
  489. insert(
  490. const_iterator pos,
  491. InputIt first, InputIt last,
  492. std::forward_iterator_tag) ->
  493. iterator
  494. {
  495. std::size_t n =
  496. std::distance(first, last);
  497. revert_insert r(pos, n, *this);
  498. while(n--)
  499. {
  500. ::new(r.p) value(*first++);
  501. ++r.p;
  502. }
  503. return r.commit();
  504. }
  505. } // namespace json
  506. } // namespace boost
  507. #endif