LCOV - code coverage report
Current view: top level - json/detail - string_impl.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 73 73
Test Date: 2026-01-05 13:48:39 Functions: 100.0 % 28 28

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3              : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
       4              : //
       5              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7              : //
       8              : // Official repository: https://github.com/boostorg/json
       9              : //
      10              : 
      11              : #ifndef BOOST_JSON_DETAIL_STRING_IMPL_HPP
      12              : #define BOOST_JSON_DETAIL_STRING_IMPL_HPP
      13              : 
      14              : #include <boost/core/detail/static_assert.hpp>
      15              : #include <boost/json/detail/config.hpp>
      16              : #include <boost/json/kind.hpp>
      17              : #include <boost/json/storage_ptr.hpp>
      18              : #include <boost/json/detail/value.hpp>
      19              : #include <algorithm>
      20              : #include <iterator>
      21              : 
      22              : namespace boost {
      23              : namespace json {
      24              : 
      25              : class value;
      26              : class string;
      27              : 
      28              : namespace detail {
      29              : 
      30              : class string_impl
      31              : {
      32              :     struct table
      33              :     {
      34              :         std::uint32_t size;
      35              :         std::uint32_t capacity;
      36              :     };
      37              : 
      38              : #if BOOST_JSON_ARCH == 64
      39              :     static constexpr std::size_t sbo_chars_ = 14;
      40              : #elif BOOST_JSON_ARCH == 32
      41              :     static constexpr std::size_t sbo_chars_ = 10;
      42              : #else
      43              : # error Unknown architecture
      44              : #endif
      45              : 
      46              :     static
      47              :     constexpr
      48              :     kind
      49              :     short_string_ =
      50              :         static_cast<kind>(
      51              :             ((unsigned char)
      52              :             kind::string) | 0x80);
      53              : 
      54              :     static
      55              :     constexpr
      56              :     kind
      57              :     key_string_ =
      58              :         static_cast<kind>(
      59              :             ((unsigned char)
      60              :             kind::string) | 0x40);
      61              : 
      62              :     struct sbo
      63              :     {
      64              :         kind k; // must come first
      65              :         char buf[sbo_chars_ + 1];
      66              :     };
      67              : 
      68              :     struct pointer
      69              :     {
      70              :         kind k; // must come first
      71              :         table* t;
      72              :     };
      73              : 
      74              :     struct key
      75              :     {
      76              :         kind k; // must come first
      77              :         std::uint32_t n;
      78              :         char* s;
      79              :     };
      80              : 
      81              :     union
      82              :     {
      83              :         sbo s_;
      84              :         pointer p_;
      85              :         key k_;
      86              :     };
      87              : 
      88              : #if BOOST_JSON_ARCH == 64
      89              :     BOOST_CORE_STATIC_ASSERT( sizeof(sbo) <= 16 );
      90              :     BOOST_CORE_STATIC_ASSERT( sizeof(pointer) <= 16 );
      91              :     BOOST_CORE_STATIC_ASSERT( sizeof(key) <= 16 );
      92              : #elif BOOST_JSON_ARCH == 32
      93              :     BOOST_CORE_STATIC_ASSERT( sizeof(sbo) <= 24 );
      94              :     BOOST_CORE_STATIC_ASSERT( sizeof(pointer) <= 24 );
      95              :     BOOST_CORE_STATIC_ASSERT( sizeof(key) <= 24 );
      96              : #endif
      97              : 
      98              : public:
      99              :     static
     100              :     constexpr
     101              :     std::size_t
     102       153866 :     max_size() noexcept
     103              :     {
     104              :         // max_size depends on the address model
     105              :         using min = std::integral_constant<std::size_t,
     106              :             std::size_t(-1) - sizeof(table)>;
     107              :         return min::value < BOOST_JSON_MAX_STRING_SIZE ?
     108       153866 :             min::value : BOOST_JSON_MAX_STRING_SIZE;
     109              :     }
     110              : 
     111              :     BOOST_JSON_DECL
     112              :     string_impl() noexcept;
     113              : 
     114              :     BOOST_JSON_DECL
     115              :     string_impl(
     116              :         std::size_t new_size,
     117              :         storage_ptr const& sp);
     118              : 
     119              :     BOOST_JSON_DECL
     120              :     string_impl(
     121              :         key_t,
     122              :         string_view s,
     123              :         storage_ptr const& sp);
     124              : 
     125              :     BOOST_JSON_DECL
     126              :     string_impl(
     127              :         key_t,
     128              :         string_view s1,
     129              :         string_view s2,
     130              :         storage_ptr const& sp);
     131              : 
     132              :     BOOST_JSON_DECL
     133              :     string_impl(
     134              :         char** dest,
     135              :         std::size_t len,
     136              :         storage_ptr const& sp);
     137              : 
     138              :     template<class InputIt>
     139            8 :     string_impl(
     140              :         InputIt first,
     141              :         InputIt last,
     142              :         storage_ptr const& sp,
     143              :         std::random_access_iterator_tag)
     144            8 :         : string_impl(last - first, sp)
     145              :     {
     146            7 :         char* out = data();
     147              : #if defined(_MSC_VER) && _MSC_VER <= 1900
     148              :         while( first != last )
     149              :             *out++ = *first++;
     150              : #else
     151            7 :         std::copy(first, last, out);
     152              : #endif
     153            7 :     }
     154              : 
     155              :     template<class InputIt>
     156           38 :     string_impl(
     157              :         InputIt first,
     158              :         InputIt last,
     159              :         storage_ptr const& sp,
     160              :         std::input_iterator_tag)
     161           38 :         : string_impl(0, sp)
     162              :     {
     163              :         struct undo
     164              :         {
     165              :             string_impl* s;
     166              :             storage_ptr const& sp;
     167              : 
     168           38 :             ~undo()
     169              :             {
     170           38 :                 if(s)
     171            3 :                     s->destroy(sp);
     172           38 :             }
     173              :         };
     174              : 
     175           38 :         undo u{this, sp};
     176           38 :         auto dest = data();
     177          313 :         while(first != last)
     178              :         {
     179          278 :             if(size() < capacity())
     180          267 :                 size(size() + 1);
     181              :             else
     182           11 :                 dest = append(1, sp);
     183          275 :             *dest++ = *first++;
     184              :         }
     185           35 :         term(size());
     186           35 :         u.s = nullptr;
     187           38 :     }
     188              : 
     189              :     std::size_t
     190        98892 :     size() const noexcept
     191              :     {
     192        98892 :         return s_.k == kind::string ?
     193        64299 :             p_.t->size :
     194              :             sbo_chars_ -
     195        98892 :                 s_.buf[sbo_chars_];
     196              :     }
     197              : 
     198              :     std::size_t
     199        91875 :     capacity() const noexcept
     200              :     {
     201        91875 :         return s_.k == kind::string ?
     202        11708 :             p_.t->capacity :
     203        91875 :             sbo_chars_;
     204              :     }
     205              : 
     206              :     void
     207        10015 :     size(std::size_t n)
     208              :     {
     209        10015 :         if(s_.k == kind::string)
     210         9733 :             p_.t->size = static_cast<
     211              :                 std::uint32_t>(n);
     212              :         else
     213          282 :             s_.buf[sbo_chars_] =
     214              :                 static_cast<char>(
     215          282 :                     sbo_chars_ - n);
     216        10015 :     }
     217              : 
     218              :     BOOST_JSON_DECL
     219              :     static
     220              :     std::uint32_t
     221              :     growth(
     222              :         std::size_t new_size,
     223              :         std::size_t capacity);
     224              : 
     225              :     char const*
     226        38150 :     release_key(
     227              :         std::size_t& n) noexcept
     228              :     {
     229        38150 :         BOOST_ASSERT(
     230              :             k_.k == key_string_);
     231        38150 :         n = k_.n;
     232        38150 :         auto const s = k_.s;
     233              :         // prevent deallocate
     234        38150 :         k_.k = short_string_;
     235        38150 :         return s;
     236              :     }
     237              : 
     238              :     void
     239        57650 :     destroy(
     240              :         storage_ptr const& sp) noexcept
     241              :     {
     242        57650 :         if(s_.k == kind::string)
     243              :         {
     244        26671 :             sp->deallocate(p_.t,
     245              :                 sizeof(table) +
     246        26671 :                     p_.t->capacity + 1,
     247              :                 alignof(table));
     248              :         }
     249        30979 :         else if(s_.k != key_string_)
     250              :         {
     251              :             // do nothing
     252              :         }
     253              :         else
     254              :         {
     255          146 :             BOOST_ASSERT(
     256              :                 s_.k == key_string_);
     257              :             // VFALCO unfortunately the key string
     258              :             // kind increases the cost of the destructor.
     259              :             // This function should be skipped when using
     260              :             // monotonic_resource.
     261          146 :             sp->deallocate(k_.s, k_.n + 1);
     262              :         }
     263        57650 :     }
     264              : 
     265              :     BOOST_JSON_DECL
     266              :     char*
     267              :     assign(
     268              :         std::size_t new_size,
     269              :         storage_ptr const& sp);
     270              : 
     271              :     BOOST_JSON_DECL
     272              :     char*
     273              :     append(
     274              :         std::size_t n,
     275              :         storage_ptr const& sp);
     276              : 
     277              :     BOOST_JSON_DECL
     278              :     void
     279              :     insert(
     280              :         std::size_t pos,
     281              :         const char* s,
     282              :         std::size_t n,
     283              :         storage_ptr const& sp);
     284              : 
     285              :     BOOST_JSON_DECL
     286              :     char*
     287              :     insert_unchecked(
     288              :         std::size_t pos,
     289              :         std::size_t n,
     290              :         storage_ptr const& sp);
     291              : 
     292              :     BOOST_JSON_DECL
     293              :     void
     294              :     replace(
     295              :         std::size_t pos,
     296              :         std::size_t n1,
     297              :         const char* s,
     298              :         std::size_t n2,
     299              :         storage_ptr const& sp);
     300              : 
     301              :     BOOST_JSON_DECL
     302              :     char*
     303              :     replace_unchecked(
     304              :         std::size_t pos,
     305              :         std::size_t n1,
     306              :         std::size_t n2,
     307              :         storage_ptr const& sp);
     308              : 
     309              :     BOOST_JSON_DECL
     310              :     void
     311              :     shrink_to_fit(
     312              :         storage_ptr const& sp) noexcept;
     313              : 
     314              :     void
     315        33565 :     term(std::size_t n) noexcept
     316              :     {
     317        33565 :         if(s_.k == short_string_)
     318              :         {
     319         5140 :             s_.buf[sbo_chars_] =
     320              :                 static_cast<char>(
     321         5140 :                     sbo_chars_ - n);
     322         5140 :             s_.buf[n] = 0;
     323              :         }
     324              :         else
     325              :         {
     326        28425 :             p_.t->size = static_cast<
     327              :                 std::uint32_t>(n);
     328        28425 :             data()[n] = 0;
     329              :         }
     330        33565 :     }
     331              : 
     332              :     char*
     333       117283 :     data() noexcept
     334              :     {
     335       117283 :         if(s_.k == short_string_)
     336        15377 :             return s_.buf;
     337              :         return reinterpret_cast<
     338       101906 :             char*>(p_.t + 1);
     339              :     }
     340              : 
     341              :     char const*
     342        44003 :     data() const noexcept
     343              :     {
     344        44003 :         if(s_.k == short_string_)
     345         4548 :             return s_.buf;
     346              :         return reinterpret_cast<
     347        39455 :             char const*>(p_.t + 1);
     348              :     }
     349              : 
     350              :     char*
     351          175 :     end() noexcept
     352              :     {
     353          175 :         return data() + size();
     354              :     }
     355              : 
     356              :     char const*
     357           10 :     end() const noexcept
     358              :     {
     359           10 :         return data() + size();
     360              :     }
     361              : };
     362              : 
     363              : template<class T>
     364              : string_view
     365         2481 : to_string_view(T const& t) noexcept
     366              : {
     367         2481 :     return string_view(t);
     368              : }
     369              : 
     370              : template<class T, class U>
     371              : using string_and_stringlike = std::integral_constant<bool,
     372              :     std::is_same<T, string>::value &&
     373              :     std::is_convertible<U const&, string_view>::value>;
     374              : 
     375              : template<class T, class U>
     376              : using string_comp_op_requirement
     377              :     = typename std::enable_if<
     378              :         string_and_stringlike<T, U>::value ||
     379              :         string_and_stringlike<U, T>::value,
     380              :         bool>::type;
     381              : 
     382              : } // detail
     383              : } // namespace json
     384              : } // namespace boost
     385              : 
     386              : #endif
        

Generated by: LCOV version 2.1