LCOV - code coverage report
Current view: top level - json/impl - array.ipp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 389 389
Test Date: 2025-12-23 17:20:51 Functions: 100.0 % 40 40

            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_IPP
      11              : #define BOOST_JSON_IMPL_ARRAY_IPP
      12              : 
      13              : #include <boost/container_hash/hash.hpp>
      14              : #include <boost/json/array.hpp>
      15              : #include <boost/json/pilfer.hpp>
      16              : #include <boost/json/detail/except.hpp>
      17              : #include <cstdlib>
      18              : #include <limits>
      19              : #include <new>
      20              : #include <utility>
      21              : 
      22              : namespace boost {
      23              : namespace json {
      24              : 
      25              : //----------------------------------------------------------
      26              : 
      27              : constexpr array::table::table() = default;
      28              : 
      29              : // empty arrays point here
      30              : BOOST_JSON_REQUIRE_CONST_INIT
      31              : array::table array::empty_;
      32              : 
      33              : auto
      34         2578 : array::
      35              : table::
      36              : allocate(
      37              :     std::size_t capacity,
      38              :     storage_ptr const& sp) ->
      39              :         table*
      40              : {
      41         2578 :     BOOST_ASSERT(capacity > 0);
      42         2578 :     if(capacity > array::max_size())
      43              :     {
      44              :         BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
      45            2 :         detail::throw_system_error( error::array_too_large, &loc );
      46              :     }
      47              :     auto p = reinterpret_cast<
      48         2576 :         table*>(sp->allocate(
      49              :             sizeof(table) +
      50         2576 :                 capacity * sizeof(value),
      51              :             alignof(value)));
      52         2437 :     p->capacity = static_cast<
      53              :         std::uint32_t>(capacity);
      54         2437 :     return p;
      55              : }
      56              : 
      57              : void
      58         4503 : array::
      59              : table::
      60              : deallocate(
      61              :     table* p,
      62              :     storage_ptr const& sp)
      63              : {
      64         4503 :     if(p->capacity == 0)
      65         2070 :         return;
      66         2433 :     sp->deallocate(p,
      67              :         sizeof(table) +
      68         2433 :             p->capacity * sizeof(value),
      69              :         alignof(value));
      70              : }
      71              : 
      72              : //----------------------------------------------------------
      73              : 
      74           37 : array::
      75              : revert_insert::
      76              : revert_insert(
      77              :     const_iterator pos,
      78              :     std::size_t n,
      79           37 :     array& arr)
      80           37 :     : arr_(&arr)
      81           37 :     , i_(pos - arr_->data())
      82           37 :     , n_(n)
      83              : {
      84           37 :     BOOST_ASSERT(
      85              :         pos >= arr_->begin() &&
      86              :         pos <= arr_->end());
      87           74 :     if( n_ <= arr_->capacity() -
      88           37 :         arr_->size())
      89              :     {
      90              :         // fast path
      91            2 :         p = arr_->data() + i_;
      92            2 :         if(n_ == 0)
      93            1 :             return;
      94            1 :         relocate(
      95            1 :             p + n_,
      96              :             p,
      97            1 :             arr_->size() - i_);
      98            1 :         arr_->t_->size = static_cast<
      99              :             std::uint32_t>(
     100            1 :                 arr_->t_->size + n_);
     101            1 :         return;
     102              :     }
     103           35 :     if(n_ > max_size() - arr_->size())
     104              :     {
     105              :         BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
     106            1 :         detail::throw_system_error( error::array_too_large, &loc );
     107              :     }
     108           34 :     auto t = table::allocate(
     109           34 :         arr_->growth(arr_->size() + n_),
     110           34 :             arr_->sp_);
     111           24 :     t->size = static_cast<std::uint32_t>(
     112           24 :         arr_->size() + n_);
     113           24 :     p = &(*t)[0] + i_;
     114           24 :     relocate(
     115           24 :         &(*t)[0],
     116           24 :         arr_->data(),
     117           24 :         i_);
     118           24 :     relocate(
     119           24 :         &(*t)[i_ + n_],
     120           24 :         arr_->data() + i_,
     121           24 :         arr_->size() - i_);
     122           24 :     t = detail::exchange(arr_->t_, t);
     123           24 :     table::deallocate(t, arr_->sp_);
     124              : }
     125              : 
     126           26 : array::
     127              : revert_insert::
     128            8 : ~revert_insert()
     129              : {
     130           26 :     if(! arr_)
     131           18 :         return;
     132            8 :     BOOST_ASSERT(n_ != 0);
     133              :     auto const pos =
     134            8 :         arr_->data() + i_;
     135            8 :     arr_->destroy(pos, p);
     136            8 :     arr_->t_->size = static_cast<
     137              :         std::uint32_t>(
     138            8 :             arr_->t_->size - n_);
     139            8 :     relocate(
     140              :         pos,
     141            8 :         pos + n_,
     142            8 :         arr_->size() - i_);
     143           26 : }
     144              : 
     145              : //----------------------------------------------------------
     146              : 
     147              : void
     148           25 : array::
     149              : destroy(
     150              :     value* first, value* last) noexcept
     151              : {
     152           25 :     if(sp_.is_not_shared_and_deallocate_is_trivial())
     153            1 :         return;
     154           50 :     while(last-- != first)
     155           26 :         last->~value();
     156              : }
     157              : 
     158              : void
     159         3732 : array::
     160              : destroy() noexcept
     161              : {
     162         3732 :     if(sp_.is_not_shared_and_deallocate_is_trivial())
     163            5 :         return;
     164         3727 :     auto last = end();
     165         3727 :     auto const first = begin();
     166        20974 :     while(last-- != first)
     167        17247 :         last->~value();
     168         3727 :     table::deallocate(t_, sp_);
     169              : }
     170              : 
     171              : //----------------------------------------------------------
     172              : //
     173              : // Special Members
     174              : //
     175              : //----------------------------------------------------------
     176              : 
     177         2120 : array::
     178         2120 : array(detail::unchecked_array&& ua)
     179         2120 :     : sp_(ua.storage())
     180              : {
     181              :     BOOST_STATIC_ASSERT(
     182              :         alignof(table) == alignof(value));
     183         2120 :     if(ua.size() == 0)
     184              :     {
     185          819 :         t_ = &empty_;
     186          819 :         return;
     187              :     }
     188         1301 :     t_= table::allocate(
     189         1301 :         ua.size(), sp_);
     190         1263 :     t_->size = static_cast<
     191         1263 :         std::uint32_t>(ua.size());
     192         1263 :     ua.relocate(data());
     193           38 : }
     194              : 
     195         3668 : array::
     196              : ~array() noexcept
     197              : {
     198         3668 :     destroy();
     199         3668 : }
     200              : 
     201           35 : array::
     202              : array(
     203              :     std::size_t count,
     204              :     value const& v,
     205           35 :     storage_ptr sp)
     206           35 :     : sp_(std::move(sp))
     207              : {
     208           35 :     if(count == 0)
     209              :     {
     210            1 :         t_ = &empty_;
     211            1 :         return;
     212              :     }
     213           63 :     t_= table::allocate(
     214           34 :         count, sp_);
     215           29 :     t_->size = 0;
     216           29 :     revert_construct r(*this);
     217           98 :     while(count--)
     218              :     {
     219          101 :         ::new(end()) value(v, sp_);
     220           69 :         ++t_->size;
     221              :     }
     222           13 :     r.commit();
     223           50 : }
     224              : 
     225           16 : array::
     226              : array(
     227              :     std::size_t count,
     228           16 :     storage_ptr sp)
     229           16 :     : sp_(std::move(sp))
     230              : {
     231           16 :     if(count == 0)
     232              :     {
     233            1 :         t_ = &empty_;
     234            1 :         return;
     235              :     }
     236           26 :     t_ = table::allocate(
     237           15 :         count, sp_);
     238           11 :     t_->size = static_cast<
     239              :         std::uint32_t>(count);
     240           11 :     auto p = data();
     241              :     do
     242              :     {
     243           34 :         ::new(p++) value(sp_);
     244              :     }
     245           34 :     while(--count);
     246            4 : }
     247              : 
     248            8 : array::
     249            8 : array(array const& other)
     250            8 :     : array(other, other.sp_)
     251              : {
     252            8 : }
     253              : 
     254          153 : array::
     255              : array(
     256              :     array const& other,
     257          153 :     storage_ptr sp)
     258          153 :     : sp_(std::move(sp))
     259              : {
     260          153 :     if(other.empty())
     261              :     {
     262           14 :         t_ = &empty_;
     263           14 :         return;
     264              :     }
     265          139 :     t_ = table::allocate(
     266          139 :         other.size(), sp_);
     267          120 :     t_->size = 0;
     268          120 :     revert_construct r(*this);
     269          120 :     auto src = other.data();
     270          120 :     auto dest = data();
     271          120 :     auto const n = other.size();
     272              :     do
     273              :     {
     274           13 :         ::new(dest++) value(
     275         2412 :             *src++, sp_);
     276         2373 :         ++t_->size;
     277              :     }
     278         2373 :     while(t_->size < n);
     279          107 :     r.commit();
     280          152 : }
     281              : 
     282          274 : array::
     283              : array(
     284              :     array&& other,
     285          274 :     storage_ptr sp)
     286          274 :     : sp_(std::move(sp))
     287              : {
     288          274 :     if(*sp_ == *other.sp_)
     289              :     {
     290              :         // same resource
     291          502 :         t_ = detail::exchange(
     292          251 :             other.t_, &empty_);
     293          255 :         return;
     294              :     }
     295           23 :     else if(other.empty())
     296              :     {
     297            4 :         t_ = &empty_;
     298            4 :         return;
     299              :     }
     300              :     // copy
     301           19 :     t_ = table::allocate(
     302           19 :         other.size(), sp_);
     303           14 :     t_->size = 0;
     304           14 :     revert_construct r(*this);
     305           14 :     auto src = other.data();
     306           14 :     auto dest = data();
     307           14 :     auto const n = other.size();
     308              :     do
     309              :     {
     310            6 :         ::new(dest++) value(
     311           48 :             *src++, sp_);
     312           30 :         ++t_->size;
     313              :     }
     314           30 :     while(t_->size < n);
     315            8 :     r.commit();
     316           25 : }
     317              : 
     318          244 : array::
     319              : array(
     320              :     std::initializer_list<
     321              :         value_ref> init,
     322          244 :     storage_ptr sp)
     323          244 :     : sp_(std::move(sp))
     324              : {
     325          244 :     if(init.size() == 0)
     326              :     {
     327            5 :         t_ = &empty_;
     328            5 :         return;
     329              :     }
     330          239 :     t_ = table::allocate(
     331          239 :         init.size(), sp_);
     332          212 :     t_->size = 0;
     333          212 :     revert_construct r(*this);
     334          212 :     value_ref::write_array(
     335          212 :         data(), init, sp_);
     336          197 :     t_->size = static_cast<
     337          197 :         std::uint32_t>(init.size());
     338          197 :     r.commit();
     339          254 : }
     340              : 
     341              : //----------------------------------------------------------
     342              : 
     343              : array&
     344           16 : array::
     345              : operator=(array const& other)
     346              : {
     347           32 :     array(other,
     348           12 :         storage()).swap(*this);
     349           12 :     return *this;
     350              : }
     351              : 
     352              : array&
     353            7 : array::
     354              : operator=(array&& other)
     355              : {
     356           14 :     array(std::move(other),
     357            5 :         storage()).swap(*this);
     358            5 :     return *this;
     359              : }
     360              : 
     361              : array&
     362            9 : array::
     363              : operator=(
     364              :     std::initializer_list<value_ref> init)
     365              : {
     366           18 :     array(init,
     367            5 :         storage()).swap(*this);
     368            5 :     return *this;
     369              : }
     370              : 
     371              : //----------------------------------------------------------
     372              : //
     373              : // Element access
     374              : //
     375              : //----------------------------------------------------------
     376              : 
     377              : system::result<value&>
     378           12 : array::try_at(std::size_t pos) noexcept
     379              : {
     380           12 :     if(pos >= t_->size)
     381              :     {
     382            8 :         system::error_code ec;
     383            8 :         BOOST_JSON_FAIL(ec, error::out_of_range);
     384            8 :         return ec;
     385              :     }
     386            4 :     return (*t_)[pos];
     387              : }
     388              : 
     389              : system::result<value const&>
     390          106 : array::try_at(std::size_t pos) const noexcept
     391              : {
     392          106 :     if(pos >= t_->size)
     393              :     {
     394           12 :         system::error_code ec;
     395           12 :         BOOST_JSON_FAIL(ec, error::out_of_range);
     396           12 :         return ec;
     397              :     }
     398           94 :     return (*t_)[pos];
     399              : }
     400              : 
     401              : value const&
     402          100 : array::
     403              : array::at(std::size_t pos, source_location const& loc) const&
     404              : {
     405          100 :     return try_at(pos).value(loc);
     406              : }
     407              : 
     408              : //----------------------------------------------------------
     409              : //
     410              : // Capacity
     411              : //
     412              : //----------------------------------------------------------
     413              : 
     414              : void
     415            6 : array::
     416              : shrink_to_fit() noexcept
     417              : {
     418            6 :     if(capacity() <= size())
     419            2 :         return;
     420            4 :     if(size() == 0)
     421              :     {
     422            1 :         table::deallocate(t_, sp_);
     423            1 :         t_ = &empty_;
     424            1 :         return;
     425              :     }
     426              : 
     427              : #ifndef BOOST_NO_EXCEPTIONS
     428              :     try
     429              :     {
     430              : #endif
     431            3 :         auto t = table::allocate(
     432            3 :             size(), sp_);
     433            4 :         relocate(
     434            2 :             &(*t)[0],
     435              :             data(),
     436              :             size());
     437            2 :         t->size = static_cast<
     438            2 :             std::uint32_t>(size());
     439            2 :         t = detail::exchange(
     440            2 :             t_, t);
     441            2 :         table::deallocate(t, sp_);
     442              : #ifndef BOOST_NO_EXCEPTIONS
     443              :     }
     444            1 :     catch(...)
     445              :     {
     446              :         // eat the exception
     447            1 :         return;
     448            1 :     }
     449              : #endif
     450              : }
     451              : 
     452              : //----------------------------------------------------------
     453              : //
     454              : // Modifiers
     455              : //
     456              : //----------------------------------------------------------
     457              : 
     458              : void
     459            4 : array::
     460              : clear() noexcept
     461              : {
     462            4 :     if(size() == 0)
     463            1 :         return;
     464            3 :     destroy(
     465              :         begin(), end());
     466            3 :     t_->size = 0;
     467              : }
     468              : 
     469              : auto
     470            3 : array::
     471              : insert(
     472              :     const_iterator pos,
     473              :     value const& v) ->
     474              :         iterator
     475              : {
     476            3 :     return emplace(pos, v);
     477              : }
     478              : 
     479              : auto
     480            3 : array::
     481              : insert(
     482              :     const_iterator pos,
     483              :     value&& v) ->
     484              :         iterator
     485              : {
     486            3 :     return emplace(pos, std::move(v));
     487              : }
     488              : 
     489              : auto
     490           10 : array::
     491              : insert(
     492              :     const_iterator pos,
     493              :     std::size_t count,
     494              :     value const& v) ->
     495              :         iterator
     496              : {
     497              :     revert_insert r(
     498           10 :         pos, count, *this);
     499           17 :     while(count--)
     500              :     {
     501           16 :         ::new(r.p) value(v, sp_);
     502           10 :         ++r.p;
     503              :     }
     504            8 :     return r.commit();
     505            7 : }
     506              : 
     507              : auto
     508            3 : array::
     509              : insert(
     510              :     const_iterator pos,
     511              :     std::initializer_list<
     512              :         value_ref> init) ->
     513              :     iterator
     514              : {
     515              :     revert_insert r(
     516            3 :         pos, init.size(), *this);
     517            2 :     value_ref::write_array(
     518            2 :         r.p, init, sp_);
     519            2 :     return r.commit();
     520            2 : }
     521              : 
     522              : auto
     523            7 : array::
     524              : erase(
     525              :     const_iterator pos) noexcept ->
     526              :     iterator
     527              : {
     528            7 :     BOOST_ASSERT(
     529              :         pos >= begin() &&
     530              :         pos <= end());
     531            7 :     return erase(pos, pos + 1);
     532              : }
     533              : 
     534              : auto
     535            8 : array::
     536              : erase(
     537              :     const_iterator first,
     538              :     const_iterator last) noexcept ->
     539              :         iterator
     540              : {
     541            8 :     BOOST_ASSERT(
     542              :         first >= begin() &&
     543              :         last >= first &&
     544              :         last <= end());
     545            8 :     std::size_t const n =
     546            8 :         last - first;
     547            8 :     auto const p = &(*t_)[0] +
     548            8 :         (first - &(*t_)[0]);
     549            8 :     destroy(p, p + n);
     550            8 :     relocate(p, p + n,
     551            8 :         t_->size - (last -
     552            8 :             &(*t_)[0]));
     553            8 :     t_->size = static_cast<
     554            8 :         std::uint32_t>(t_->size - n);
     555            8 :     return p;
     556              : }
     557              : 
     558              : void
     559            4 : array::
     560              : push_back(value const& v)
     561              : {
     562            4 :     emplace_back(v);
     563            2 : }
     564              : 
     565              : void
     566            9 : array::
     567              : push_back(value&& v)
     568              : {
     569            9 :     emplace_back(std::move(v));
     570            7 : }
     571              : 
     572              : void
     573            3 : array::
     574              : pop_back() noexcept
     575              : {
     576            3 :     auto const p = &back();
     577            3 :     destroy(p, p + 1);
     578            3 :     --t_->size;
     579            3 : }
     580              : 
     581              : void
     582           15 : array::
     583              : resize(std::size_t count)
     584              : {
     585           15 :     if(count <= t_->size)
     586              :     {
     587              :         // shrink
     588            4 :         destroy(
     589            2 :             &(*t_)[0] + count,
     590            2 :             &(*t_)[0] + t_->size);
     591            2 :         t_->size = static_cast<
     592              :             std::uint32_t>(count);
     593            2 :         return;
     594              :     }
     595              : 
     596           13 :     reserve(count);
     597           12 :     auto p = &(*t_)[t_->size];
     598           12 :     auto const end = &(*t_)[count];
     599           32 :     while(p != end)
     600           20 :         ::new(p++) value(sp_);
     601           12 :     t_->size = static_cast<
     602              :         std::uint32_t>(count);
     603              : }
     604              : 
     605              : void
     606            7 : array::
     607              : resize(
     608              :     std::size_t count,
     609              :     value const& v)
     610              : {
     611            7 :     if(count <= size())
     612              :     {
     613              :         // shrink
     614            2 :         destroy(
     615            1 :             data() + count,
     616            1 :             data() + size());
     617            1 :         t_->size = static_cast<
     618              :             std::uint32_t>(count);
     619            1 :         return;
     620              :     }
     621            6 :     count -= size();
     622              :     revert_insert r(
     623            6 :         end(), count, *this);
     624            9 :     while(count--)
     625              :     {
     626           12 :         ::new(r.p) value(v, sp_);
     627            4 :         ++r.p;
     628              :     }
     629            1 :     r.commit();
     630            5 : }
     631              : 
     632              : void
     633           28 : array::
     634              : swap(array& other)
     635              : {
     636           28 :     if(*sp_ == *other.sp_)
     637              :     {
     638           48 :         t_ = detail::exchange(
     639           24 :             other.t_, t_);
     640           24 :         return;
     641              :     }
     642              :     array temp1(
     643            4 :         std::move(*this),
     644            9 :         other.storage());
     645              :     array temp2(
     646            3 :         std::move(other),
     647            7 :         this->storage());
     648            2 :     this->~array();
     649            6 :     ::new(this) array(
     650            2 :         pilfer(temp2));
     651            2 :     other.~array();
     652            6 :     ::new(&other) array(
     653            2 :         pilfer(temp1));
     654            3 : }
     655              : 
     656              : //----------------------------------------------------------
     657              : //
     658              : // Private
     659              : //
     660              : //----------------------------------------------------------
     661              : 
     662              : std::size_t
     663          814 : array::
     664              : growth(
     665              :     std::size_t new_size) const
     666              : {
     667          814 :     if(new_size > max_size())
     668              :     {
     669              :         BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
     670            1 :         detail::throw_system_error( error::array_too_large, &loc );
     671              :     }
     672          813 :     std::size_t const old = capacity();
     673          813 :     if(old > max_size() - old / 2)
     674            1 :         return new_size;
     675          812 :     std::size_t const g =
     676          812 :         old + old / 2; // 1.5x
     677          812 :     if(g < new_size)
     678          732 :         return new_size;
     679           80 :     return g;
     680              : }
     681              : 
     682              : // precondition: new_capacity > capacity()
     683              : void
     684          702 : array::
     685              : reserve_impl(
     686              :     std::size_t new_capacity)
     687              : {
     688          702 :     BOOST_ASSERT(
     689              :         new_capacity > t_->capacity);
     690          701 :     auto t = table::allocate(
     691          702 :         growth(new_capacity), sp_);
     692          681 :     relocate(
     693          681 :         &(*t)[0],
     694          681 :         &(*t_)[0],
     695          681 :         t_->size);
     696          681 :     t->size = t_->size;
     697          681 :     t = detail::exchange(t_, t);
     698          681 :     table::deallocate(t, sp_);
     699          681 : }
     700              : 
     701              : // precondition: pv is not aliased
     702              : value&
     703         7686 : array::
     704              : push_back(
     705              :     pilfered<value> pv)
     706              : {
     707         7686 :     auto const n = t_->size;
     708         7686 :     if(n < t_->capacity)
     709              :     {
     710              :         // fast path
     711              :         auto& v = *::new(
     712         7619 :             &(*t_)[n]) value(pv);
     713         7619 :         ++t_->size;
     714         7619 :         return v;
     715              :     }
     716              :     auto const t =
     717           67 :         detail::exchange(t_,
     718              :             table::allocate(
     719           67 :                 growth(n + 1),
     720           67 :                     sp_));
     721              :     auto& v = *::new(
     722           62 :         &(*t_)[n]) value(pv);
     723           62 :     relocate(
     724           62 :         &(*t_)[0],
     725           62 :         &(*t)[0],
     726              :         n);
     727           62 :     t_->size = n + 1;
     728           62 :     table::deallocate(t, sp_);
     729           62 :     return v;
     730              : }
     731              : 
     732              : // precondition: pv is not aliased
     733              : auto
     734           12 : array::
     735              : insert(
     736              :     const_iterator pos,
     737              :     pilfered<value> pv) ->
     738              :         iterator
     739              : {
     740           12 :     BOOST_ASSERT(
     741              :         pos >= begin() &&
     742              :         pos <= end());
     743           12 :     std::size_t const n =
     744           12 :         t_->size;
     745              :     std::size_t const i =
     746           12 :         pos - &(*t_)[0];
     747           12 :     if(n < t_->capacity)
     748              :     {
     749              :         // fast path
     750              :         auto const p =
     751            1 :             &(*t_)[i];
     752            1 :         relocate(
     753              :             p + 1,
     754              :             p,
     755              :             n - i);
     756            1 :         ::new(p) value(pv);
     757            1 :         ++t_->size;
     758            1 :         return p;
     759              :     }
     760              :     auto t =
     761           11 :         table::allocate(
     762           11 :             growth(n + 1), sp_);
     763            6 :     auto const p = &(*t)[i];
     764            6 :     ::new(p) value(pv);
     765            6 :     relocate(
     766            6 :         &(*t)[0],
     767            6 :         &(*t_)[0],
     768              :         i);
     769            6 :     relocate(
     770              :         p + 1,
     771            6 :         &(*t_)[i],
     772              :         n - i);
     773            6 :     t->size = static_cast<
     774            6 :         std::uint32_t>(size() + 1);
     775            6 :     t = detail::exchange(t_, t);
     776            6 :     table::deallocate(t, sp_);
     777            6 :     return p;
     778              : }
     779              : 
     780              : //----------------------------------------------------------
     781              : 
     782              : bool
     783           88 : array::
     784              : equal(
     785              :     array const& other) const noexcept
     786              : {
     787           88 :     if(size() != other.size())
     788            2 :         return false;
     789         3284 :     for(std::size_t i = 0; i < size(); ++i)
     790         3204 :         if((*this)[i] != other[i])
     791            6 :             return false;
     792           80 :     return true;
     793              : }
     794              : 
     795              : } // namespace json
     796              : } // namespace boost
     797              : 
     798              : //----------------------------------------------------------
     799              : //
     800              : // std::hash specialization
     801              : //
     802              : //----------------------------------------------------------
     803              : 
     804              : std::size_t
     805           12 : std::hash<::boost::json::array>::operator()(
     806              :     ::boost::json::array const& ja) const noexcept
     807              : {
     808           12 :     return ::boost::hash< ::boost::json::array >()( ja );
     809              : }
     810              : 
     811              : //----------------------------------------------------------
     812              : 
     813              : #endif
        

Generated by: LCOV version 2.1