LCOV - code coverage report
Current view: top level - json/impl - array.ipp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 389 389
Test Date: 2026-03-05 09:04:27 Functions: 100.0 % 40 40

           TLA  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 HIT        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.3