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