LCOV - code coverage report
Current view: top level - json/impl - array.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 163 163
Test Date: 2026-01-02 17:31:39 Functions: 100.0 % 78 78

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

Generated by: LCOV version 2.1