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

Generated by: LCOV version 2.1