LCOV - code coverage report
Current view: top level - json/detail - string_impl.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 76 76
Test Date: 2026-08-03 09:51:43 Functions: 100.0 % 29 29

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

Generated by: LCOV version 2.3