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