99.13% Lines (227/229) 100.00% Functions (13/13)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) 3   // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/boostorg/json 8   // Official repository: https://github.com/boostorg/json
9   // 9   //
10   10  
11   #ifndef BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP 11   #ifndef BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP
12   #define BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP 12   #define BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP
13   13  
14   #include <boost/json/detail/string_impl.hpp> 14   #include <boost/json/detail/string_impl.hpp>
15   #include <boost/json/detail/except.hpp> 15   #include <boost/json/detail/except.hpp>
16   #include <cstring> 16   #include <cstring>
17   #include <functional> 17   #include <functional>
18   18  
19   namespace boost { 19   namespace boost {
20   namespace json { 20   namespace json {
21   namespace detail { 21   namespace detail {
22   22  
23   inline 23   inline
24   bool 24   bool
HITCBC 25   23 ptr_in_range( 25   23 ptr_in_range(
26   const char* first, 26   const char* first,
27   const char* last, 27   const char* last,
28   const char* ptr) noexcept 28   const char* ptr) noexcept
29   { 29   {
HITCBC 30   37 return std::less<const char*>()(ptr, last) && 30   37 return std::less<const char*>()(ptr, last) &&
HITCBC 31   37 std::greater_equal<const char*>()(ptr, first); 31   37 std::greater_equal<const char*>()(ptr, first);
32   } 32   }
33   33  
HITCBC 34   30933 string_impl:: 34   30933 string_impl::
HITCBC 35   30933 string_impl() noexcept 35   30933 string_impl() noexcept
36   { 36   {
HITCBC 37   30933 s_.k = short_string_; 37   30933 s_.k = short_string_;
HITCBC 38   30933 s_.buf[sbo_chars_] = 38   30933 s_.buf[sbo_chars_] =
39   static_cast<char>( 39   static_cast<char>(
40   sbo_chars_); 40   sbo_chars_);
HITCBC 41   30933 s_.buf[0] = 0; 41   30933 s_.buf[0] = 0;
HITCBC 42   30933 } 42   30933 }
43   43  
HITCBC 44   26901 string_impl:: 44   26901 string_impl::
45   string_impl( 45   string_impl(
46   std::size_t size, 46   std::size_t size,
HITCBC 47   26901 storage_ptr const& sp) 47   26901 storage_ptr const& sp)
48   { 48   {
HITCBC 49   26901 if(size <= sbo_chars_) 49   26901 if(size <= sbo_chars_)
50   { 50   {
HITCBC 51   41 s_.k = short_string_; 51   41 s_.k = short_string_;
HITCBC 52   41 s_.buf[sbo_chars_] = 52   41 s_.buf[sbo_chars_] =
53   static_cast<char>( 53   static_cast<char>(
HITCBC 54   41 sbo_chars_ - size); 54   41 sbo_chars_ - size);
HITCBC 55   41 s_.buf[size] = 0; 55   41 s_.buf[size] = 0;
56   } 56   }
57   else 57   else
58   { 58   {
HITCBC 59   26860 s_.k = kind::string; 59   26860 s_.k = kind::string;
HITCBC 60   26860 auto const n = growth( 60   26860 auto const n = growth(
61   size, sbo_chars_ + 1); 61   size, sbo_chars_ + 1);
HITCBC 62   26860 p_.t = ::new(sp->allocate( 62   26860 p_.t = ::new(sp->allocate(
63   sizeof(table) + 63   sizeof(table) +
HITCBC 64   26860 n + 1, 64   26860 n + 1,
65   alignof(table))) table{ 65   alignof(table))) table{
66   static_cast< 66   static_cast<
67   std::uint32_t>(size), 67   std::uint32_t>(size),
68   static_cast< 68   static_cast<
HITCBC 69   26673 std::uint32_t>(n)}; 69   26673 std::uint32_t>(n)};
HITCBC 70   26673 data()[n] = 0; 70   26673 data()[n] = 0;
71   } 71   }
HITCBC 72   26714 } 72   26714 }
73   73  
74   // construct a key, unchecked 74   // construct a key, unchecked
HITCBC 75   30296 string_impl:: 75   30296 string_impl::
76   string_impl( 76   string_impl(
77   key_t, 77   key_t,
78   string_view s, 78   string_view s,
HITCBC 79   30296 storage_ptr const& sp) 79   30296 storage_ptr const& sp)
80   { 80   {
HITCBC 81   30296 BOOST_ASSERT( 81   30296 BOOST_ASSERT(
82   s.size() <= max_size()); 82   s.size() <= max_size());
HITCBC 83   30296 k_.k = key_string_; 83   30296 k_.k = key_string_;
HITCBC 84   30296 k_.n = static_cast< 84   30296 k_.n = static_cast<
HITCBC 85   30296 std::uint32_t>(s.size()); 85   30296 std::uint32_t>(s.size());
HITCBC 86   30236 k_.s = reinterpret_cast<char*>( 86   30236 k_.s = reinterpret_cast<char*>(
HITCBC 87   30296 sp->allocate(s.size() + 1, 87   30296 sp->allocate(s.size() + 1,
88   alignof(char))); 88   alignof(char)));
HITCBC 89   30236 k_.s[s.size()] = 0; // null term 89   30236 k_.s[s.size()] = 0; // null term
HITCBC 90   30236 std::memcpy(&k_.s[0], 90   30236 std::memcpy(&k_.s[0],
HITCBC 91   30236 s.data(), s.size()); 91   30236 s.data(), s.size());
HITCBC 92   30236 } 92   30236 }
93   93  
94   // construct a key, unchecked 94   // construct a key, unchecked
HITCBC 95   8060 string_impl:: 95   8060 string_impl::
96   string_impl( 96   string_impl(
97   key_t, 97   key_t,
98   string_view s1, 98   string_view s1,
99   string_view s2, 99   string_view s2,
HITCBC 100   8060 storage_ptr const& sp) 100   8060 storage_ptr const& sp)
101   { 101   {
HITCBC 102   8060 auto len = s1.size() + s2.size(); 102   8060 auto len = s1.size() + s2.size();
HITCBC 103   8060 BOOST_ASSERT(len <= max_size()); 103   8060 BOOST_ASSERT(len <= max_size());
HITCBC 104   8060 k_.k = key_string_; 104   8060 k_.k = key_string_;
HITCBC 105   8060 k_.n = static_cast< 105   8060 k_.n = static_cast<
106   std::uint32_t>(len); 106   std::uint32_t>(len);
HITCBC 107   8060 k_.s = reinterpret_cast<char*>( 107   8060 k_.s = reinterpret_cast<char*>(
HITCBC 108   8060 sp->allocate(len + 1, 108   8060 sp->allocate(len + 1,
109   alignof(char))); 109   alignof(char)));
HITCBC 110   8060 k_.s[len] = 0; // null term 110   8060 k_.s[len] = 0; // null term
HITCBC 111   8060 std::memcpy(&k_.s[0], 111   8060 std::memcpy(&k_.s[0],
HITCBC 112   8060 s1.data(), s1.size()); 112   8060 s1.data(), s1.size());
HITCBC 113   16120 std::memcpy(&k_.s[s1.size()], 113   16120 std::memcpy(&k_.s[s1.size()],
HITCBC 114   8060 s2.data(), s2.size()); 114   8060 s2.data(), s2.size());
HITCBC 115   8060 } 115   8060 }
116   116  
117   std::uint32_t 117   std::uint32_t
HITCBC 118   53714 string_impl:: 118   53714 string_impl::
119   growth( 119   growth(
120   std::size_t new_size, 120   std::size_t new_size,
121   std::size_t capacity) 121   std::size_t capacity)
122   { 122   {
HITCBC 123   53714 if(new_size > max_size()) 123   53714 if(new_size > max_size())
124   { 124   {
125   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 125   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 126   1 detail::throw_system_error( error::string_too_large, &loc ); 126   1 detail::throw_system_error( error::string_too_large, &loc );
127   } 127   }
128   // growth factor 2 128   // growth factor 2
HITCBC 129   53713 if( capacity > 129   53713 if( capacity >
HITCBC 130   53713 max_size() - capacity) 130   53713 max_size() - capacity)
131   return static_cast< 131   return static_cast<
MISUBC 132   std::uint32_t>(max_size()); // overflow 132   std::uint32_t>(max_size()); // overflow
133   return static_cast<std::uint32_t>( 133   return static_cast<std::uint32_t>(
HITCBC 134   53713 (std::max)(capacity * 2, new_size)); 134   53713 (std::max)(capacity * 2, new_size));
135   } 135   }
136   136  
137   char* 137   char*
HITCBC 138   18450 string_impl:: 138   18450 string_impl::
139   assign( 139   assign(
140   std::size_t new_size, 140   std::size_t new_size,
141   storage_ptr const& sp) 141   storage_ptr const& sp)
142   { 142   {
HITCBC 143   18450 if(new_size > capacity()) 143   18450 if(new_size > capacity())
144   { 144   {
HITCBC 145   17092 string_impl tmp(growth( 145   17092 string_impl tmp(growth(
146   new_size, 146   new_size,
HITCBC 147   17092 capacity()), sp); 147   17092 capacity()), sp);
HITCBC 148   16951 destroy(sp); 148   16951 destroy(sp);
HITCBC 149   16951 *this = tmp; 149   16951 *this = tmp;
150   } 150   }
HITCBC 151   18309 term(new_size); 151   18309 term(new_size);
HITCBC 152   18309 return data(); 152   18309 return data();
153   } 153   }
154   154  
155   char* 155   char*
HITCBC 156   154 string_impl:: 156   154 string_impl::
157   append( 157   append(
158   std::size_t n, 158   std::size_t n,
159   storage_ptr const& sp) 159   storage_ptr const& sp)
160   { 160   {
HITCBC 161   154 if(n > max_size() - size()) 161   154 if(n > max_size() - size())
162   { 162   {
163   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 163   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 164   1 detail::throw_system_error( error::string_too_large, &loc ); 164   1 detail::throw_system_error( error::string_too_large, &loc );
165   } 165   }
HITCBC 166   153 if(n <= capacity() - size()) 166   153 if(n <= capacity() - size())
167   { 167   {
HITCBC 168   107 term(size() + n); 168   107 term(size() + n);
HITCBC 169   107 return end() - n; 169   107 return end() - n;
170   } 170   }
HITCBC 171   92 string_impl tmp(growth( 171   92 string_impl tmp(growth(
HITCBC 172   92 size() + n, capacity()), sp); 172   92 size() + n, capacity()), sp);
HITCBC 173   27 std::memcpy( 173   27 std::memcpy(
HITCBC 174   27 tmp.data(), data(), size()); 174   27 tmp.data(), data(), size());
HITCBC 175   27 tmp.term(size() + n); 175   27 tmp.term(size() + n);
HITCBC 176   27 destroy(sp); 176   27 destroy(sp);
HITCBC 177   27 *this = tmp; 177   27 *this = tmp;
HITCBC 178   27 return end() - n; 178   27 return end() - n;
179   } 179   }
180   180  
181   void 181   void
HITCBC 182   27 string_impl:: 182   27 string_impl::
183   insert( 183   insert(
184   std::size_t pos, 184   std::size_t pos,
185   const char* s, 185   const char* s,
186   std::size_t n, 186   std::size_t n,
187   storage_ptr const& sp) 187   storage_ptr const& sp)
188   { 188   {
HITCBC 189   27 const auto curr_size = size(); 189   27 const auto curr_size = size();
HITCBC 190   27 if(pos > curr_size) 190   27 if(pos > curr_size)
191   { 191   {
192   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 192   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 193   2 detail::throw_system_error( error::out_of_range, &loc ); 193   2 detail::throw_system_error( error::out_of_range, &loc );
194   } 194   }
HITCBC 195   25 const auto curr_data = data(); 195   25 const auto curr_data = data();
HITCBC 196   25 if(n <= capacity() - curr_size) 196   25 if(n <= capacity() - curr_size)
197   { 197   {
HITCBC 198   10 const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); 198   10 const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s);
HITCBC 199   10 if (!inside || (inside && ((s - curr_data) + n <= pos))) 199   10 if (!inside || (inside && ((s - curr_data) + n <= pos)))
200   { 200   {
HITCBC 201   8 std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); 201   8 std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1);
HITCBC 202   8 std::memcpy(&curr_data[pos], s, n); 202   8 std::memcpy(&curr_data[pos], s, n);
203   } 203   }
204   else 204   else
205   { 205   {
HITCBC 206   2 const std::size_t offset = s - curr_data; 206   2 const std::size_t offset = s - curr_data;
HITCBC 207   2 std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1); 207   2 std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1);
HITCBC 208   2 if (offset < pos) 208   2 if (offset < pos)
209   { 209   {
HITCBC 210   1 const std::size_t diff = pos - offset; 210   1 const std::size_t diff = pos - offset;
HITCBC 211   1 std::memcpy(&curr_data[pos], &curr_data[offset], diff); 211   1 std::memcpy(&curr_data[pos], &curr_data[offset], diff);
HITCBC 212   1 std::memcpy(&curr_data[pos + diff], &curr_data[pos + n], n - diff); 212   1 std::memcpy(&curr_data[pos + diff], &curr_data[pos + n], n - diff);
213   } 213   }
214   else 214   else
215   { 215   {
HITCBC 216   1 std::memcpy(&curr_data[pos], &curr_data[offset + n], n); 216   1 std::memcpy(&curr_data[pos], &curr_data[offset + n], n);
217   } 217   }
218   } 218   }
HITCBC 219   10 size(curr_size + n); 219   10 size(curr_size + n);
220   } 220   }
221   else 221   else
222   { 222   {
HITCBC 223   15 if(n > max_size() - curr_size) 223   15 if(n > max_size() - curr_size)
224   { 224   {
225   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 225   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 226   1 detail::throw_system_error( error::string_too_large, &loc ); 226   1 detail::throw_system_error( error::string_too_large, &loc );
227   } 227   }
HITCBC 228   14 string_impl tmp(growth( 228   14 string_impl tmp(growth(
HITCBC 229   14 curr_size + n, capacity()), sp); 229   14 curr_size + n, capacity()), sp);
HITCBC 230   7 tmp.size(curr_size + n); 230   7 tmp.size(curr_size + n);
HITCBC 231   7 std::memcpy( 231   7 std::memcpy(
HITCBC 232   7 tmp.data(), 232   7 tmp.data(),
233   curr_data, 233   curr_data,
234   pos); 234   pos);
HITCBC 235   14 std::memcpy( 235   14 std::memcpy(
HITCBC 236   14 tmp.data() + pos + n, 236   14 tmp.data() + pos + n,
237   curr_data + pos, 237   curr_data + pos,
HITCBC 238   7 curr_size + 1 - pos); 238   7 curr_size + 1 - pos);
HITCBC 239   7 std::memcpy( 239   7 std::memcpy(
HITCBC 240   7 tmp.data() + pos, 240   7 tmp.data() + pos,
241   s, 241   s,
242   n); 242   n);
HITCBC 243   7 destroy(sp); 243   7 destroy(sp);
HITCBC 244   7 *this = tmp; 244   7 *this = tmp;
245   } 245   }
HITCBC 246   17 } 246   17 }
247   247  
248   char* 248   char*
HITCBC 249   17 string_impl:: 249   17 string_impl::
250   insert_unchecked( 250   insert_unchecked(
251   std::size_t pos, 251   std::size_t pos,
252   std::size_t n, 252   std::size_t n,
253   storage_ptr const& sp) 253   storage_ptr const& sp)
254   { 254   {
HITCBC 255   17 const auto curr_size = size(); 255   17 const auto curr_size = size();
HITCBC 256   17 if(pos > curr_size) 256   17 if(pos > curr_size)
257   { 257   {
258   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 258   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 259   1 detail::throw_system_error( error::out_of_range, &loc ); 259   1 detail::throw_system_error( error::out_of_range, &loc );
260   } 260   }
HITCBC 261   16 const auto curr_data = data(); 261   16 const auto curr_data = data();
HITCBC 262   16 if(n <= capacity() - size()) 262   16 if(n <= capacity() - size())
263   { 263   {
HITCBC 264   5 auto const dest = 264   5 auto const dest =
265   curr_data + pos; 265   curr_data + pos;
HITCBC 266   5 std::memmove( 266   5 std::memmove(
267   dest + n, 267   dest + n,
268   dest, 268   dest,
HITCBC 269   5 curr_size + 1 - pos); 269   5 curr_size + 1 - pos);
HITCBC 270   5 size(curr_size + n); 270   5 size(curr_size + n);
HITCBC 271   5 return dest; 271   5 return dest;
272   } 272   }
HITCBC 273   11 if(n > max_size() - curr_size) 273   11 if(n > max_size() - curr_size)
274   { 274   {
275   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 275   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 276   1 detail::throw_system_error( error::string_too_large, &loc ); 276   1 detail::throw_system_error( error::string_too_large, &loc );
277   } 277   }
HITCBC 278   10 string_impl tmp(growth( 278   10 string_impl tmp(growth(
HITCBC 279   10 curr_size + n, capacity()), sp); 279   10 curr_size + n, capacity()), sp);
HITCBC 280   5 tmp.size(curr_size + n); 280   5 tmp.size(curr_size + n);
HITCBC 281   5 std::memcpy( 281   5 std::memcpy(
HITCBC 282   5 tmp.data(), 282   5 tmp.data(),
283   curr_data, 283   curr_data,
284   pos); 284   pos);
HITCBC 285   10 std::memcpy( 285   10 std::memcpy(
HITCBC 286   10 tmp.data() + pos + n, 286   10 tmp.data() + pos + n,
287   curr_data + pos, 287   curr_data + pos,
HITCBC 288   5 curr_size + 1 - pos); 288   5 curr_size + 1 - pos);
HITCBC 289   5 destroy(sp); 289   5 destroy(sp);
HITCBC 290   5 *this = tmp; 290   5 *this = tmp;
HITCBC 291   5 return data() + pos; 291   5 return data() + pos;
292   } 292   }
293   293  
294   void 294   void
HITCBC 295   19 string_impl:: 295   19 string_impl::
296   replace( 296   replace(
297   std::size_t pos, 297   std::size_t pos,
298   std::size_t n1, 298   std::size_t n1,
299   const char* s, 299   const char* s,
300   std::size_t n2, 300   std::size_t n2,
301   storage_ptr const& sp) 301   storage_ptr const& sp)
302   { 302   {
HITCBC 303   19 const auto curr_size = size(); 303   19 const auto curr_size = size();
HITCBC 304   19 if (pos > curr_size) 304   19 if (pos > curr_size)
305   { 305   {
306   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 306   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 307   1 detail::throw_system_error( error::out_of_range, &loc ); 307   1 detail::throw_system_error( error::out_of_range, &loc );
308   } 308   }
HITCBC 309   18 const auto curr_data = data(); 309   18 const auto curr_data = data();
HITCBC 310   18 n1 = (std::min)(n1, curr_size - pos); 310   18 n1 = (std::min)(n1, curr_size - pos);
HITCBC 311   18 const auto delta = (std::max)(n1, n2) - 311   18 const auto delta = (std::max)(n1, n2) -
HITCBC 312   18 (std::min)(n1, n2); 312   18 (std::min)(n1, n2);
313   // if we are shrinking in size or we have enough 313   // if we are shrinking in size or we have enough
314   // capacity, dont reallocate 314   // capacity, dont reallocate
HITCBC 315   18 if (n1 > n2 || delta <= capacity() - curr_size) 315   18 if (n1 > n2 || delta <= capacity() - curr_size)
316   { 316   {
HITCBC 317   13 const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s); 317   13 const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s);
318   // there is nothing to replace; return 318   // there is nothing to replace; return
HITCBC 319   13 if (inside && s == curr_data + pos && n1 == n2) 319   13 if (inside && s == curr_data + pos && n1 == n2)
HITCBC 320   1 return; 320   1 return;
HITCBC 321   12 if (!inside || (inside && ((s - curr_data) + n2 <= pos))) 321   12 if (!inside || (inside && ((s - curr_data) + n2 <= pos)))
322   { 322   {
323   // source outside 323   // source outside
HITCBC 324   6 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); 324   6 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
HITCBC 325   6 std::memcpy(&curr_data[pos], s, n2); 325   6 std::memcpy(&curr_data[pos], s, n2);
326   } 326   }
327   else 327   else
328   { 328   {
329   // source inside 329   // source inside
HITCBC 330   6 const std::size_t offset = s - curr_data; 330   6 const std::size_t offset = s - curr_data;
HITCBC 331   6 if (n2 >= n1) 331   6 if (n2 >= n1)
332   { 332   {
333   // grow/unchanged 333   // grow/unchanged
HITCBC 334   4 const std::size_t diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; 334   4 const std::size_t diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
335   // shift all right of splice point by n2 - n1 to the right 335   // shift all right of splice point by n2 - n1 to the right
HITCBC 336   4 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); 336   4 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
337   // copy all before splice point 337   // copy all before splice point
HITCBC 338   4 std::memmove(&curr_data[pos], &curr_data[offset], diff); 338   4 std::memmove(&curr_data[pos], &curr_data[offset], diff);
339   // copy all after splice point 339   // copy all after splice point
HITCBC 340   4 std::memmove(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff); 340   4 std::memmove(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff);
341   } 341   }
342   else 342   else
343   { 343   {
344   // shrink 344   // shrink
345   // copy all elements into place 345   // copy all elements into place
HITCBC 346   2 std::memmove(&curr_data[pos], &curr_data[offset], n2); 346   2 std::memmove(&curr_data[pos], &curr_data[offset], n2);
347   // shift all elements after splice point left 347   // shift all elements after splice point left
HITCBC 348   2 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); 348   2 std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
349   } 349   }
350   } 350   }
HITCBC 351   12 size((curr_size - n1) + n2); 351   12 size((curr_size - n1) + n2);
352   } 352   }
353   else 353   else
354   { 354   {
HITCBC 355   5 if (delta > max_size() - curr_size) 355   5 if (delta > max_size() - curr_size)
356   { 356   {
357   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 357   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 358   1 detail::throw_system_error( error::string_too_large, &loc ); 358   1 detail::throw_system_error( error::string_too_large, &loc );
359   } 359   }
360   // would exceed capacity, reallocate 360   // would exceed capacity, reallocate
HITCBC 361   4 string_impl tmp(growth( 361   4 string_impl tmp(growth(
HITCBC 362   4 curr_size + delta, capacity()), sp); 362   4 curr_size + delta, capacity()), sp);
HITCBC 363   2 tmp.size(curr_size + delta); 363   2 tmp.size(curr_size + delta);
HITCBC 364   2 std::memcpy( 364   2 std::memcpy(
HITCBC 365   2 tmp.data(), 365   2 tmp.data(),
366   curr_data, 366   curr_data,
367   pos); 367   pos);
HITCBC 368   4 std::memcpy( 368   4 std::memcpy(
HITCBC 369   4 tmp.data() + pos + n2, 369   4 tmp.data() + pos + n2,
HITCBC 370   2 curr_data + pos + n1, 370   2 curr_data + pos + n1,
HITCBC 371   2 curr_size - pos - n1 + 1); 371   2 curr_size - pos - n1 + 1);
HITCBC 372   4 std::memcpy( 372   4 std::memcpy(
HITCBC 373   2 tmp.data() + pos, 373   2 tmp.data() + pos,
374   s, 374   s,
375   n2); 375   n2);
HITCBC 376   2 destroy(sp); 376   2 destroy(sp);
HITCBC 377   2 *this = tmp; 377   2 *this = tmp;
378   } 378   }
379   } 379   }
380   380  
381   // unlike the replace overload, this function does 381   // unlike the replace overload, this function does
382   // not move any characters 382   // not move any characters
383   char* 383   char*
HITCBC 384   7 string_impl:: 384   7 string_impl::
385   replace_unchecked( 385   replace_unchecked(
386   std::size_t pos, 386   std::size_t pos,
387   std::size_t n1, 387   std::size_t n1,
388   std::size_t n2, 388   std::size_t n2,
389   storage_ptr const& sp) 389   storage_ptr const& sp)
390   { 390   {
HITCBC 391   7 const auto curr_size = size(); 391   7 const auto curr_size = size();
HITCBC 392   7 if(pos > curr_size) 392   7 if(pos > curr_size)
393   { 393   {
394   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 394   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 395   1 detail::throw_system_error( error::out_of_range, &loc ); 395   1 detail::throw_system_error( error::out_of_range, &loc );
396   } 396   }
HITCBC 397   6 const auto curr_data = data(); 397   6 const auto curr_data = data();
HITCBC 398   6 const auto delta = (std::max)(n1, n2) - 398   6 const auto delta = (std::max)(n1, n2) -
HITCBC 399   6 (std::min)(n1, n2); 399   6 (std::min)(n1, n2);
400   // if the size doesn't change, we don't need to 400   // if the size doesn't change, we don't need to
401   // do anything 401   // do anything
HITCBC 402   6 if (!delta) 402   6 if (!delta)
HITCBC 403   1 return curr_data + pos; 403   1 return curr_data + pos;
404   // if we are shrinking in size or we have enough 404   // if we are shrinking in size or we have enough
405   // capacity, dont reallocate 405   // capacity, dont reallocate
HITCBC 406   5 if(n1 > n2 || delta <= capacity() - curr_size) 406   5 if(n1 > n2 || delta <= capacity() - curr_size)
407   { 407   {
HITCBC 408   2 auto const replace_pos = curr_data + pos; 408   2 auto const replace_pos = curr_data + pos;
HITCBC 409   2 std::memmove( 409   2 std::memmove(
HITCBC 410   2 replace_pos + n2, 410   2 replace_pos + n2,
HITCBC 411   2 replace_pos + n1, 411   2 replace_pos + n1,
HITCBC 412   2 curr_size - pos - n1 + 1); 412   2 curr_size - pos - n1 + 1);
HITCBC 413   2 size((curr_size - n1) + n2); 413   2 size((curr_size - n1) + n2);
HITCBC 414   2 return replace_pos; 414   2 return replace_pos;
415   } 415   }
HITCBC 416   3 if(delta > max_size() - curr_size) 416   3 if(delta > max_size() - curr_size)
417   { 417   {
418   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 418   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 419   1 detail::throw_system_error( error::string_too_large, &loc ); 419   1 detail::throw_system_error( error::string_too_large, &loc );
420   } 420   }
421   // would exceed capacity, reallocate 421   // would exceed capacity, reallocate
HITCBC 422   2 string_impl tmp(growth( 422   2 string_impl tmp(growth(
HITCBC 423   2 curr_size + delta, capacity()), sp); 423   2 curr_size + delta, capacity()), sp);
HITCBC 424   1 tmp.size(curr_size + delta); 424   1 tmp.size(curr_size + delta);
HITCBC 425   1 std::memcpy( 425   1 std::memcpy(
HITCBC 426   1 tmp.data(), 426   1 tmp.data(),
427   curr_data, 427   curr_data,
428   pos); 428   pos);
HITCBC 429   2 std::memcpy( 429   2 std::memcpy(
HITCBC 430   2 tmp.data() + pos + n2, 430   2 tmp.data() + pos + n2,
HITCBC 431   1 curr_data + pos + n1, 431   1 curr_data + pos + n1,
HITCBC 432   1 curr_size - pos - n1 + 1); 432   1 curr_size - pos - n1 + 1);
HITCBC 433   1 destroy(sp); 433   1 destroy(sp);
HITCBC 434   1 *this = tmp; 434   1 *this = tmp;
HITCBC 435   1 return data() + pos; 435   1 return data() + pos;
436   } 436   }
437   437  
438   void 438   void
HITCBC 439   7 string_impl:: 439   7 string_impl::
440   shrink_to_fit( 440   shrink_to_fit(
441   storage_ptr const& sp) noexcept 441   storage_ptr const& sp) noexcept
442   { 442   {
HITCBC 443   7 if(s_.k == short_string_) 443   7 if(s_.k == short_string_)
HITCBC 444   3 return; 444   3 return;
HITCBC 445   4 auto const t = p_.t; 445   4 auto const t = p_.t;
HITCBC 446   4 if(t->size <= sbo_chars_) 446   4 if(t->size <= sbo_chars_)
447   { 447   {
HITCBC 448   2 s_.k = short_string_; 448   2 s_.k = short_string_;
HITCBC 449   4 std::memcpy( 449   4 std::memcpy(
HITCBC 450   2 s_.buf, data(), t->size); 450   2 s_.buf, data(), t->size);
HITCBC 451   2 s_.buf[sbo_chars_] = 451   2 s_.buf[sbo_chars_] =
452   static_cast<char>( 452   static_cast<char>(
HITCBC 453   2 sbo_chars_ - t->size); 453   2 sbo_chars_ - t->size);
HITCBC 454   2 s_.buf[t->size] = 0; 454   2 s_.buf[t->size] = 0;
HITCBC 455   2 sp->deallocate(t, 455   2 sp->deallocate(t,
456   sizeof(table) + 456   sizeof(table) +
HITCBC 457   2 t->capacity + 1, 457   2 t->capacity + 1,
458   alignof(table)); 458   alignof(table));
HITCBC 459   2 return; 459   2 return;
460   } 460   }
HITCBC 461   2 if(t->size >= t->capacity) 461   2 if(t->size >= t->capacity)
MISUBC 462   return; 462   return;
463   #ifndef BOOST_NO_EXCEPTIONS 463   #ifndef BOOST_NO_EXCEPTIONS
464   try 464   try
465   { 465   {
466   #endif 466   #endif
HITCBC 467   2 string_impl tmp(t->size, sp); 467   2 string_impl tmp(t->size, sp);
HITCBC 468   1 std::memcpy( 468   1 std::memcpy(
HITCBC 469   1 tmp.data(), 469   1 tmp.data(),
HITCBC 470   1 data(), 470   1 data(),
471   size()); 471   size());
HITCBC 472   1 destroy(sp); 472   1 destroy(sp);
HITCBC 473   1 *this = tmp; 473   1 *this = tmp;
474   #ifndef BOOST_NO_EXCEPTIONS 474   #ifndef BOOST_NO_EXCEPTIONS
475   } 475   }
HITCBC 476   1 catch(std::exception const&) 476   1 catch(std::exception const&)
477   { 477   {
478   // eat the exception 478   // eat the exception
HITCBC 479   1 } 479   1 }
480   #endif 480   #endif
481   } 481   }
482   482  
483   } // detail 483   } // detail
484   } // namespace json 484   } // namespace json
485   } // namespace boost 485   } // namespace boost
486   486  
487   #endif 487   #endif