100.00% Lines (168/168)
100.00% Functions (37/37)
| 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_OBJECT_HPP | 10 | #ifndef BOOST_JSON_IMPL_OBJECT_HPP | |||||
| 11 | #define BOOST_JSON_IMPL_OBJECT_HPP | 11 | #define BOOST_JSON_IMPL_OBJECT_HPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/core/detail/static_assert.hpp> | 13 | #include <boost/core/detail/static_assert.hpp> | |||||
| 14 | #include <boost/json/value.hpp> | 14 | #include <boost/json/value.hpp> | |||||
| 15 | #include <iterator> | 15 | #include <iterator> | |||||
| 16 | #include <cmath> | 16 | #include <cmath> | |||||
| 17 | #include <type_traits> | 17 | #include <type_traits> | |||||
| 18 | #include <utility> | 18 | #include <utility> | |||||
| 19 | 19 | |||||||
| 20 | namespace boost { | 20 | namespace boost { | |||||
| 21 | namespace json { | 21 | namespace json { | |||||
| 22 | 22 | |||||||
| 23 | namespace detail { | 23 | namespace detail { | |||||
| 24 | 24 | |||||||
| 25 | // Objects with size less than or equal | 25 | // Objects with size less than or equal | |||||
| 26 | // to this number will use a linear search | 26 | // to this number will use a linear search | |||||
| 27 | // instead of the more expensive hash function. | 27 | // instead of the more expensive hash function. | |||||
| 28 | static | 28 | static | |||||
| 29 | constexpr | 29 | constexpr | |||||
| 30 | std::size_t | 30 | std::size_t | |||||
| 31 | small_object_size_ = 18; | 31 | small_object_size_ = 18; | |||||
| 32 | 32 | |||||||
| 33 | BOOST_CORE_STATIC_ASSERT( | 33 | BOOST_CORE_STATIC_ASSERT( | |||||
| 34 | small_object_size_ < BOOST_JSON_MAX_STRUCTURED_SIZE); | 34 | small_object_size_ < BOOST_JSON_MAX_STRUCTURED_SIZE); | |||||
| 35 | 35 | |||||||
| 36 | } // detail | 36 | } // detail | |||||
| 37 | 37 | |||||||
| 38 | //---------------------------------------------------------- | 38 | //---------------------------------------------------------- | |||||
| 39 | 39 | |||||||
| 40 | struct alignas(key_value_pair) | 40 | struct alignas(key_value_pair) | |||||
| 41 | object::table | 41 | object::table | |||||
| 42 | { | 42 | { | |||||
| 43 | std::uint32_t size = 0; | 43 | std::uint32_t size = 0; | |||||
| 44 | std::uint32_t capacity = 0; | 44 | std::uint32_t capacity = 0; | |||||
| 45 | std::uintptr_t salt = 0; | 45 | std::uintptr_t salt = 0; | |||||
| 46 | 46 | |||||||
| 47 | #if defined(_MSC_VER) && BOOST_JSON_ARCH == 32 | 47 | #if defined(_MSC_VER) && BOOST_JSON_ARCH == 32 | |||||
| 48 | // VFALCO If we make key_value_pair smaller, | 48 | // VFALCO If we make key_value_pair smaller, | |||||
| 49 | // then we might want to revisit this | 49 | // then we might want to revisit this | |||||
| 50 | // padding. | 50 | // padding. | |||||
| 51 | BOOST_CORE_STATIC_ASSERT( sizeof(key_value_pair) == 32 ); | 51 | BOOST_CORE_STATIC_ASSERT( sizeof(key_value_pair) == 32 ); | |||||
| 52 | char pad[4] = {}; // silence warnings | 52 | char pad[4] = {}; // silence warnings | |||||
| 53 | #endif | 53 | #endif | |||||
| 54 | 54 | |||||||
| 55 | constexpr table(); | 55 | constexpr table(); | |||||
| 56 | 56 | |||||||
| 57 | // returns true if we use a linear | 57 | // returns true if we use a linear | |||||
| 58 | // search instead of the hash table. | 58 | // search instead of the hash table. | |||||
| HITCBC | 59 | 122186 | bool is_small() const noexcept | 59 | 122186 | bool is_small() const noexcept | ||
| 60 | { | 60 | { | |||||
| HITCBC | 61 | 122186 | return capacity <= | 61 | 122186 | return capacity <= | ||
| HITCBC | 62 | 122186 | detail::small_object_size_; | 62 | 122186 | detail::small_object_size_; | ||
| 63 | } | 63 | } | |||||
| 64 | 64 | |||||||
| 65 | key_value_pair& | 65 | key_value_pair& | |||||
| HITCBC | 66 | 294485 | operator[]( | 66 | 294046 | operator[]( | ||
| 67 | std::size_t pos) noexcept | 67 | std::size_t pos) noexcept | |||||
| 68 | { | 68 | { | |||||
| 69 | return reinterpret_cast< | 69 | return reinterpret_cast< | |||||
| 70 | key_value_pair*>( | 70 | key_value_pair*>( | |||||
| HITCBC | 71 | 294485 | this + 1)[pos]; | 71 | 294046 | this + 1)[pos]; | ||
| 72 | } | 72 | } | |||||
| 73 | 73 | |||||||
| 74 | // VFALCO This is exported for tests | 74 | // VFALCO This is exported for tests | |||||
| 75 | BOOST_JSON_DECL | 75 | BOOST_JSON_DECL | |||||
| 76 | std::size_t | 76 | std::size_t | |||||
| 77 | digest(string_view key) const noexcept; | 77 | digest(string_view key) const noexcept; | |||||
| 78 | 78 | |||||||
| 79 | inline | 79 | inline | |||||
| 80 | index_t& | 80 | index_t& | |||||
| 81 | bucket(std::size_t hash) noexcept; | 81 | bucket(std::size_t hash) noexcept; | |||||
| 82 | 82 | |||||||
| 83 | inline | 83 | inline | |||||
| 84 | index_t& | 84 | index_t& | |||||
| 85 | bucket(string_view key) noexcept; | 85 | bucket(string_view key) noexcept; | |||||
| 86 | 86 | |||||||
| 87 | inline | 87 | inline | |||||
| 88 | void | 88 | void | |||||
| 89 | clear() noexcept; | 89 | clear() noexcept; | |||||
| 90 | 90 | |||||||
| 91 | static | 91 | static | |||||
| 92 | inline | 92 | inline | |||||
| 93 | table* | 93 | table* | |||||
| 94 | allocate( | 94 | allocate( | |||||
| 95 | std::size_t capacity, | 95 | std::size_t capacity, | |||||
| 96 | std::uintptr_t salt, | 96 | std::uintptr_t salt, | |||||
| 97 | storage_ptr const& sp); | 97 | storage_ptr const& sp); | |||||
| 98 | 98 | |||||||
| 99 | static | 99 | static | |||||
| 100 | void | 100 | void | |||||
| HITCBC | 101 | 36352 | deallocate( | 101 | 36352 | deallocate( | ||
| 102 | table* p, | 102 | table* p, | |||||
| 103 | storage_ptr const& sp) noexcept | 103 | storage_ptr const& sp) noexcept | |||||
| 104 | { | 104 | { | |||||
| HITCBC | 105 | 36352 | if(p->capacity == 0) | 105 | 36352 | if(p->capacity == 0) | ||
| HITCBC | 106 | 983 | return; | 106 | 983 | return; | ||
| HITCBC | 107 | 35369 | if(! p->is_small()) | 107 | 35369 | if(! p->is_small()) | ||
| HITCBC | 108 | 388 | sp->deallocate(p, | 108 | 388 | sp->deallocate(p, | ||
| HITCBC | 109 | 388 | sizeof(table) + p->capacity * ( | 109 | 388 | sizeof(table) + p->capacity * ( | ||
| 110 | sizeof(key_value_pair) + | 110 | sizeof(key_value_pair) + | |||||
| 111 | sizeof(index_t))); | 111 | sizeof(index_t))); | |||||
| 112 | else | 112 | else | |||||
| HITCBC | 113 | 34981 | sp->deallocate(p, | 113 | 34981 | sp->deallocate(p, | ||
| HITCBC | 114 | 34981 | sizeof(table) + p->capacity * | 114 | 34981 | sizeof(table) + p->capacity * | ||
| 115 | sizeof(key_value_pair)); | 115 | sizeof(key_value_pair)); | |||||
| 116 | } | 116 | } | |||||
| 117 | }; | 117 | }; | |||||
| 118 | 118 | |||||||
| 119 | //---------------------------------------------------------- | 119 | //---------------------------------------------------------- | |||||
| 120 | 120 | |||||||
| 121 | class object::revert_construct | 121 | class object::revert_construct | |||||
| 122 | { | 122 | { | |||||
| 123 | object* obj_; | 123 | object* obj_; | |||||
| 124 | 124 | |||||||
| 125 | BOOST_JSON_DECL | 125 | BOOST_JSON_DECL | |||||
| 126 | void | 126 | void | |||||
| 127 | destroy() noexcept; | 127 | destroy() noexcept; | |||||
| 128 | 128 | |||||||
| 129 | public: | 129 | public: | |||||
| 130 | explicit | 130 | explicit | |||||
| HITCBC | 131 | 705 | revert_construct( | 131 | 705 | revert_construct( | ||
| 132 | object& obj) noexcept | 132 | object& obj) noexcept | |||||
| HITCBC | 133 | 705 | : obj_(&obj) | 133 | 705 | : obj_(&obj) | ||
| 134 | { | 134 | { | |||||
| HITCBC | 135 | 705 | } | 135 | 705 | } | ||
| 136 | 136 | |||||||
| HITCBC | 137 | 705 | ~revert_construct() | 137 | 705 | ~revert_construct() | ||
| HITCBC | 138 | 374 | { | 138 | 374 | { | ||
| HITCBC | 139 | 705 | if(! obj_) | 139 | 705 | if(! obj_) | ||
| HITCBC | 140 | 331 | return; | 140 | 331 | return; | ||
| HITCBC | 141 | 374 | destroy(); | 141 | 374 | destroy(); | ||
| HITCBC | 142 | 705 | } | 142 | 705 | } | ||
| 143 | 143 | |||||||
| 144 | void | 144 | void | |||||
| HITCBC | 145 | 331 | commit() noexcept | 145 | 331 | commit() noexcept | ||
| 146 | { | 146 | { | |||||
| HITCBC | 147 | 331 | obj_ = nullptr; | 147 | 331 | obj_ = nullptr; | ||
| HITCBC | 148 | 331 | } | 148 | 331 | } | ||
| 149 | }; | 149 | }; | |||||
| 150 | 150 | |||||||
| 151 | //---------------------------------------------------------- | 151 | //---------------------------------------------------------- | |||||
| 152 | 152 | |||||||
| 153 | class object::revert_insert | 153 | class object::revert_insert | |||||
| 154 | { | 154 | { | |||||
| 155 | object* obj_; | 155 | object* obj_; | |||||
| 156 | table* t_ = nullptr; | 156 | table* t_ = nullptr; | |||||
| 157 | std::size_t size_; | 157 | std::size_t size_; | |||||
| 158 | 158 | |||||||
| 159 | BOOST_JSON_DECL | 159 | BOOST_JSON_DECL | |||||
| 160 | void | 160 | void | |||||
| 161 | destroy() noexcept; | 161 | destroy() noexcept; | |||||
| 162 | 162 | |||||||
| 163 | public: | 163 | public: | |||||
| 164 | explicit | 164 | explicit | |||||
| HITCBC | 165 | 503 | revert_insert( | 165 | 503 | revert_insert( | ||
| 166 | object& obj, | 166 | object& obj, | |||||
| 167 | std::size_t capacity) | 167 | std::size_t capacity) | |||||
| HITCBC | 168 | 503 | : obj_(&obj) | 168 | 503 | : obj_(&obj) | ||
| HITCBC | 169 | 503 | , size_(obj_->size()) | 169 | 503 | , size_(obj_->size()) | ||
| 170 | { | 170 | { | |||||
| HITCBC | 171 | 503 | if( capacity > obj_->capacity() ) | 171 | 503 | if( capacity > obj_->capacity() ) | ||
| HITCBC | 172 | 138 | t_ = obj_->reserve_impl(capacity); | 172 | 138 | t_ = obj_->reserve_impl(capacity); | ||
| HITCBC | 173 | 494 | } | 173 | 494 | } | ||
| 174 | 174 | |||||||
| HITCBC | 175 | 494 | ~revert_insert() | 175 | 494 | ~revert_insert() | ||
| HITCBC | 176 | 230 | { | 176 | 230 | { | ||
| HITCBC | 177 | 494 | if(! obj_) | 177 | 494 | if(! obj_) | ||
| HITCBC | 178 | 264 | return; | 178 | 264 | return; | ||
| 179 | 179 | |||||||
| HITCBC | 180 | 230 | destroy(); | 180 | 230 | destroy(); | ||
| HITCBC | 181 | 230 | if( t_ ) | 181 | 230 | if( t_ ) | ||
| 182 | { | 182 | { | |||||
| HITCBC | 183 | 117 | table::deallocate( obj_->t_, obj_->sp_ ); | 183 | 117 | table::deallocate( obj_->t_, obj_->sp_ ); | ||
| HITCBC | 184 | 117 | obj_->t_ = t_; | 184 | 117 | obj_->t_ = t_; | ||
| 185 | } | 185 | } | |||||
| 186 | else | 186 | else | |||||
| 187 | { | 187 | { | |||||
| HITCBC | 188 | 113 | obj_->t_->size = static_cast<index_t>(size_); | 188 | 113 | obj_->t_->size = static_cast<index_t>(size_); | ||
| 189 | } | 189 | } | |||||
| HITCBC | 190 | 494 | } | 190 | 494 | } | ||
| 191 | 191 | |||||||
| 192 | void | 192 | void | |||||
| HITCBC | 193 | 264 | commit() noexcept | 193 | 264 | commit() noexcept | ||
| 194 | { | 194 | { | |||||
| HITCBC | 195 | 264 | BOOST_ASSERT(obj_); | 195 | 264 | BOOST_ASSERT(obj_); | ||
| HITCBC | 196 | 264 | if( t_ ) | 196 | 264 | if( t_ ) | ||
| HITCBC | 197 | 12 | table::deallocate( t_, obj_->sp_ ); | 197 | 12 | table::deallocate( t_, obj_->sp_ ); | ||
| HITCBC | 198 | 264 | obj_ = nullptr; | 198 | 264 | obj_ = nullptr; | ||
| HITCBC | 199 | 264 | } | 199 | 264 | } | ||
| 200 | }; | 200 | }; | |||||
| 201 | 201 | |||||||
| 202 | //---------------------------------------------------------- | 202 | //---------------------------------------------------------- | |||||
| 203 | // | 203 | // | |||||
| 204 | // Iterators | 204 | // Iterators | |||||
| 205 | // | 205 | // | |||||
| 206 | //---------------------------------------------------------- | 206 | //---------------------------------------------------------- | |||||
| 207 | 207 | |||||||
| 208 | auto | 208 | auto | |||||
| HITCBC | 209 | 70788 | object:: | 209 | 70788 | object:: | ||
| 210 | begin() noexcept -> | 210 | begin() noexcept -> | |||||
| 211 | iterator | 211 | iterator | |||||
| 212 | { | 212 | { | |||||
| HITCBC | 213 | 70788 | return &(*t_)[0]; | 213 | 70788 | return &(*t_)[0]; | ||
| 214 | } | 214 | } | |||||
| 215 | 215 | |||||||
| 216 | auto | 216 | auto | |||||
| HITCBC | 217 | 53205 | object:: | 217 | 53205 | object:: | ||
| 218 | begin() const noexcept -> | 218 | begin() const noexcept -> | |||||
| 219 | const_iterator | 219 | const_iterator | |||||
| 220 | { | 220 | { | |||||
| HITCBC | 221 | 53205 | return &(*t_)[0]; | 221 | 53205 | return &(*t_)[0]; | ||
| 222 | } | 222 | } | |||||
| 223 | 223 | |||||||
| 224 | auto | 224 | auto | |||||
| HITCBC | 225 | 3 | object:: | 225 | 3 | object:: | ||
| 226 | cbegin() const noexcept -> | 226 | cbegin() const noexcept -> | |||||
| 227 | const_iterator | 227 | const_iterator | |||||
| 228 | { | 228 | { | |||||
| HITCBC | 229 | 3 | return &(*t_)[0]; | 229 | 3 | return &(*t_)[0]; | ||
| 230 | } | 230 | } | |||||
| 231 | 231 | |||||||
| 232 | auto | 232 | auto | |||||
| HITCBC | 233 | 46093 | object:: | 233 | 46093 | object:: | ||
| 234 | end() noexcept -> | 234 | end() noexcept -> | |||||
| 235 | iterator | 235 | iterator | |||||
| 236 | { | 236 | { | |||||
| HITCBC | 237 | 46093 | return &(*t_)[t_->size]; | 237 | 46093 | return &(*t_)[t_->size]; | ||
| 238 | } | 238 | } | |||||
| 239 | 239 | |||||||
| 240 | auto | 240 | auto | |||||
| HITCBC | 241 | 27786 | object:: | 241 | 27786 | object:: | ||
| 242 | end() const noexcept -> | 242 | end() const noexcept -> | |||||
| 243 | const_iterator | 243 | const_iterator | |||||
| 244 | { | 244 | { | |||||
| HITCBC | 245 | 27786 | return &(*t_)[t_->size]; | 245 | 27786 | return &(*t_)[t_->size]; | ||
| 246 | } | 246 | } | |||||
| 247 | 247 | |||||||
| 248 | auto | 248 | auto | |||||
| HITCBC | 249 | 3 | object:: | 249 | 3 | object:: | ||
| 250 | cend() const noexcept -> | 250 | cend() const noexcept -> | |||||
| 251 | const_iterator | 251 | const_iterator | |||||
| 252 | { | 252 | { | |||||
| HITCBC | 253 | 3 | return &(*t_)[t_->size]; | 253 | 3 | return &(*t_)[t_->size]; | ||
| 254 | } | 254 | } | |||||
| 255 | 255 | |||||||
| 256 | auto | 256 | auto | |||||
| HITCBC | 257 | 2 | object:: | 257 | 2 | object:: | ||
| 258 | rbegin() noexcept -> | 258 | rbegin() noexcept -> | |||||
| 259 | reverse_iterator | 259 | reverse_iterator | |||||
| 260 | { | 260 | { | |||||
| HITCBC | 261 | 2 | return reverse_iterator(end()); | 261 | 2 | return reverse_iterator(end()); | ||
| 262 | } | 262 | } | |||||
| 263 | 263 | |||||||
| 264 | auto | 264 | auto | |||||
| HITCBC | 265 | 2 | object:: | 265 | 2 | object:: | ||
| 266 | rbegin() const noexcept -> | 266 | rbegin() const noexcept -> | |||||
| 267 | const_reverse_iterator | 267 | const_reverse_iterator | |||||
| 268 | { | 268 | { | |||||
| HITCBC | 269 | 2 | return const_reverse_iterator(end()); | 269 | 2 | return const_reverse_iterator(end()); | ||
| 270 | } | 270 | } | |||||
| 271 | 271 | |||||||
| 272 | auto | 272 | auto | |||||
| HITCBC | 273 | 2 | object:: | 273 | 2 | object:: | ||
| 274 | crbegin() const noexcept -> | 274 | crbegin() const noexcept -> | |||||
| 275 | const_reverse_iterator | 275 | const_reverse_iterator | |||||
| 276 | { | 276 | { | |||||
| HITCBC | 277 | 2 | return const_reverse_iterator(end()); | 277 | 2 | return const_reverse_iterator(end()); | ||
| 278 | } | 278 | } | |||||
| 279 | 279 | |||||||
| 280 | auto | 280 | auto | |||||
| HITCBC | 281 | 2 | object:: | 281 | 2 | object:: | ||
| 282 | rend() noexcept -> | 282 | rend() noexcept -> | |||||
| 283 | reverse_iterator | 283 | reverse_iterator | |||||
| 284 | { | 284 | { | |||||
| HITCBC | 285 | 2 | return reverse_iterator(begin()); | 285 | 2 | return reverse_iterator(begin()); | ||
| 286 | } | 286 | } | |||||
| 287 | 287 | |||||||
| 288 | auto | 288 | auto | |||||
| HITCBC | 289 | 2 | object:: | 289 | 2 | object:: | ||
| 290 | rend() const noexcept -> | 290 | rend() const noexcept -> | |||||
| 291 | const_reverse_iterator | 291 | const_reverse_iterator | |||||
| 292 | { | 292 | { | |||||
| HITCBC | 293 | 2 | return const_reverse_iterator(begin()); | 293 | 2 | return const_reverse_iterator(begin()); | ||
| 294 | } | 294 | } | |||||
| 295 | 295 | |||||||
| 296 | auto | 296 | auto | |||||
| HITCBC | 297 | 2 | object:: | 297 | 2 | object:: | ||
| 298 | crend() const noexcept -> | 298 | crend() const noexcept -> | |||||
| 299 | const_reverse_iterator | 299 | const_reverse_iterator | |||||
| 300 | { | 300 | { | |||||
| HITCBC | 301 | 2 | return const_reverse_iterator(begin()); | 301 | 2 | return const_reverse_iterator(begin()); | ||
| 302 | } | 302 | } | |||||
| 303 | 303 | |||||||
| 304 | //---------------------------------------------------------- | 304 | //---------------------------------------------------------- | |||||
| 305 | // | 305 | // | |||||
| 306 | // Capacity | 306 | // Capacity | |||||
| 307 | // | 307 | // | |||||
| 308 | //---------------------------------------------------------- | 308 | //---------------------------------------------------------- | |||||
| 309 | 309 | |||||||
| 310 | bool | 310 | bool | |||||
| HITCBC | 311 | 10473 | object:: | 311 | 10473 | object:: | ||
| 312 | empty() const noexcept | 312 | empty() const noexcept | |||||
| 313 | { | 313 | { | |||||
| HITCBC | 314 | 10473 | return t_->size == 0; | 314 | 10473 | return t_->size == 0; | ||
| 315 | } | 315 | } | |||||
| 316 | 316 | |||||||
| 317 | auto | 317 | auto | |||||
| HITCBC | 318 | 44249 | object:: | 318 | 44249 | object:: | ||
| 319 | size() const noexcept -> | 319 | size() const noexcept -> | |||||
| 320 | std::size_t | 320 | std::size_t | |||||
| 321 | { | 321 | { | |||||
| HITCBC | 322 | 44249 | return t_->size; | 322 | 44249 | return t_->size; | ||
| 323 | } | 323 | } | |||||
| 324 | 324 | |||||||
| 325 | constexpr | 325 | constexpr | |||||
| 326 | std::size_t | 326 | std::size_t | |||||
| HITCBC | 327 | 73125 | object:: | 327 | 73125 | object:: | ||
| 328 | max_size() noexcept | 328 | max_size() noexcept | |||||
| 329 | { | 329 | { | |||||
| 330 | // max_size depends on the address model | 330 | // max_size depends on the address model | |||||
| 331 | using min = std::integral_constant<std::size_t, | 331 | using min = std::integral_constant<std::size_t, | |||||
| 332 | (std::size_t(-1) - sizeof(table)) / | 332 | (std::size_t(-1) - sizeof(table)) / | |||||
| 333 | (sizeof(key_value_pair) + sizeof(index_t))>; | 333 | (sizeof(key_value_pair) + sizeof(index_t))>; | |||||
| 334 | return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ? | 334 | return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ? | |||||
| HITCBC | 335 | 73125 | min::value : BOOST_JSON_MAX_STRUCTURED_SIZE; | 335 | 73125 | min::value : BOOST_JSON_MAX_STRUCTURED_SIZE; | ||
| 336 | } | 336 | } | |||||
| 337 | 337 | |||||||
| 338 | auto | 338 | auto | |||||
| HITCBC | 339 | 18848 | object:: | 339 | 18848 | object:: | ||
| 340 | capacity() const noexcept -> | 340 | capacity() const noexcept -> | |||||
| 341 | std::size_t | 341 | std::size_t | |||||
| 342 | { | 342 | { | |||||
| HITCBC | 343 | 18848 | return t_->capacity; | 343 | 18848 | return t_->capacity; | ||
| 344 | } | 344 | } | |||||
| 345 | 345 | |||||||
| 346 | void | 346 | void | |||||
| HITCBC | 347 | 4742 | object:: | 347 | 4742 | object:: | ||
| 348 | reserve(std::size_t new_capacity) | 348 | reserve(std::size_t new_capacity) | |||||
| 349 | { | 349 | { | |||||
| HITCBC | 350 | 4742 | if( new_capacity <= capacity() ) | 350 | 4742 | if( new_capacity <= capacity() ) | ||
| HITCBC | 351 | 3224 | return; | 351 | 3224 | return; | ||
| HITCBC | 352 | 1518 | table* const old_table = reserve_impl(new_capacity); | 352 | 1518 | table* const old_table = reserve_impl(new_capacity); | ||
| HITCBC | 353 | 1453 | table::deallocate( old_table, sp_ ); | 353 | 1453 | table::deallocate( old_table, sp_ ); | ||
| 354 | } | 354 | } | |||||
| 355 | 355 | |||||||
| 356 | //---------------------------------------------------------- | 356 | //---------------------------------------------------------- | |||||
| 357 | // | 357 | // | |||||
| 358 | // Lookup | 358 | // Lookup | |||||
| 359 | // | 359 | // | |||||
| 360 | //---------------------------------------------------------- | 360 | //---------------------------------------------------------- | |||||
| 361 | 361 | |||||||
| 362 | value& | 362 | value& | |||||
| HITCBC | 363 | 42 | object:: | 363 | 42 | object:: | ||
| 364 | at(string_view key, source_location const& loc) & | 364 | at(string_view key, source_location const& loc) & | |||||
| 365 | { | 365 | { | |||||
| HITCBC | 366 | 42 | auto const& self = *this; | 366 | 42 | auto const& self = *this; | ||
| HITCBC | 367 | 42 | return const_cast< value& >( self.at(key, loc) ); | 367 | 42 | return const_cast< value& >( self.at(key, loc) ); | ||
| 368 | } | 368 | } | |||||
| 369 | 369 | |||||||
| 370 | value&& | 370 | value&& | |||||
| HITCBC | 371 | 5 | object:: | 371 | 5 | object:: | ||
| 372 | at(string_view key, source_location const& loc) && | 372 | at(string_view key, source_location const& loc) && | |||||
| 373 | { | 373 | { | |||||
| HITCBC | 374 | 5 | return std::move( at(key, loc) ); | 374 | 5 | return std::move( at(key, loc) ); | ||
| 375 | } | 375 | } | |||||
| 376 | 376 | |||||||
| 377 | //---------------------------------------------------------- | 377 | //---------------------------------------------------------- | |||||
| 378 | 378 | |||||||
| 379 | template<class P, class> | 379 | template<class P, class> | |||||
| 380 | auto | 380 | auto | |||||
| HITCBC | 381 | 3127 | object:: | 381 | 3127 | object:: | ||
| 382 | insert(P&& p) -> | 382 | insert(P&& p) -> | |||||
| 383 | std::pair<iterator, bool> | 383 | std::pair<iterator, bool> | |||||
| 384 | { | 384 | { | |||||
| HITCBC | 385 | 3422 | key_value_pair v( | 385 | 3422 | key_value_pair v( | ||
| HITCBC | 386 | 3127 | std::forward<P>(p), sp_); | 386 | 3127 | std::forward<P>(p), sp_); | ||
| HITCBC | 387 | 5791 | return emplace_impl( v.key(), pilfer(v) ); | 387 | 5791 | return emplace_impl( v.key(), pilfer(v) ); | ||
| HITCBC | 388 | 2979 | } | 388 | 2979 | } | ||
| 389 | 389 | |||||||
| 390 | template<class M> | 390 | template<class M> | |||||
| 391 | auto | 391 | auto | |||||
| HITCBC | 392 | 17 | object:: | 392 | 17 | object:: | ||
| 393 | insert_or_assign( | 393 | insert_or_assign( | |||||
| 394 | string_view key, M&& m) -> | 394 | string_view key, M&& m) -> | |||||
| 395 | std::pair<iterator, bool> | 395 | std::pair<iterator, bool> | |||||
| 396 | { | 396 | { | |||||
| HITCBC | 397 | 17 | std::pair<iterator, bool> result = emplace_impl( | 397 | 17 | std::pair<iterator, bool> result = emplace_impl( | ||
| 398 | key, key, static_cast<M&&>(m) ); | 398 | key, key, static_cast<M&&>(m) ); | |||||
| HITCBC | 399 | 10 | if( !result.second ) | 399 | 10 | if( !result.second ) | ||
| 400 | { | 400 | { | |||||
| HITCBC | 401 | 8 | value(static_cast<M>(m), sp_).swap( | 401 | 8 | value(static_cast<M>(m), sp_).swap( | ||
| HITCBC | 402 | 3 | result.first->value()); | 402 | 3 | result.first->value()); | ||
| 403 | } | 403 | } | |||||
| HITCBC | 404 | 9 | return result; | 404 | 9 | return result; | ||
| 405 | } | 405 | } | |||||
| 406 | 406 | |||||||
| 407 | template<class Arg> | 407 | template<class Arg> | |||||
| 408 | auto | 408 | auto | |||||
| HITCBC | 409 | 995 | object:: | 409 | 995 | object:: | ||
| 410 | emplace( | 410 | emplace( | |||||
| 411 | string_view key, | 411 | string_view key, | |||||
| 412 | Arg&& arg) -> | 412 | Arg&& arg) -> | |||||
| 413 | std::pair<iterator, bool> | 413 | std::pair<iterator, bool> | |||||
| 414 | { | 414 | { | |||||
| HITCBC | 415 | 995 | return emplace_impl( key, key, static_cast<Arg&&>(arg) ); | 415 | 995 | return emplace_impl( key, key, static_cast<Arg&&>(arg) ); | ||
| 416 | } | 416 | } | |||||
| 417 | 417 | |||||||
| 418 | //---------------------------------------------------------- | 418 | //---------------------------------------------------------- | |||||
| 419 | // | 419 | // | |||||
| 420 | // (private) | 420 | // (private) | |||||
| 421 | // | 421 | // | |||||
| 422 | //---------------------------------------------------------- | 422 | //---------------------------------------------------------- | |||||
| 423 | 423 | |||||||
| 424 | template<class InputIt> | 424 | template<class InputIt> | |||||
| 425 | void | 425 | void | |||||
| HITCBC | 426 | 78 | object:: | 426 | 78 | object:: | ||
| 427 | construct( | 427 | construct( | |||||
| 428 | InputIt first, | 428 | InputIt first, | |||||
| 429 | InputIt last, | 429 | InputIt last, | |||||
| 430 | std::size_t min_capacity, | 430 | std::size_t min_capacity, | |||||
| 431 | std::input_iterator_tag) | 431 | std::input_iterator_tag) | |||||
| 432 | { | 432 | { | |||||
| HITCBC | 433 | 78 | reserve(min_capacity); | 433 | 78 | reserve(min_capacity); | ||
| HITCBC | 434 | 76 | revert_construct r(*this); | 434 | 76 | revert_construct r(*this); | ||
| HITCBC | 435 | 753 | while(first != last) | 435 | 753 | while(first != last) | ||
| 436 | { | 436 | { | |||||
| HITCBC | 437 | 750 | insert(*first); | 437 | 750 | insert(*first); | ||
| HITCBC | 438 | 677 | ++first; | 438 | 677 | ++first; | ||
| 439 | } | 439 | } | |||||
| HITCBC | 440 | 3 | r.commit(); | 440 | 3 | r.commit(); | ||
| HITCBC | 441 | 76 | } | 441 | 76 | } | ||
| 442 | 442 | |||||||
| 443 | template<class InputIt> | 443 | template<class InputIt> | |||||
| 444 | void | 444 | void | |||||
| HITCBC | 445 | 82 | object:: | 445 | 82 | object:: | ||
| 446 | construct( | 446 | construct( | |||||
| 447 | InputIt first, | 447 | InputIt first, | |||||
| 448 | InputIt last, | 448 | InputIt last, | |||||
| 449 | std::size_t min_capacity, | 449 | std::size_t min_capacity, | |||||
| 450 | std::forward_iterator_tag) | 450 | std::forward_iterator_tag) | |||||
| 451 | { | 451 | { | |||||
| HITCBC | 452 | 82 | auto n = static_cast< | 452 | 82 | auto n = static_cast< | ||
| HITCBC | 453 | 82 | std::size_t>(std::distance( | 453 | 82 | std::size_t>(std::distance( | ||
| 454 | first, last)); | 454 | first, last)); | |||||
| HITCBC | 455 | 82 | if( n < min_capacity) | 455 | 82 | if( n < min_capacity) | ||
| HITCBC | 456 | 76 | n = min_capacity; | 456 | 76 | n = min_capacity; | ||
| HITCBC | 457 | 82 | reserve(n); | 457 | 82 | reserve(n); | ||
| HITCBC | 458 | 79 | revert_construct r(*this); | 458 | 79 | revert_construct r(*this); | ||
| HITCBC | 459 | 771 | while(first != last) | 459 | 771 | while(first != last) | ||
| 460 | { | 460 | { | |||||
| HITCBC | 461 | 764 | insert(*first); | 461 | 764 | insert(*first); | ||
| HITCBC | 462 | 692 | ++first; | 462 | 692 | ++first; | ||
| 463 | } | 463 | } | |||||
| HITCBC | 464 | 7 | r.commit(); | 464 | 7 | r.commit(); | ||
| HITCBC | 465 | 79 | } | 465 | 79 | } | ||
| 466 | 466 | |||||||
| 467 | template<class InputIt> | 467 | template<class InputIt> | |||||
| 468 | void | 468 | void | |||||
| HITCBC | 469 | 94 | object:: | 469 | 94 | object:: | ||
| 470 | insert( | 470 | insert( | |||||
| 471 | InputIt first, | 471 | InputIt first, | |||||
| 472 | InputIt last, | 472 | InputIt last, | |||||
| 473 | std::input_iterator_tag) | 473 | std::input_iterator_tag) | |||||
| 474 | { | 474 | { | |||||
| 475 | // Since input iterators cannot be rewound, | 475 | // Since input iterators cannot be rewound, | |||||
| 476 | // we keep inserted elements on an exception. | 476 | // we keep inserted elements on an exception. | |||||
| 477 | // | 477 | // | |||||
| HITCBC | 478 | 871 | while(first != last) | 478 | 871 | while(first != last) | ||
| 479 | { | 479 | { | |||||
| HITCBC | 480 | 867 | insert(*first); | 480 | 867 | insert(*first); | ||
| HITCBC | 481 | 777 | ++first; | 481 | 777 | ++first; | ||
| 482 | } | 482 | } | |||||
| HITCBC | 483 | 4 | } | 483 | 4 | } | ||
| 484 | 484 | |||||||
| 485 | template<class InputIt> | 485 | template<class InputIt> | |||||
| 486 | void | 486 | void | |||||
| HITCBC | 487 | 80 | object:: | 487 | 80 | object:: | ||
| 488 | insert( | 488 | insert( | |||||
| 489 | InputIt first, | 489 | InputIt first, | |||||
| 490 | InputIt last, | 490 | InputIt last, | |||||
| 491 | std::forward_iterator_tag) | 491 | std::forward_iterator_tag) | |||||
| 492 | { | 492 | { | |||||
| HITCBC | 493 | 80 | auto const n = | 493 | 80 | auto const n = | ||
| 494 | static_cast<std::size_t>( | 494 | static_cast<std::size_t>( | |||||
| HITCBC | 495 | 80 | std::distance(first, last)); | 495 | 80 | std::distance(first, last)); | ||
| HITCBC | 496 | 80 | auto const n0 = size(); | 496 | 80 | auto const n0 = size(); | ||
| HITCBC | 497 | 80 | if(n > max_size() - n0) | 497 | 80 | if(n > max_size() - n0) | ||
| 498 | { | 498 | { | |||||
| 499 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 499 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 500 | 1 | detail::throw_system_error( error::object_too_large, &loc ); | 500 | 1 | detail::throw_system_error( error::object_too_large, &loc ); | ||
| 501 | } | 501 | } | |||||
| HITCBC | 502 | 79 | revert_insert r( *this, n0 + n ); | 502 | 79 | revert_insert r( *this, n0 + n ); | ||
| HITCBC | 503 | 738 | while(first != last) | 503 | 738 | while(first != last) | ||
| 504 | { | 504 | { | |||||
| HITCBC | 505 | 734 | insert(*first); | 505 | 734 | insert(*first); | ||
| HITCBC | 506 | 661 | ++first; | 506 | 661 | ++first; | ||
| 507 | } | 507 | } | |||||
| HITCBC | 508 | 4 | r.commit(); | 508 | 4 | r.commit(); | ||
| HITCBC | 509 | 77 | } | 509 | 77 | } | ||
| 510 | 510 | |||||||
| 511 | template< class... Args > | 511 | template< class... Args > | |||||
| 512 | std::pair<object::iterator, bool> | 512 | std::pair<object::iterator, bool> | |||||
| HITCBC | 513 | 3991 | object:: | 513 | 3991 | object:: | ||
| 514 | emplace_impl( string_view key, Args&& ... args ) | 514 | emplace_impl( string_view key, Args&& ... args ) | |||||
| 515 | { | 515 | { | |||||
| HITCBC | 516 | 3991 | std::pair<iterator, std::size_t> search_result(nullptr, 0); | 516 | 3991 | std::pair<iterator, std::size_t> search_result(nullptr, 0); | ||
| HITCBC | 517 | 3991 | if( !empty() ) | 517 | 3991 | if( !empty() ) | ||
| 518 | { | 518 | { | |||||
| HITCBC | 519 | 3462 | search_result = detail::find_in_object(*this, key); | 519 | 3462 | search_result = detail::find_in_object(*this, key); | ||
| HITCBC | 520 | 3462 | if( search_result.first ) | 520 | 3462 | if( search_result.first ) | ||
| HITCBC | 521 | 30 | return { search_result.first, false }; | 521 | 30 | return { search_result.first, false }; | ||
| 522 | } | 522 | } | |||||
| 523 | 523 | |||||||
| 524 | // we create the new value before reserving, in case it is a reference to | 524 | // we create the new value before reserving, in case it is a reference to | |||||
| 525 | // a subobject of the current object | 525 | // a subobject of the current object | |||||
| HITCBC | 526 | 4253 | key_value_pair kv( static_cast<Args&&>(args)..., sp_ ); | 526 | 4253 | key_value_pair kv( static_cast<Args&&>(args)..., sp_ ); | ||
| 527 | // the key might get deallocated too | 527 | // the key might get deallocated too | |||||
| HITCBC | 528 | 3808 | key = kv.key(); | 528 | 3808 | key = kv.key(); | ||
| 529 | 529 | |||||||
| HITCBC | 530 | 3808 | std::size_t const old_capacity = capacity(); | 530 | 3808 | std::size_t const old_capacity = capacity(); | ||
| HITCBC | 531 | 3808 | reserve(size() + 1); | 531 | 3808 | reserve(size() + 1); | ||
| HITCBC | 532 | 4294 | if( (empty() && capacity() > detail::small_object_size_) | 532 | 4294 | if( (empty() && capacity() > detail::small_object_size_) | ||
| HITCBC | 533 | 4294 | || (capacity() != old_capacity) ) | 533 | 4294 | || (capacity() != old_capacity) ) | ||
| HITCBC | 534 | 724 | search_result.second = detail::digest( | 534 | 724 | search_result.second = detail::digest( | ||
| HITCBC | 535 | 724 | key.begin(), key.end(), t_->salt); | 535 | 724 | key.begin(), key.end(), t_->salt); | ||
| 536 | 536 | |||||||
| HITCBC | 537 | 3781 | BOOST_ASSERT( | 537 | 3781 | BOOST_ASSERT( | ||
| 538 | t_->is_small() || | 538 | t_->is_small() || | |||||
| 539 | (search_result.second == | 539 | (search_result.second == | |||||
| 540 | detail::digest(key.begin(), key.end(), t_->salt)) ); | 540 | detail::digest(key.begin(), key.end(), t_->salt)) ); | |||||
| 541 | 541 | |||||||
| HITCBC | 542 | 3781 | return { insert_impl(pilfer(kv), search_result.second), true }; | 542 | 3781 | return { insert_impl(pilfer(kv), search_result.second), true }; | ||
| HITCBC | 543 | 3808 | } | 543 | 3808 | } | ||
| 544 | 544 | |||||||
| 545 | //---------------------------------------------------------- | 545 | //---------------------------------------------------------- | |||||
| 546 | 546 | |||||||
| 547 | namespace detail { | 547 | namespace detail { | |||||
| 548 | 548 | |||||||
| HITCBC | 549 | 34879 | unchecked_object:: | 549 | 34879 | unchecked_object:: | ||
| HITCBC | 550 | 1086 | ~unchecked_object() | 550 | 1086 | ~unchecked_object() | ||
| 551 | { | 551 | { | |||||
| HITCBC | 552 | 34879 | if(! data_) | 552 | 34879 | if(! data_) | ||
| HITCBC | 553 | 33791 | return; | 553 | 33791 | return; | ||
| HITCBC | 554 | 1088 | if(sp_.is_not_shared_and_deallocate_is_trivial()) | 554 | 1088 | if(sp_.is_not_shared_and_deallocate_is_trivial()) | ||
| HITCBC | 555 | 2 | return; | 555 | 2 | return; | ||
| HITCBC | 556 | 1086 | value* p = data_; | 556 | 1086 | value* p = data_; | ||
| HITCBC | 557 | 1146 | while(size_--) | 557 | 1146 | while(size_--) | ||
| 558 | { | 558 | { | |||||
| HITCBC | 559 | 60 | p[0].~value(); | 559 | 60 | p[0].~value(); | ||
| HITCBC | 560 | 60 | p[1].~value(); | 560 | 60 | p[1].~value(); | ||
| HITCBC | 561 | 60 | p += 2; | 561 | 60 | p += 2; | ||
| 562 | } | 562 | } | |||||
| HITCBC | 563 | 34879 | } | 563 | 34879 | } | ||
| 564 | 564 | |||||||
| 565 | } // detail | 565 | } // detail | |||||
| 566 | 566 | |||||||
| 567 | } // namespace json | 567 | } // namespace json | |||||
| 568 | } // namespace boost | 568 | } // namespace boost | |||||
| 569 | 569 | |||||||
| 570 | #endif | 570 | #endif | |||||