array.hpp 8.8 KB

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