100.00% Lines (173/173) 100.00% Functions (36/36)
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   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/boostorg/json 7   // Official repository: https://github.com/boostorg/json
8   // 8   //
9   9  
10   #ifndef BOOST_JSON_IMPL_STRING_IPP 10   #ifndef BOOST_JSON_IMPL_STRING_IPP
11   #define BOOST_JSON_IMPL_STRING_IPP 11   #define BOOST_JSON_IMPL_STRING_IPP
12   12  
13   #include <boost/json/detail/except.hpp> 13   #include <boost/json/detail/except.hpp>
14   #include <algorithm> 14   #include <algorithm>
15   #include <new> 15   #include <new>
16   #include <ostream> 16   #include <ostream>
17   #include <stdexcept> 17   #include <stdexcept>
18   #include <string> 18   #include <string>
19   #include <utility> 19   #include <utility>
20   20  
21   namespace boost { 21   namespace boost {
22   namespace json { 22   namespace json {
23   23  
24   //---------------------------------------------------------- 24   //----------------------------------------------------------
25   // 25   //
26   // Construction 26   // Construction
27   // 27   //
28   //---------------------------------------------------------- 28   //----------------------------------------------------------
29   29  
HITCBC 30   78 string:: 30   78 string::
31   string( 31   string(
32   std::size_t count, 32   std::size_t count,
33   char ch, 33   char ch,
HITCBC 34   78 storage_ptr sp) 34   78 storage_ptr sp)
HITCBC 35   78 : sp_(std::move(sp)) 35   78 : sp_(std::move(sp))
36   { 36   {
HITCBC 37   78 assign(count, ch); 37   78 assign(count, ch);
HITCBC 38   78 } 38   78 }
39   39  
HITCBC 40   175 string:: 40   175 string::
41   string( 41   string(
42   char const* s, 42   char const* s,
HITCBC 43   175 storage_ptr sp) 43   175 storage_ptr sp)
HITCBC 44   175 : sp_(std::move(sp)) 44   175 : sp_(std::move(sp))
45   { 45   {
HITCBC 46   175 assign(s); 46   175 assign(s);
HITCBC 47   175 } 47   175 }
48   48  
HITCBC 49   4 string:: 49   4 string::
50   string( 50   string(
51   char const* s, 51   char const* s,
52   std::size_t count, 52   std::size_t count,
HITCBC 53   4 storage_ptr sp) 53   4 storage_ptr sp)
HITCBC 54   4 : sp_(std::move(sp)) 54   4 : sp_(std::move(sp))
55   { 55   {
HITCBC 56   4 assign(s, count); 56   4 assign(s, count);
HITCBC 57   4 } 57   4 }
58   58  
HITCBC 59   8 string:: 59   8 string::
HITCBC 60   8 string(string const& other) 60   8 string(string const& other)
HITCBC 61   8 : sp_(other.sp_) 61   8 : sp_(other.sp_)
62   { 62   {
HITCBC 63   8 assign(other); 63   8 assign(other);
HITCBC 64   8 } 64   8 }
65   65  
HITCBC 66   158 string:: 66   158 string::
67   string( 67   string(
68   string const& other, 68   string const& other,
HITCBC 69   158 storage_ptr sp) 69   158 storage_ptr sp)
HITCBC 70   158 : sp_(std::move(sp)) 70   158 : sp_(std::move(sp))
71   { 71   {
HITCBC 72   158 assign(other); 72   158 assign(other);
HITCBC 73   158 } 73   158 }
74   74  
HITCBC 75   351 string:: 75   351 string::
76   string( 76   string(
77   string&& other, 77   string&& other,
HITCBC 78   351 storage_ptr sp) 78   351 storage_ptr sp)
HITCBC 79   351 : sp_(std::move(sp)) 79   351 : sp_(std::move(sp))
80   { 80   {
HITCBC 81   351 assign(std::move(other)); 81   351 assign(std::move(other));
HITCBC 82   351 } 82   351 }
83   83  
HITCBC 84   17891 string:: 84   17891 string::
85   string( 85   string(
86   string_view s, 86   string_view s,
HITCBC 87   17891 storage_ptr sp) 87   17891 storage_ptr sp)
HITCBC 88   17891 : sp_(std::move(sp)) 88   17891 : sp_(std::move(sp))
89   { 89   {
HITCBC 90   17891 assign(s); 90   17891 assign(s);
HITCBC 91   17891 } 91   17891 }
92   92  
93   //---------------------------------------------------------- 93   //----------------------------------------------------------
94   // 94   //
95   // Assignment 95   // Assignment
96   // 96   //
97   //---------------------------------------------------------- 97   //----------------------------------------------------------
98   98  
99   string& 99   string&
HITCBC 100   6 string:: 100   6 string::
101   operator=(string const& other) 101   operator=(string const& other)
102   { 102   {
HITCBC 103   6 return assign(other); 103   6 return assign(other);
104   } 104   }
105   105  
106   string& 106   string&
HITCBC 107   10 string:: 107   10 string::
108   operator=(string&& other) 108   operator=(string&& other)
109   { 109   {
HITCBC 110   10 return assign(std::move(other)); 110   10 return assign(std::move(other));
111   } 111   }
112   112  
113   string& 113   string&
HITCBC 114   9 string:: 114   9 string::
115   operator=(char const* s) 115   operator=(char const* s)
116   { 116   {
HITCBC 117   9 return assign(s); 117   9 return assign(s);
118   } 118   }
119   119  
120   string& 120   string&
HITCBC 121   8 string:: 121   8 string::
122   operator=(string_view s) 122   operator=(string_view s)
123   { 123   {
HITCBC 124   8 return assign(s); 124   8 return assign(s);
125   } 125   }
126   126  
127   127  
128   128  
129   string& 129   string&
HITCBC 130   83 string:: 130   83 string::
131   assign( 131   assign(
132   size_type count, 132   size_type count,
133   char ch) 133   char ch)
134   { 134   {
HITCBC 135   64 std::char_traits<char>::assign( 135   64 std::char_traits<char>::assign(
HITCBC 136   83 impl_.assign(count, sp_), 136   83 impl_.assign(count, sp_),
137   count, 137   count,
138   ch); 138   ch);
HITCBC 139   64 return *this; 139   64 return *this;
140   } 140   }
141   141  
142   string& 142   string&
HITCBC 143   206 string:: 143   206 string::
144   assign( 144   assign(
145   string const& other) 145   string const& other)
146   { 146   {
HITCBC 147   206 if(this == &other) 147   206 if(this == &other)
HITCBC 148   1 return *this; 148   1 return *this;
HITCBC 149   205 return assign( 149   205 return assign(
150   other.data(), 150   other.data(),
HITCBC 151   177 other.size()); 151   177 other.size());
152   } 152   }
153   153  
154   string& 154   string&
HITCBC 155   375 string:: 155   375 string::
156   assign(string&& other) 156   assign(string&& other)
157   { 157   {
HITCBC 158   375 if( &other == this ) 158   375 if( &other == this )
HITCBC 159   1 return *this; 159   1 return *this;
160   160  
HITCBC 161   374 if(*sp_ == *other.sp_) 161   374 if(*sp_ == *other.sp_)
162   { 162   {
HITCBC 163   340 impl_.destroy(sp_); 163   340 impl_.destroy(sp_);
HITCBC 164   340 impl_ = other.impl_; 164   340 impl_ = other.impl_;
HITCBC 165   340 ::new(&other.impl_) detail::string_impl(); 165   340 ::new(&other.impl_) detail::string_impl();
HITCBC 166   340 return *this; 166   340 return *this;
167   } 167   }
168   168  
169   // copy 169   // copy
HITCBC 170   34 return assign(other); 170   34 return assign(other);
171   } 171   }
172   172  
173   string& 173   string&
HITCBC 174   18381 string:: 174   18381 string::
175   assign( 175   assign(
176   char const* s, 176   char const* s,
177   size_type count) 177   size_type count)
178   { 178   {
HITCBC 179   18257 std::char_traits<char>::copy( 179   18257 std::char_traits<char>::copy(
HITCBC 180   18381 impl_.assign(count, sp_), 180   18381 impl_.assign(count, sp_),
181   s, count); 181   s, count);
HITCBC 182   18257 return *this; 182   18257 return *this;
183   } 183   }
184   184  
185   string& 185   string&
HITCBC 186   189 string:: 186   189 string::
187   assign( 187   assign(
188   char const* s) 188   char const* s)
189   { 189   {
HITCBC 190   189 return assign(s, std::char_traits< 190   189 return assign(s, std::char_traits<
HITCBC 191   186 char>::length(s)); 191   186 char>::length(s));
192   } 192   }
193   193  
194   //---------------------------------------------------------- 194   //----------------------------------------------------------
195   // 195   //
196   // Capacity 196   // Capacity
197   // 197   //
198   //---------------------------------------------------------- 198   //----------------------------------------------------------
199   199  
200   void 200   void
HITCBC 201   7 string:: 201   7 string::
202   shrink_to_fit() 202   shrink_to_fit()
203   { 203   {
HITCBC 204   7 impl_.shrink_to_fit(sp_); 204   7 impl_.shrink_to_fit(sp_);
HITCBC 205   7 } 205   7 }
206   206  
207   //---------------------------------------------------------- 207   //----------------------------------------------------------
208   // 208   //
209   // Access 209   // Access
210   // 210   //
211   //---------------------------------------------------------- 211   //----------------------------------------------------------
212   212  
213   system::result<char&> 213   system::result<char&>
HITCBC 214   12 string::try_at(std::size_t pos) noexcept 214   12 string::try_at(std::size_t pos) noexcept
215   { 215   {
HITCBC 216   12 if( pos < size() ) 216   12 if( pos < size() )
HITCBC 217   10 return impl_.data()[pos]; 217   10 return impl_.data()[pos];
218   218  
HITCBC 219   2 system::error_code ec; 219   2 system::error_code ec;
HITCBC 220   2 BOOST_JSON_FAIL(ec, error::out_of_range); 220   2 BOOST_JSON_FAIL(ec, error::out_of_range);
HITCBC 221   2 return ec; 221   2 return ec;
222   } 222   }
223   223  
224   system::result<char const&> 224   system::result<char const&>
HITCBC 225   20 string::try_at(std::size_t pos) const noexcept 225   20 string::try_at(std::size_t pos) const noexcept
226   { 226   {
HITCBC 227   20 if( pos < size() ) 227   20 if( pos < size() )
HITCBC 228   18 return impl_.data()[pos]; 228   18 return impl_.data()[pos];
229   229  
HITCBC 230   2 system::error_code ec; 230   2 system::error_code ec;
HITCBC 231   2 BOOST_JSON_FAIL(ec, error::out_of_range); 231   2 BOOST_JSON_FAIL(ec, error::out_of_range);
HITCBC 232   2 return ec; 232   2 return ec;
233   } 233   }
234   234  
235   char const& 235   char const&
HITCBC 236   18 string::at(std::size_t pos, source_location const& loc) const 236   18 string::at(std::size_t pos, source_location const& loc) const
237   { 237   {
HITCBC 238   18 return try_at(pos).value(loc); 238   18 return try_at(pos).value(loc);
239   } 239   }
240   240  
241   //---------------------------------------------------------- 241   //----------------------------------------------------------
242   // 242   //
243   // Operations 243   // Operations
244   // 244   //
245   //---------------------------------------------------------- 245   //----------------------------------------------------------
246   246  
247   void 247   void
HITCBC 248   2 string:: 248   2 string::
249   clear() noexcept 249   clear() noexcept
250   { 250   {
HITCBC 251   2 impl_.term(0); 251   2 impl_.term(0);
HITCBC 252   2 } 252   2 }
253   253  
254   //---------------------------------------------------------- 254   //----------------------------------------------------------
255   255  
256   void 256   void
HITCBC 257   148 string:: 257   148 string::
258   push_back(char ch) 258   push_back(char ch)
259   { 259   {
HITCBC 260   148 *impl_.append(1, sp_) = ch; 260   148 *impl_.append(1, sp_) = ch;
HITCBC 261   146 } 261   146 }
262   262  
263   void 263   void
HITCBC 264   29 string:: 264   29 string::
265   pop_back() 265   pop_back()
266   { 266   {
HITCBC 267   29 back() = 0; 267   29 back() = 0;
HITCBC 268   29 impl_.size(impl_.size() - 1); 268   29 impl_.size(impl_.size() - 1);
HITCBC 269   29 } 269   29 }
270   270  
271   //---------------------------------------------------------- 271   //----------------------------------------------------------
272   272  
273   string& 273   string&
HITCBC 274   4 string:: 274   4 string::
275   append(size_type count, char ch) 275   append(size_type count, char ch)
276   { 276   {
HITCBC 277   2 std::char_traits<char>::assign( 277   2 std::char_traits<char>::assign(
HITCBC 278   4 impl_.append(count, sp_), 278   4 impl_.append(count, sp_),
279   count, ch); 279   count, ch);
HITCBC 280   2 return *this; 280   2 return *this;
281   } 281   }
282   282  
283   string& 283   string&
HITCBC 284   55 string:: 284   55 string::
285   append(string_view sv) 285   append(string_view sv)
286   { 286   {
HITCBC 287   55 auto const p = impl_.data(); 287   55 auto const p = impl_.data();
HITCBC 288   55 if(detail::ptr_in_range(p, p + impl_.size(), sv.data())) 288   55 if(detail::ptr_in_range(p, p + impl_.size(), sv.data()))
289   { 289   {
290   // sv aliases our own storage; appending may reallocate and free the 290   // sv aliases our own storage; appending may reallocate and free the
291   // buffer sv points into, so copy from the relocated offset afterwards 291   // buffer sv points into, so copy from the relocated offset afterwards
HITCBC 292   10 auto const offset = sv.data() - p; 292   10 auto const offset = sv.data() - p;
HITCBC 293   10 auto const dest = impl_.append(sv.size(), sp_); 293   10 auto const dest = impl_.append(sv.size(), sp_);
HITCBC 294   8 std::char_traits<char>::copy( 294   8 std::char_traits<char>::copy(
HITCBC 295   8 dest, impl_.data() + offset, sv.size()); 295   8 dest, impl_.data() + offset, sv.size());
296   } 296   }
297   else 297   else
298   { 298   {
HITCBC 299   90 std::char_traits<char>::copy( 299   90 std::char_traits<char>::copy(
HITCBC 300   45 impl_.append(sv.size(), sp_), 300   45 impl_.append(sv.size(), sp_),
301   sv.data(), sv.size()); 301   sv.data(), sv.size());
302   } 302   }
HITCBC 303   40 return *this; 303   40 return *this;
304   } 304   }
305   305  
306   //---------------------------------------------------------- 306   //----------------------------------------------------------
307   307  
308   string& 308   string&
HITCBC 309   27 string:: 309   27 string::
310   insert( 310   insert(
311   size_type pos, 311   size_type pos,
312   string_view sv) 312   string_view sv)
313   { 313   {
HITCBC 314   27 impl_.insert(pos, sv.data(), sv.size(), sp_); 314   27 impl_.insert(pos, sv.data(), sv.size(), sp_);
HITCBC 315   17 return *this; 315   17 return *this;
316   } 316   }
317   317  
318   string& 318   string&
HITCBC 319   11 string:: 319   11 string::
320   insert( 320   insert(
321   std::size_t pos, 321   std::size_t pos,
322   std::size_t count, 322   std::size_t count,
323   char ch) 323   char ch)
324   { 324   {
HITCBC 325   6 std::char_traits<char>::assign( 325   6 std::char_traits<char>::assign(
HITCBC 326   11 impl_.insert_unchecked(pos, count, sp_), 326   11 impl_.insert_unchecked(pos, count, sp_),
327   count, ch); 327   count, ch);
HITCBC 328   6 return *this; 328   6 return *this;
329   } 329   }
330   330  
331   //---------------------------------------------------------- 331   //----------------------------------------------------------
332   332  
333   string& 333   string&
HITCBC 334   19 string:: 334   19 string::
335   replace( 335   replace(
336   std::size_t pos, 336   std::size_t pos,
337   std::size_t count, 337   std::size_t count,
338   string_view sv) 338   string_view sv)
339   { 339   {
HITCBC 340   19 impl_.replace(pos, count, sv.data(), sv.size(), sp_); 340   19 impl_.replace(pos, count, sv.data(), sv.size(), sp_);
HITCBC 341   15 return *this; 341   15 return *this;
342   } 342   }
343   343  
344   string& 344   string&
HITCBC 345   11 string:: 345   11 string::
346   replace( 346   replace(
347   std::size_t pos, 347   std::size_t pos,
348   std::size_t count, 348   std::size_t count,
349   std::size_t count2, 349   std::size_t count2,
350   char ch) 350   char ch)
351   { 351   {
HITCBC 352   7 std::char_traits<char>::assign( 352   7 std::char_traits<char>::assign(
HITCBC 353   11 impl_.replace_unchecked(pos, count, count2, sp_), 353   11 impl_.replace_unchecked(pos, count, count2, sp_),
354   count2, ch); 354   count2, ch);
HITCBC 355   7 return *this; 355   7 return *this;
356   } 356   }
357   357  
358   //---------------------------------------------------------- 358   //----------------------------------------------------------
359   359  
360   string& 360   string&
HITCBC 361   10 string:: 361   10 string::
362   erase( 362   erase(
363   size_type pos, 363   size_type pos,
364   size_type count) 364   size_type count)
365   { 365   {
HITCBC 366   10 if(pos > impl_.size()) 366   10 if(pos > impl_.size())
367   { 367   {
368   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; 368   BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
HITCBC 369   1 detail::throw_system_error( error::out_of_range, &loc ); 369   1 detail::throw_system_error( error::out_of_range, &loc );
370   } 370   }
HITCBC 371   9 if( count > impl_.size() - pos) 371   9 if( count > impl_.size() - pos)
HITCBC 372   4 count = impl_.size() - pos; 372   4 count = impl_.size() - pos;
HITCBC 373   9 std::char_traits<char>::move( 373   9 std::char_traits<char>::move(
HITCBC 374   9 impl_.data() + pos, 374   9 impl_.data() + pos,
HITCBC 375   9 impl_.data() + pos + count, 375   9 impl_.data() + pos + count,
HITCBC 376   9 impl_.size() - pos - count + 1); 376   9 impl_.size() - pos - count + 1);
HITCBC 377   9 impl_.term(impl_.size() - count); 377   9 impl_.term(impl_.size() - count);
HITCBC 378   9 return *this; 378   9 return *this;
379   } 379   }
380   380  
381   auto 381   auto
HITCBC 382   2 string:: 382   2 string::
383   erase(const_iterator pos) -> 383   erase(const_iterator pos) ->
384   iterator 384   iterator
385   { 385   {
HITCBC 386   2 return erase(pos, pos+1); 386   2 return erase(pos, pos+1);
387   } 387   }
388   388  
389   auto 389   auto
HITCBC 390   3 string:: 390   3 string::
391   erase( 391   erase(
392   const_iterator first, 392   const_iterator first,
393   const_iterator last) -> 393   const_iterator last) ->
394   iterator 394   iterator
395   { 395   {
HITCBC 396   3 auto const pos = first - begin(); 396   3 auto const pos = first - begin();
HITCBC 397   3 auto const count = last - first; 397   3 auto const count = last - first;
HITCBC 398   3 erase(pos, count); 398   3 erase(pos, count);
HITCBC 399   3 return data() + pos; 399   3 return data() + pos;
400   } 400   }
401   401  
402   //---------------------------------------------------------- 402   //----------------------------------------------------------
403   403  
404   void 404   void
HITCBC 405   66 string:: 405   66 string::
406   resize(size_type count, char ch) 406   resize(size_type count, char ch)
407   { 407   {
HITCBC 408   66 if(count <= impl_.size()) 408   66 if(count <= impl_.size())
409   { 409   {
HITCBC 410   25 impl_.term(count); 410   25 impl_.term(count);
HITCBC 411   25 return; 411   25 return;
412   } 412   }
413   413  
HITCBC 414   41 reserve(count); 414   41 reserve(count);
HITCBC 415   35 std::char_traits<char>::assign( 415   35 std::char_traits<char>::assign(
416   impl_.end(), 416   impl_.end(),
HITCBC 417   35 count - impl_.size(), 417   35 count - impl_.size(),
418   ch); 418   ch);
HITCBC 419   35 grow(count - size()); 419   35 grow(count - size());
420   } 420   }
421   421  
422   //---------------------------------------------------------- 422   //----------------------------------------------------------
423   423  
424   void 424   void
HITCBC 425   4 string:: 425   4 string::
426   swap(string& other) 426   swap(string& other)
427   { 427   {
HITCBC 428   4 if(*sp_ == *other.sp_) 428   4 if(*sp_ == *other.sp_)
429   { 429   {
HITCBC 430   3 std::swap(impl_, other.impl_); 430   3 std::swap(impl_, other.impl_);
HITCBC 431   3 return; 431   3 return;
432   } 432   }
433   string temp1( 433   string temp1(
HITCBC 434   1 std::move(*this), other.sp_); 434   1 std::move(*this), other.sp_);
435   string temp2( 435   string temp2(
HITCBC 436   1 std::move(other), sp_); 436   1 std::move(other), sp_);
HITCBC 437   1 this->~string(); 437   1 this->~string();
HITCBC 438   1 ::new(this) string(pilfer(temp2)); 438   1 ::new(this) string(pilfer(temp2));
HITCBC 439   1 other.~string(); 439   1 other.~string();
HITCBC 440   1 ::new(&other) string(pilfer(temp1)); 440   1 ::new(&other) string(pilfer(temp1));
HITCBC 441   1 } 441   1 }
442   442  
443   //---------------------------------------------------------- 443   //----------------------------------------------------------
444   444  
445   void 445   void
HITCBC 446   9686 string:: 446   9686 string::
447   reserve_impl(size_type new_cap) 447   reserve_impl(size_type new_cap)
448   { 448   {
HITCBC 449   9686 BOOST_ASSERT( 449   9686 BOOST_ASSERT(
450   new_cap >= impl_.capacity()); 450   new_cap >= impl_.capacity());
HITCBC 451   9686 if(new_cap > impl_.capacity()) 451   9686 if(new_cap > impl_.capacity())
452   { 452   {
453   // grow 453   // grow
HITCBC 454   9686 new_cap = detail::string_impl::growth( 454   9686 new_cap = detail::string_impl::growth(
455   new_cap, impl_.capacity()); 455   new_cap, impl_.capacity());
HITCBC 456   9685 detail::string_impl tmp(new_cap, sp_); 456   9685 detail::string_impl tmp(new_cap, sp_);
HITCBC 457   9675 std::char_traits<char>::copy(tmp.data(), 457   9675 std::char_traits<char>::copy(tmp.data(),
HITCBC 458   9675 impl_.data(), impl_.size() + 1); 458   9675 impl_.data(), impl_.size() + 1);
HITCBC 459   9675 tmp.size(impl_.size()); 459   9675 tmp.size(impl_.size());
HITCBC 460   9675 impl_.destroy(sp_); 460   9675 impl_.destroy(sp_);
HITCBC 461   9675 impl_ = tmp; 461   9675 impl_ = tmp;
HITCBC 462   9675 return; 462   9675 return;
463   } 463   }
464   } 464   }
465   465  
466   } // namespace json 466   } // namespace json
467   } // namespace boost 467   } // namespace boost
468   468  
469   //---------------------------------------------------------- 469   //----------------------------------------------------------
470   470  
471   std::size_t 471   std::size_t
HITCBC 472   3 std::hash< ::boost::json::string >::operator()( 472   3 std::hash< ::boost::json::string >::operator()(
473   ::boost::json::string const& js ) const noexcept 473   ::boost::json::string const& js ) const noexcept
474   { 474   {
HITCBC 475   3 return ::boost::hash< ::boost::json::string >()( js ); 475   3 return ::boost::hash< ::boost::json::string >()( js );
476   } 476   }
477   477  
478   #endif 478   #endif