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 % 73 73
Test Date: 2026-07-08 12:13:06 Functions: 100.0 % 28 28

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

Generated by: LCOV version 2.3