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