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