100.00% Lines (201/201) 100.00% Functions (30/30)
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_VALUE_STACK_IPP 10   #ifndef BOOST_JSON_IMPL_VALUE_STACK_IPP
11   #define BOOST_JSON_IMPL_VALUE_STACK_IPP 11   #define BOOST_JSON_IMPL_VALUE_STACK_IPP
12   12  
13   #include <boost/json/value_stack.hpp> 13   #include <boost/json/value_stack.hpp>
14   #include <cstring> 14   #include <cstring>
15   #include <memory> 15   #include <memory>
16   #include <stdexcept> 16   #include <stdexcept>
17   #include <utility> 17   #include <utility>
18   18  
19   namespace boost { 19   namespace boost {
20   namespace json { 20   namespace json {
21   21  
22   //-------------------------------------- 22   //--------------------------------------
23   23  
HITCBC 24   2076914 value_stack:: 24   2076914 value_stack::
25   stack:: 25   stack::
26   ~stack() 26   ~stack()
27   { 27   {
HITCBC 28   2076914 clear(); 28   2076914 clear();
HITCBC 29   2076914 if( begin_ != temp_ && 29   2076914 if( begin_ != temp_ &&
HITCBC 30   75357 begin_ != nullptr) 30   75357 begin_ != nullptr)
HITCBC 31   75349 sp_->deallocate( 31   75349 sp_->deallocate(
HITCBC 32   75349 begin_, 32   75349 begin_,
HITCBC 33   75349 (end_ - begin_) * 33   75349 (end_ - begin_) *
34   sizeof(value)); 34   sizeof(value));
HITCBC 35   2076914 } 35   2076914 }
36   36  
HITCBC 37   2076914 value_stack:: 37   2076914 value_stack::
38   stack:: 38   stack::
39   stack( 39   stack(
40   storage_ptr sp, 40   storage_ptr sp,
41   void* temp, 41   void* temp,
HITCBC 42   2076914 std::size_t size) noexcept 42   2076914 std::size_t size) noexcept
HITCBC 43   2076914 : sp_(std::move(sp)) 43   2076914 : sp_(std::move(sp))
44   { 44   {
45   // the buffer stores `value`s, so it has to be aligned for one; 45   // the buffer stores `value`s, so it has to be aligned for one;
46   // align it up the same way static_resource does for its buffer 46   // align it up the same way static_resource does for its buffer
HITCBC 47   2076914 void* const aligned = std::align( 47   2076914 void* const aligned = std::align(
48   alignof(value), 48   alignof(value),
49   min_size_ * sizeof(value), 49   min_size_ * sizeof(value),
50   temp, size); 50   temp, size);
HITCBC 51   2076914 if(aligned) 51   2076914 if(aligned)
52   { 52   {
HITCBC 53   2001518 temp_ = temp; 53   2001518 temp_ = temp;
HITCBC 54   2001518 begin_ = reinterpret_cast< 54   2001518 begin_ = reinterpret_cast<
55   value*>(temp); 55   value*>(temp);
HITCBC 56   2001518 top_ = begin_; 56   2001518 top_ = begin_;
HITCBC 57   2001518 end_ = begin_ + 57   2001518 end_ = begin_ +
HITCBC 58   2001518 size / sizeof(value); 58   2001518 size / sizeof(value);
59   } 59   }
60   else 60   else
61   { 61   {
HITCBC 62   75396 temp_ = temp; 62   75396 temp_ = temp;
HITCBC 63   75396 begin_ = nullptr; 63   75396 begin_ = nullptr;
HITCBC 64   75396 top_ = nullptr; 64   75396 top_ = nullptr;
HITCBC 65   75396 end_ = nullptr; 65   75396 end_ = nullptr;
66   } 66   }
HITCBC 67   2076914 } 67   2076914 }
68   68  
69   void 69   void
HITCBC 70   4153167 value_stack:: 70   4153167 value_stack::
71   stack:: 71   stack::
72   run_dtors(bool b) noexcept 72   run_dtors(bool b) noexcept
73   { 73   {
HITCBC 74   4153167 run_dtors_ = b; 74   4153167 run_dtors_ = b;
HITCBC 75   4153167 } 75   4153167 }
76   76  
77   std::size_t 77   std::size_t
HITCBC 78   4213837 value_stack:: 78   4213837 value_stack::
79   stack:: 79   stack::
80   size() const noexcept 80   size() const noexcept
81   { 81   {
HITCBC 82   4213837 return top_ - begin_; 82   4213837 return top_ - begin_;
83   } 83   }
84   84  
85   bool 85   bool
HITCBC 86   64466 value_stack:: 86   64466 value_stack::
87   stack:: 87   stack::
88   has_chars() 88   has_chars()
89   { 89   {
HITCBC 90   64466 return chars_ != 0; 90   64466 return chars_ != 0;
91   } 91   }
92   92  
93   //-------------------------------------- 93   //--------------------------------------
94   94  
95   // destroy the values but 95   // destroy the values but
96   // not the stack allocation. 96   // not the stack allocation.
97   void 97   void
HITCBC 98   6230081 value_stack:: 98   6230081 value_stack::
99   stack:: 99   stack::
100   clear() noexcept 100   clear() noexcept
101   { 101   {
HITCBC 102   6230081 if(top_ != begin_) 102   6230081 if(top_ != begin_)
103   { 103   {
HITCBC 104   86 if(run_dtors_) 104   86 if(run_dtors_)
HITCBC 105   86 for(auto it = top_; 105   86 for(auto it = top_;
HITCBC 106   339 it-- != begin_;) 106   339 it-- != begin_;)
HITCBC 107   253 it->~value(); 107   253 it->~value();
HITCBC 108   86 top_ = begin_; 108   86 top_ = begin_;
109   } 109   }
HITCBC 110   6230081 chars_ = 0; 110   6230081 chars_ = 0;
HITCBC 111   6230081 } 111   6230081 }
112   112  
113   void 113   void
HITCBC 114   1868 value_stack:: 114   1868 value_stack::
115   stack:: 115   stack::
116   maybe_grow() 116   maybe_grow()
117   { 117   {
HITCBC 118   1868 if(top_ >= end_) 118   1868 if(top_ >= end_)
HITCBC 119   266 grow_one(); 119   266 grow_one();
HITCBC 120   1868 } 120   1868 }
121   121  
122   // make room for at least one more value 122   // make room for at least one more value
123   void 123   void
HITCBC 124   66512 value_stack:: 124   66512 value_stack::
125   stack:: 125   stack::
126   grow_one() 126   grow_one()
127   { 127   {
HITCBC 128   66512 BOOST_ASSERT(chars_ == 0); 128   66512 BOOST_ASSERT(chars_ == 0);
HITCBC 129   66512 std::size_t const capacity = 129   66512 std::size_t const capacity =
HITCBC 130   66512 end_ - begin_; 130   66512 end_ - begin_;
HITCBC 131   66512 std::size_t new_cap = min_size_; 131   66512 std::size_t new_cap = min_size_;
132   // VFALCO check overflow here 132   // VFALCO check overflow here
HITCBC 133   66554 while(new_cap < capacity + 1) 133   66554 while(new_cap < capacity + 1)
HITCBC 134   42 new_cap <<= 1; 134   42 new_cap <<= 1;
135   auto const begin = 135   auto const begin =
136   reinterpret_cast<value*>( 136   reinterpret_cast<value*>(
HITCBC 137   66512 sp_->allocate( 137   66512 sp_->allocate(
138   new_cap * sizeof(value))); 138   new_cap * sizeof(value)));
HITCBC 139   66512 std::size_t const cur_size = top_ - begin_; 139   66512 std::size_t const cur_size = top_ - begin_;
HITCBC 140   66512 if(begin_) 140   66512 if(begin_)
141   { 141   {
HITCBC 142   11 std::memcpy( 142   11 std::memcpy(
143   reinterpret_cast<char*>(begin), 143   reinterpret_cast<char*>(begin),
HITCBC 144   11 reinterpret_cast<char*>(begin_), 144   11 reinterpret_cast<char*>(begin_),
HITCBC 145   11 size() * sizeof(value)); 145   11 size() * sizeof(value));
HITCBC 146   11 if(begin_ != temp_) 146   11 if(begin_ != temp_)
HITCBC 147   9 sp_->deallocate(begin_, 147   9 sp_->deallocate(begin_,
148   capacity * sizeof(value)); 148   capacity * sizeof(value));
149   } 149   }
150   // book-keeping 150   // book-keeping
HITCBC 151   66512 top_ = begin + cur_size; 151   66512 top_ = begin + cur_size;
HITCBC 152   66512 end_ = begin + new_cap; 152   66512 end_ = begin + new_cap;
HITCBC 153   66512 begin_ = begin; 153   66512 begin_ = begin;
HITCBC 154   66512 } 154   66512 }
155   155  
156   // make room for nchars additional characters. 156   // make room for nchars additional characters.
157   void 157   void
HITCBC 158   16180 value_stack:: 158   16180 value_stack::
159   stack:: 159   stack::
160   grow(std::size_t nchars) 160   grow(std::size_t nchars)
161   { 161   {
162   // needed capacity in values 162   // needed capacity in values
163   std::size_t const needed = 163   std::size_t const needed =
HITCBC 164   16180 size() + 164   16180 size() +
HITCBC 165   16180 1 + 165   16180 1 +
HITCBC 166   16180 ((chars_ + nchars + 166   16180 ((chars_ + nchars +
HITCBC 167   16180 sizeof(value) - 1) / 167   16180 sizeof(value) - 1) /
HITCBC 168   16180 sizeof(value)); 168   16180 sizeof(value));
HITCBC 169   16180 std::size_t const capacity = 169   16180 std::size_t const capacity =
HITCBC 170   16180 end_ - begin_; 170   16180 end_ - begin_;
HITCBC 171   16180 BOOST_ASSERT( 171   16180 BOOST_ASSERT(
172   needed > capacity); 172   needed > capacity);
HITCBC 173   16180 std::size_t new_cap = min_size_; 173   16180 std::size_t new_cap = min_size_;
174   // VFALCO check overflow here 174   // VFALCO check overflow here
HITCBC 175   57842 while(new_cap < needed) 175   57842 while(new_cap < needed)
HITCBC 176   41662 new_cap <<= 1; 176   41662 new_cap <<= 1;
177   auto const begin = 177   auto const begin =
178   reinterpret_cast<value*>( 178   reinterpret_cast<value*>(
HITCBC 179   16180 sp_->allocate( 179   16180 sp_->allocate(
180   new_cap * sizeof(value))); 180   new_cap * sizeof(value)));
HITCBC 181   16180 std::size_t const cur_size = top_ - begin_; 181   16180 std::size_t const cur_size = top_ - begin_;
HITCBC 182   16180 if(begin_) 182   16180 if(begin_)
183   { 183   {
184   std::size_t amount = 184   std::size_t amount =
HITCBC 185   7334 size() * sizeof(value); 185   7334 size() * sizeof(value);
HITCBC 186   7334 if(chars_ > 0) 186   7334 if(chars_ > 0)
HITCBC 187   6 amount += sizeof(value) + chars_; 187   6 amount += sizeof(value) + chars_;
HITCBC 188   7334 std::memcpy( 188   7334 std::memcpy(
189   reinterpret_cast<char*>(begin), 189   reinterpret_cast<char*>(begin),
HITCBC 190   7334 reinterpret_cast<char*>(begin_), 190   7334 reinterpret_cast<char*>(begin_),
191   amount); 191   amount);
HITCBC 192   7334 if(begin_ != temp_) 192   7334 if(begin_ != temp_)
HITCBC 193   7334 sp_->deallocate(begin_, 193   7334 sp_->deallocate(begin_,
194   capacity * sizeof(value)); 194   capacity * sizeof(value));
195   } 195   }
196   // book-keeping 196   // book-keeping
HITCBC 197   16180 top_ = begin + cur_size; 197   16180 top_ = begin + cur_size;
HITCBC 198   16180 end_ = begin + new_cap; 198   16180 end_ = begin + new_cap;
HITCBC 199   16180 begin_ = begin; 199   16180 begin_ = begin;
HITCBC 200   16180 } 200   16180 }
201   201  
202   //-------------------------------------- 202   //--------------------------------------
203   203  
204   void 204   void
HITCBC 205   20149 value_stack:: 205   20149 value_stack::
206   stack:: 206   stack::
207   append(string_view s) 207   append(string_view s)
208   { 208   {
HITCBC 209   20149 std::size_t const bytes_avail = 209   20149 std::size_t const bytes_avail =
210   reinterpret_cast< 210   reinterpret_cast<
HITCBC 211   20149 char const*>(end_) - 211   20149 char const*>(end_) -
212   reinterpret_cast< 212   reinterpret_cast<
HITCBC 213   20149 char const*>(top_); 213   20149 char const*>(top_);
214   // make sure there is room for 214   // make sure there is room for
215   // pushing one more value without 215   // pushing one more value without
216   // clobbering the string. 216   // clobbering the string.
HITCBC 217   40298 if(sizeof(value) + chars_ + 217   40298 if(sizeof(value) + chars_ +
HITCBC 218   20149 s.size() > bytes_avail) 218   20149 s.size() > bytes_avail)
HITCBC 219   16180 grow(s.size()); 219   16180 grow(s.size());
220   220  
221   // copy the new piece 221   // copy the new piece
HITCBC 222   20149 std::memcpy( 222   20149 std::memcpy(
223   reinterpret_cast<char*>( 223   reinterpret_cast<char*>(
HITCBC 224   20149 top_ + 1) + chars_, 224   20149 top_ + 1) + chars_,
HITCBC 225   20149 s.data(), s.size()); 225   20149 s.data(), s.size());
HITCBC 226   20149 chars_ += s.size(); 226   20149 chars_ += s.size();
227   227  
228   // ensure a pushed value cannot 228   // ensure a pushed value cannot
229   // clobber the released string. 229   // clobber the released string.
HITCBC 230   20149 BOOST_ASSERT( 230   20149 BOOST_ASSERT(
231   reinterpret_cast<char*>( 231   reinterpret_cast<char*>(
232   top_ + 1) + chars_ <= 232   top_ + 1) + chars_ <=
233   reinterpret_cast<char*>( 233   reinterpret_cast<char*>(
234   end_)); 234   end_));
HITCBC 235   20149 } 235   20149 }
236   236  
237   string_view 237   string_view
HITCBC 238   17021 value_stack:: 238   17021 value_stack::
239   stack:: 239   stack::
240   release_string() noexcept 240   release_string() noexcept
241   { 241   {
242   // ensure a pushed value cannot 242   // ensure a pushed value cannot
243   // clobber the released string. 243   // clobber the released string.
HITCBC 244   17021 BOOST_ASSERT( 244   17021 BOOST_ASSERT(
245   reinterpret_cast<char*>( 245   reinterpret_cast<char*>(
246   top_ + 1) + chars_ <= 246   top_ + 1) + chars_ <=
247   reinterpret_cast<char*>( 247   reinterpret_cast<char*>(
248   end_)); 248   end_));
HITCBC 249   17021 auto const n = chars_; 249   17021 auto const n = chars_;
HITCBC 250   17021 chars_ = 0; 250   17021 chars_ = 0;
251   return { reinterpret_cast< 251   return { reinterpret_cast<
HITCBC 252   17021 char const*>(top_ + 1), n }; 252   17021 char const*>(top_ + 1), n };
253   } 253   }
254   254  
255   // transfer ownership of the top n 255   // transfer ownership of the top n
256   // elements of the stack to the caller 256   // elements of the stack to the caller
257   value* 257   value*
HITCBC 258   2113656 value_stack:: 258   2113656 value_stack::
259   stack:: 259   stack::
260   release(std::size_t n) noexcept 260   release(std::size_t n) noexcept
261   { 261   {
HITCBC 262   2113656 BOOST_ASSERT(n <= size()); 262   2113656 BOOST_ASSERT(n <= size());
HITCBC 263   2113656 BOOST_ASSERT(chars_ == 0); 263   2113656 BOOST_ASSERT(chars_ == 0);
HITCBC 264   2113656 top_ -= n; 264   2113656 top_ -= n;
HITCBC 265   2113656 return top_; 265   2113656 return top_;
266   } 266   }
267   267  
268   template<class... Args> 268   template<class... Args>
269   value& 269   value&
HITCBC 270   2119951 value_stack:: 270   2119951 value_stack::
271   stack:: 271   stack::
272   push(Args&&... args) 272   push(Args&&... args)
273   { 273   {
HITCBC 274   2119951 BOOST_ASSERT(chars_ == 0); 274   2119951 BOOST_ASSERT(chars_ == 0);
HITCBC 275   2119951 if(top_ >= end_) 275   2119951 if(top_ >= end_)
HITCBC 276   66246 grow_one(); 276   66246 grow_one();
277   value& jv = detail::access:: 277   value& jv = detail::access::
HITCBC 278   2119951 construct_value(top_, 278   2119951 construct_value(top_,
279   std::forward<Args>(args)...); 279   std::forward<Args>(args)...);
HITCBC 280   2119887 ++top_; 280   2119887 ++top_;
HITCBC 281   2119887 return jv; 281   2119887 return jv;
282   } 282   }
283   283  
284   template<class Unchecked> 284   template<class Unchecked>
285   void 285   void
HITCBC 286   37000 value_stack:: 286   37000 value_stack::
287   stack:: 287   stack::
288   exchange(Unchecked&& u) 288   exchange(Unchecked&& u)
289   { 289   {
HITCBC 290   37000 BOOST_ASSERT(chars_ == 0); 290   37000 BOOST_ASSERT(chars_ == 0);
291   union U 291   union U
292   { 292   {
293   value v; 293   value v;
HITCBC 294   37000 U() {} 294   37000 U() {}
HITCBC 295   37000 ~U() {} 295   37000 ~U() {}
HITCBC 296   37000 } jv; 296   37000 } jv;
297   // construct value on the stack 297   // construct value on the stack
298   // to avoid clobbering top_[0], 298   // to avoid clobbering top_[0],
299   // which belongs to `u`. 299   // which belongs to `u`.
300   detail::access:: 300   detail::access::
HITCBC 301   37000 construct_value( 301   37000 construct_value(
HITCBC 302   37000 &jv.v, std::move(u)); 302   37000 &jv.v, std::move(u));
HITCBC 303   36923 std::memcpy( 303   36923 std::memcpy(
304   reinterpret_cast< 304   reinterpret_cast<
HITCBC 305   36923 char*>(top_), 305   36923 char*>(top_),
306   &jv.v, sizeof(value)); 306   &jv.v, sizeof(value));
HITCBC 307   36923 ++top_; 307   36923 ++top_;
HITCBC 308   37000 } 308   37000 }
309   309  
310   //---------------------------------------------------------- 310   //----------------------------------------------------------
311   311  
HITCBC 312   2076914 value_stack:: 312   2076914 value_stack::
313   ~value_stack() 313   ~value_stack()
314   { 314   {
315   // default dtor is here so the 315   // default dtor is here so the
316   // definition goes in the library 316   // definition goes in the library
317   // instead of the caller's TU. 317   // instead of the caller's TU.
HITCBC 318   2076914 } 318   2076914 }
319   319  
HITCBC 320   2076914 value_stack:: 320   2076914 value_stack::
321   value_stack( 321   value_stack(
322   storage_ptr sp, 322   storage_ptr sp,
323   unsigned char* temp_buffer, 323   unsigned char* temp_buffer,
HITCBC 324   2076914 std::size_t temp_size) noexcept 324   2076914 std::size_t temp_size) noexcept
HITCBC 325   2076914 : st_( 325   2076914 : st_(
HITCBC 326   2076914 std::move(sp), 326   2076914 std::move(sp),
327   temp_buffer, 327   temp_buffer,
HITCBC 328   2076914 temp_size) 328   2076914 temp_size)
329   { 329   {
HITCBC 330   2076914 } 330   2076914 }
331   331  
332   void 332   void
HITCBC 333   4153167 value_stack:: 333   4153167 value_stack::
334   reset(storage_ptr sp) noexcept 334   reset(storage_ptr sp) noexcept
335   { 335   {
HITCBC 336   4153167 st_.clear(); 336   4153167 st_.clear();
337   337  
HITCBC 338   4153167 sp_.~storage_ptr(); 338   4153167 sp_.~storage_ptr();
HITCBC 339   12459493 ::new(&sp_) storage_ptr( 339   12459493 ::new(&sp_) storage_ptr(
HITCBC 340   4153167 pilfer(sp)); 340   4153167 pilfer(sp));
341   341  
342   // `stack` needs this 342   // `stack` needs this
343   // to clean up correctly 343   // to clean up correctly
HITCBC 344   8306334 st_.run_dtors( 344   8306334 st_.run_dtors(
HITCBC 345   4153167 ! sp_.is_not_shared_and_deallocate_is_trivial()); 345   4153167 ! sp_.is_not_shared_and_deallocate_is_trivial());
HITCBC 346   4153167 } 346   4153167 }
347   347  
348   value 348   value
HITCBC 349   2076656 value_stack:: 349   2076656 value_stack::
350   release() noexcept 350   release() noexcept
351   { 351   {
352   // This means the caller did not 352   // This means the caller did not
353   // cause a single top level element 353   // cause a single top level element
354   // to be produced. 354   // to be produced.
HITCBC 355   2076656 BOOST_ASSERT(st_.size() == 1); 355   2076656 BOOST_ASSERT(st_.size() == 1);
356   356  
357   // give up shared ownership 357   // give up shared ownership
HITCBC 358   2076656 sp_ = {}; 358   2076656 sp_ = {};
359   359  
HITCBC 360   2076656 return pilfer(*st_.release(1)); 360   2076656 return pilfer(*st_.release(1));
361   } 361   }
362   362  
363   //---------------------------------------------------------- 363   //----------------------------------------------------------
364   364  
365   void 365   void
HITCBC 366   2120 value_stack:: 366   2120 value_stack::
367   push_array(std::size_t n) 367   push_array(std::size_t n)
368   { 368   {
369   // we already have room if n > 0 369   // we already have room if n > 0
HITCBC 370   2120 if(BOOST_JSON_UNLIKELY(n == 0)) 370   2120 if(BOOST_JSON_UNLIKELY(n == 0))
HITCBC 371   819 st_.maybe_grow(); 371   819 st_.maybe_grow();
372   detail::unchecked_array ua( 372   detail::unchecked_array ua(
HITCBC 373   2120 st_.release(n), n, sp_); 373   2120 st_.release(n), n, sp_);
HITCBC 374   2120 st_.exchange(std::move(ua)); 374   2120 st_.exchange(std::move(ua));
HITCBC 375   2120 } 375   2120 }
376   376  
377   void 377   void
HITCBC 378   34880 value_stack:: 378   34880 value_stack::
379   push_object(std::size_t n) 379   push_object(std::size_t n)
380   { 380   {
381   // we already have room if n > 0 381   // we already have room if n > 0
HITCBC 382   34880 if(BOOST_JSON_UNLIKELY(n == 0)) 382   34880 if(BOOST_JSON_UNLIKELY(n == 0))
HITCBC 383   1049 st_.maybe_grow(); 383   1049 st_.maybe_grow();
384   detail::unchecked_object uo( 384   detail::unchecked_object uo(
HITCBC 385   34880 st_.release(n * 2), n, sp_); 385   34880 st_.release(n * 2), n, sp_);
HITCBC 386   34880 st_.exchange(std::move(uo)); 386   34880 st_.exchange(std::move(uo));
HITCBC 387   34880 } 387   34880 }
388   388  
389   void 389   void
HITCBC 390   20149 value_stack:: 390   20149 value_stack::
391   push_chars( 391   push_chars(
392   string_view s) 392   string_view s)
393   { 393   {
HITCBC 394   20149 st_.append(s); 394   20149 st_.append(s);
HITCBC 395   20149 } 395   20149 }
396   396  
397   void 397   void
HITCBC 398   38358 value_stack:: 398   38358 value_stack::
399   push_key( 399   push_key(
400   string_view s) 400   string_view s)
401   { 401   {
HITCBC 402   38358 if(! st_.has_chars()) 402   38358 if(! st_.has_chars())
403   { 403   {
HITCBC 404   30297 st_.push(detail::key_t{}, s, sp_); 404   30297 st_.push(detail::key_t{}, s, sp_);
HITCBC 405   30237 return; 405   30237 return;
406   } 406   }
HITCBC 407   8061 auto part = st_.release_string(); 407   8061 auto part = st_.release_string();
HITCBC 408   8061 st_.push(detail::key_t{}, part, s, sp_); 408   8061 st_.push(detail::key_t{}, part, s, sp_);
409   } 409   }
410   410  
411   void 411   void
HITCBC 412   26108 value_stack:: 412   26108 value_stack::
413   push_string( 413   push_string(
414   string_view s) 414   string_view s)
415   { 415   {
HITCBC 416   26108 if(! st_.has_chars()) 416   26108 if(! st_.has_chars())
417   { 417   {
418   // fast path 418   // fast path
HITCBC 419   17148 st_.push(s, sp_); 419   17148 st_.push(s, sp_);
HITCBC 420   17144 return; 420   17144 return;
421   } 421   }
422   422  
423   // VFALCO We could add a special 423   // VFALCO We could add a special
424   // private ctor to string that just 424   // private ctor to string that just
425   // creates uninitialized space, 425   // creates uninitialized space,
426   // to reduce member function calls. 426   // to reduce member function calls.
HITCBC 427   8960 auto part = st_.release_string(); 427   8960 auto part = st_.release_string();
HITCBC 428   17920 auto& str = st_.push( 428   17920 auto& str = st_.push(
HITCBC 429   8960 string_kind, sp_).get_string(); 429   8960 string_kind, sp_).get_string();
HITCBC 430   8960 str.reserve( 430   8960 str.reserve(
HITCBC 431   8960 part.size() + s.size()); 431   8960 part.size() + s.size());
HITCBC 432   8960 std::memcpy( 432   8960 std::memcpy(
HITCBC 433   8960 str.data(), 433   8960 str.data(),
HITCBC 434   8960 part.data(), part.size()); 434   8960 part.data(), part.size());
HITCBC 435   8960 std::memcpy( 435   8960 std::memcpy(
HITCBC 436   8960 str.data() + part.size(), 436   8960 str.data() + part.size(),
HITCBC 437   8960 s.data(), s.size()); 437   8960 s.data(), s.size());
HITCBC 438   8960 str.grow(part.size() + s.size()); 438   8960 str.grow(part.size() + s.size());
439   } 439   }
440   440  
441   void 441   void
HITCBC 442   5816 value_stack:: 442   5816 value_stack::
443   push_int64( 443   push_int64(
444   std::int64_t i) 444   std::int64_t i)
445   { 445   {
HITCBC 446   5816 st_.push(i, sp_); 446   5816 st_.push(i, sp_);
HITCBC 447   5816 } 447   5816 }
448   448  
449   void 449   void
HITCBC 450   70 value_stack:: 450   70 value_stack::
451   push_uint64( 451   push_uint64(
452   std::uint64_t u) 452   std::uint64_t u)
453   { 453   {
HITCBC 454   70 st_.push(u, sp_); 454   70 st_.push(u, sp_);
HITCBC 455   70 } 455   70 }
456   456  
457   void 457   void
HITCBC 458   2039830 value_stack:: 458   2039830 value_stack::
459   push_double( 459   push_double(
460   double d) 460   double d)
461   { 461   {
HITCBC 462   2039830 st_.push(d, sp_); 462   2039830 st_.push(d, sp_);
HITCBC 463   2039830 } 463   2039830 }
464   464  
465   void 465   void
HITCBC 466   400 value_stack:: 466   400 value_stack::
467   push_bool( 467   push_bool(
468   bool b) 468   bool b)
469   { 469   {
HITCBC 470   400 st_.push(b, sp_); 470   400 st_.push(b, sp_);
HITCBC 471   400 } 471   400 }
472   472  
473   void 473   void
HITCBC 474   9369 value_stack:: 474   9369 value_stack::
475   push_null() 475   push_null()
476   { 476   {
HITCBC 477   9369 st_.push(nullptr, sp_); 477   9369 st_.push(nullptr, sp_);
HITCBC 478   9369 } 478   9369 }
479   479  
480   } // namespace json 480   } // namespace json
481   } // namespace boost 481   } // namespace boost
482   482  
483   #endif 483   #endif