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 | |||||