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

Generated by: LCOV version 2.1