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