100.00% Lines (441/441)
100.00% Functions (49/49)
| 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_IPP | 10 | #ifndef BOOST_JSON_IMPL_OBJECT_IPP | |||||
| 11 | #define BOOST_JSON_IMPL_OBJECT_IPP | 11 | #define BOOST_JSON_IMPL_OBJECT_IPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/core/detail/static_assert.hpp> | 13 | #include <boost/core/detail/static_assert.hpp> | |||||
| 14 | #include <boost/container_hash/hash.hpp> | 14 | #include <boost/container_hash/hash.hpp> | |||||
| 15 | #include <boost/json/object.hpp> | 15 | #include <boost/json/object.hpp> | |||||
| 16 | #include <boost/json/detail/digest.hpp> | 16 | #include <boost/json/detail/digest.hpp> | |||||
| 17 | #include <boost/json/detail/except.hpp> | 17 | #include <boost/json/detail/except.hpp> | |||||
| 18 | #include <algorithm> | 18 | #include <algorithm> | |||||
| 19 | #include <cmath> | 19 | #include <cmath> | |||||
| 20 | #include <cstdlib> | 20 | #include <cstdlib> | |||||
| 21 | #include <cstring> | 21 | #include <cstring> | |||||
| 22 | #include <new> | 22 | #include <new> | |||||
| 23 | #include <stdexcept> | 23 | #include <stdexcept> | |||||
| 24 | #include <type_traits> | 24 | #include <type_traits> | |||||
| 25 | 25 | |||||||
| 26 | namespace boost { | 26 | namespace boost { | |||||
| 27 | namespace json { | 27 | namespace json { | |||||
| 28 | namespace detail { | 28 | namespace detail { | |||||
| 29 | 29 | |||||||
| 30 | template<class CharRange> | 30 | template<class CharRange> | |||||
| 31 | std::pair<key_value_pair*, std::size_t> | 31 | std::pair<key_value_pair*, std::size_t> | |||||
| HITCBC | 32 | 42848 | find_in_object( | 32 | 44588 | find_in_object( | ||
| 33 | object const& obj, | 33 | object const& obj, | |||||
| 34 | CharRange key) noexcept | 34 | CharRange key) noexcept | |||||
| 35 | { | 35 | { | |||||
| HITCBC | 36 | 42848 | BOOST_ASSERT(obj.t_->capacity > 0); | 36 | 44588 | BOOST_ASSERT(obj.t_->capacity > 0); | ||
| HITCBC | 37 | 42848 | if(obj.t_->is_small()) | 37 | 44588 | if(obj.t_->is_small()) | ||
| 38 | { | 38 | { | |||||
| HITCBC | 39 | 41000 | auto it = &(*obj.t_)[0]; | 39 | 41000 | auto it = &(*obj.t_)[0]; | ||
| 40 | auto const last = | 40 | auto const last = | |||||
| HITCBC | 41 | 41000 | &(*obj.t_)[obj.t_->size]; | 41 | 41000 | &(*obj.t_)[obj.t_->size]; | ||
| HITCBC | 42 | 75332 | for(;it != last; ++it) | 42 | 75332 | for(;it != last; ++it) | ||
| HITCBC | 43 | 35057 | if( key == it->key() ) | 43 | 35057 | if( key == it->key() ) | ||
| HITCBC | 44 | 725 | return { it, 0 }; | 44 | 725 | return { it, 0 }; | ||
| HITCBC | 45 | 40275 | return { nullptr, 0 }; | 45 | 40275 | return { nullptr, 0 }; | ||
| 46 | } | 46 | } | |||||
| 47 | std::pair< | 47 | std::pair< | |||||
| 48 | key_value_pair*, | 48 | key_value_pair*, | |||||
| HITCBC | 49 | 1848 | std::size_t> result; | 49 | 3588 | std::size_t> result; | ||
| HITCBC | 50 | 1848 | BOOST_ASSERT(obj.t_->salt != 0); | 50 | 3588 | BOOST_ASSERT(obj.t_->salt != 0); | ||
| HITCBC | 51 | 1848 | result.second = detail::digest(key.begin(), key.end(), obj.t_->salt); | 51 | 3588 | result.second = detail::digest(key.begin(), key.end(), obj.t_->salt); | ||
| HITCBC | 52 | 1848 | auto i = obj.t_->bucket( | 52 | 3588 | auto i = obj.t_->bucket( | ||
| 53 | result.second); | 53 | result.second); | |||||
| HITCBC | 54 | 2757 | while(i != object::null_index_) | 54 | 4931 | while(i != object::null_index_) | ||
| 55 | { | 55 | { | |||||
| HITCBC | 56 | 1247 | auto& v = (*obj.t_)[i]; | 56 | 2584 | auto& v = (*obj.t_)[i]; | ||
| HITCBC | 57 | 1247 | if( key == v.key() ) | 57 | 2584 | if( key == v.key() ) | ||
| 58 | { | 58 | { | |||||
| HITCBC | 59 | 338 | result.first = &v; | 59 | 1241 | result.first = &v; | ||
| HITCBC | 60 | 338 | return result; | 60 | 1241 | return result; | ||
| 61 | } | 61 | } | |||||
| HITCBC | 62 | 909 | i = access::next(v); | 62 | 1343 | i = access::next(v); | ||
| 63 | } | 63 | } | |||||
| HITCBC | 64 | 1510 | result.first = nullptr; | 64 | 2347 | result.first = nullptr; | ||
| HITCBC | 65 | 1510 | return result; | 65 | 2347 | return result; | ||
| 66 | } | 66 | } | |||||
| 67 | 67 | |||||||
| 68 | 68 | |||||||
| 69 | template | 69 | template | |||||
| 70 | std::pair<key_value_pair*, std::size_t> | 70 | std::pair<key_value_pair*, std::size_t> | |||||
| 71 | find_in_object<string_view>( | 71 | find_in_object<string_view>( | |||||
| 72 | object const& obj, | 72 | object const& obj, | |||||
| 73 | string_view key) noexcept; | 73 | string_view key) noexcept; | |||||
| 74 | 74 | |||||||
| 75 | } // namespace detail | 75 | } // namespace detail | |||||
| 76 | 76 | |||||||
| 77 | //---------------------------------------------------------- | 77 | //---------------------------------------------------------- | |||||
| 78 | 78 | |||||||
| 79 | constexpr object::table::table() = default; | 79 | constexpr object::table::table() = default; | |||||
| 80 | 80 | |||||||
| 81 | // empty objects point here | 81 | // empty objects point here | |||||
| 82 | BOOST_JSON_REQUIRE_CONST_INIT | 82 | BOOST_JSON_REQUIRE_CONST_INIT | |||||
| 83 | object::table object::empty_; | 83 | object::table object::empty_; | |||||
| 84 | 84 | |||||||
| 85 | std::size_t | 85 | std::size_t | |||||
| HITCBC | 86 | 7145 | object::table:: | 86 | 7637 | object::table:: | ||
| 87 | digest(string_view key) const noexcept | 87 | digest(string_view key) const noexcept | |||||
| 88 | { | 88 | { | |||||
| HITCBC | 89 | 7145 | BOOST_ASSERT(salt != 0); | 89 | 7637 | BOOST_ASSERT(salt != 0); | ||
| HITCBC | 90 | 7145 | return detail::digest( | 90 | 7637 | return detail::digest( | ||
| HITCBC | 91 | 14290 | key.begin(), key.end(), salt); | 91 | 15274 | key.begin(), key.end(), salt); | ||
| 92 | } | 92 | } | |||||
| 93 | 93 | |||||||
| 94 | auto | 94 | auto | |||||
| HITCBC | 95 | 10517 | object::table:: | 95 | 13617 | object::table:: | ||
| 96 | bucket(std::size_t hash) noexcept -> | 96 | bucket(std::size_t hash) noexcept -> | |||||
| 97 | index_t& | 97 | index_t& | |||||
| 98 | { | 98 | { | |||||
| 99 | return reinterpret_cast< | 99 | return reinterpret_cast< | |||||
| HITCBC | 100 | 10517 | index_t*>(&(*this)[capacity])[ | 100 | 13617 | index_t*>(&(*this)[capacity])[ | ||
| HITCBC | 101 | 10517 | hash % capacity]; | 101 | 13617 | hash % capacity]; | ||
| 102 | } | 102 | } | |||||
| 103 | 103 | |||||||
| 104 | auto | 104 | auto | |||||
| HITCBC | 105 | 7082 | object::table:: | 105 | 7608 | object::table:: | ||
| 106 | bucket(string_view key) noexcept -> | 106 | bucket(string_view key) noexcept -> | |||||
| 107 | index_t& | 107 | index_t& | |||||
| 108 | { | 108 | { | |||||
| HITCBC | 109 | 7082 | return bucket(digest(key)); | 109 | 7608 | return bucket(digest(key)); | ||
| 110 | } | 110 | } | |||||
| 111 | 111 | |||||||
| 112 | void | 112 | void | |||||
| HITCBC | 113 | 392 | object::table:: | 113 | 431 | object::table:: | ||
| 114 | clear() noexcept | 114 | clear() noexcept | |||||
| 115 | { | 115 | { | |||||
| HITCBC | 116 | 392 | BOOST_ASSERT(! is_small()); | 116 | 431 | BOOST_ASSERT(! is_small()); | ||
| 117 | // initialize buckets | 117 | // initialize buckets | |||||
| HITCBC | 118 | 784 | std::memset( | 118 | 862 | std::memset( | ||
| 119 | reinterpret_cast<index_t*>( | 119 | reinterpret_cast<index_t*>( | |||||
| HITCBC | 120 | 392 | &(*this)[capacity]), | 120 | 431 | &(*this)[capacity]), | ||
| 121 | 0xff, // null_index_ | 121 | 0xff, // null_index_ | |||||
| HITCBC | 122 | 392 | capacity * sizeof(index_t)); | 122 | 431 | capacity * sizeof(index_t)); | ||
| HITCBC | 123 | 392 | } | 123 | 431 | } | ||
| 124 | 124 | |||||||
| 125 | object::table* | 125 | object::table* | |||||
| HITCBC | 126 | 35480 | object::table:: | 126 | 35519 | object::table:: | ||
| 127 | allocate( | 127 | allocate( | |||||
| 128 | std::size_t capacity, | 128 | std::size_t capacity, | |||||
| 129 | std::uintptr_t salt, | 129 | std::uintptr_t salt, | |||||
| 130 | storage_ptr const& sp) | 130 | storage_ptr const& sp) | |||||
| 131 | { | 131 | { | |||||
| 132 | BOOST_CORE_STATIC_ASSERT( | 132 | BOOST_CORE_STATIC_ASSERT( | |||||
| 133 | alignof(key_value_pair) >= alignof(index_t)); | 133 | alignof(key_value_pair) >= alignof(index_t)); | |||||
| HITCBC | 134 | 35480 | BOOST_ASSERT(capacity > 0); | 134 | 35519 | BOOST_ASSERT(capacity > 0); | ||
| HITCBC | 135 | 35480 | BOOST_ASSERT(capacity <= max_size()); | 135 | 35519 | BOOST_ASSERT(capacity <= max_size()); | ||
| 136 | table* p; | 136 | table* p; | |||||
| HITCBC | 137 | 35480 | if(capacity <= detail::small_object_size_) | 137 | 35519 | if(capacity <= detail::small_object_size_) | ||
| 138 | { | 138 | { | |||||
| 139 | p = reinterpret_cast< | 139 | p = reinterpret_cast< | |||||
| HITCBC | 140 | 35077 | table*>(sp->allocate( | 140 | 35077 | table*>(sp->allocate( | ||
| HITCBC | 141 | 35077 | sizeof(table) + capacity * | 141 | 35077 | sizeof(table) + capacity * | ||
| 142 | sizeof(key_value_pair))); | 142 | sizeof(key_value_pair))); | |||||
| HITCBC | 143 | 34986 | p->capacity = static_cast< | 143 | 34986 | p->capacity = static_cast< | ||
| 144 | std::uint32_t>(capacity); | 144 | std::uint32_t>(capacity); | |||||
| 145 | } | 145 | } | |||||
| 146 | else | 146 | else | |||||
| 147 | { | 147 | { | |||||
| 148 | p = reinterpret_cast< | 148 | p = reinterpret_cast< | |||||
| HITCBC | 149 | 403 | table*>(sp->allocate( | 149 | 442 | table*>(sp->allocate( | ||
| HITCBC | 150 | 403 | sizeof(table) + capacity * ( | 150 | 442 | sizeof(table) + capacity * ( | ||
| 151 | sizeof(key_value_pair) + | 151 | sizeof(key_value_pair) + | |||||
| 152 | sizeof(index_t)))); | 152 | sizeof(index_t)))); | |||||
| HITCBC | 153 | 388 | p->capacity = static_cast< | 153 | 427 | p->capacity = static_cast< | ||
| 154 | std::uint32_t>(capacity); | 154 | std::uint32_t>(capacity); | |||||
| HITCBC | 155 | 388 | p->clear(); | 155 | 427 | p->clear(); | ||
| 156 | } | 156 | } | |||||
| HITCBC | 157 | 35374 | if(salt) | 157 | 35413 | if(salt) | ||
| 158 | { | 158 | { | |||||
| HITCBC | 159 | 489 | p->salt = salt; | 159 | 489 | p->salt = salt; | ||
| 160 | } | 160 | } | |||||
| 161 | else | 161 | else | |||||
| 162 | { | 162 | { | |||||
| 163 | // VFALCO This would be better if it | 163 | // VFALCO This would be better if it | |||||
| 164 | // was random, but maybe this | 164 | // was random, but maybe this | |||||
| 165 | // is good enough. | 165 | // is good enough. | |||||
| HITCBC | 166 | 34885 | p->salt = reinterpret_cast< | 166 | 34924 | p->salt = reinterpret_cast< | ||
| 167 | std::uintptr_t>(p); | 167 | std::uintptr_t>(p); | |||||
| 168 | } | 168 | } | |||||
| HITCBC | 169 | 35374 | return p; | 169 | 35413 | return p; | ||
| 170 | } | 170 | } | |||||
| 171 | 171 | |||||||
| 172 | //---------------------------------------------------------- | 172 | //---------------------------------------------------------- | |||||
| 173 | 173 | |||||||
| 174 | void | 174 | void | |||||
| HITCBC | 175 | 374 | object:: | 175 | 374 | object:: | ||
| 176 | revert_construct:: | 176 | revert_construct:: | |||||
| 177 | destroy() noexcept | 177 | destroy() noexcept | |||||
| 178 | { | 178 | { | |||||
| HITCBC | 179 | 374 | obj_->destroy(); | 179 | 374 | obj_->destroy(); | ||
| HITCBC | 180 | 374 | } | 180 | 374 | } | ||
| 181 | 181 | |||||||
| 182 | //---------------------------------------------------------- | 182 | //---------------------------------------------------------- | |||||
| 183 | 183 | |||||||
| 184 | void | 184 | void | |||||
| HITCBC | 185 | 230 | object:: | 185 | 242 | object:: | ||
| 186 | revert_insert:: | 186 | revert_insert:: | |||||
| 187 | destroy() noexcept | 187 | destroy() noexcept | |||||
| 188 | { | 188 | { | |||||
| 189 | + | // when no reallocation happened, insert_impl linked each rolled-back | ||||||
| 190 | + | // element into a bucket of the live table; unlink them while their keys | ||||||
| 191 | + | // are still valid, otherwise a bucket head is left pointing at a slot | ||||||
| 192 | + | // that is about to be destroyed | ||||||
| HITGNC | 193 | + | 242 | if( !t_ && !obj_->t_->is_small() ) | ||||
| 194 | + | { | ||||||
| HITGNC | 195 | + | 69 | key_value_pair* const first = &(*obj_->t_)[size_]; | ||||
| HITGNC | 196 | + | 69 | key_value_pair* last = obj_->end(); | ||||
| HITGNC | 197 | + | 595 | while( last != first ) | ||||
| 198 | + | { | ||||||
| HITGNC | 199 | + | 526 | --last; | ||||
| HITGNC | 200 | + | 526 | obj_->remove( obj_->t_->bucket( last->key() ), *last ); | ||||
| 201 | + | } | ||||||
| 202 | + | } | ||||||
| HITCBC | 189 | 230 | obj_->destroy( | 203 | 242 | obj_->destroy( | ||
| HITCBC | 190 | 230 | &(*obj_->t_)[size_], | 204 | 242 | &(*obj_->t_)[size_], | ||
| HITCBC | 191 | 230 | obj_->end()); | 205 | 242 | obj_->end()); | ||
| HITCBC | 192 | 230 | } | 206 | 242 | } | ||
| 193 | 207 | |||||||
| 194 | //---------------------------------------------------------- | 208 | //---------------------------------------------------------- | |||||
| 195 | // | 209 | // | |||||
| 196 | // Construction | 210 | // Construction | |||||
| 197 | // | 211 | // | |||||
| 198 | //---------------------------------------------------------- | 212 | //---------------------------------------------------------- | |||||
| 199 | 213 | |||||||
| HITCBC | 200 | 34880 | object:: | 214 | 34880 | object:: | ||
| HITCBC | 201 | 34880 | object(detail::unchecked_object&& uo) | 215 | 34880 | object(detail::unchecked_object&& uo) | ||
| HITCBC | 202 | 34880 | : sp_(uo.storage()) | 216 | 34880 | : sp_(uo.storage()) | ||
| 203 | { | 217 | { | |||||
| HITCBC | 204 | 34880 | if(uo.size() == 0) | 218 | 34880 | if(uo.size() == 0) | ||
| 205 | { | 219 | { | |||||
| HITCBC | 206 | 1049 | t_ = &empty_; | 220 | 1049 | t_ = &empty_; | ||
| HITCBC | 207 | 1049 | return; | 221 | 1049 | return; | ||
| 208 | } | 222 | } | |||||
| 209 | // should already be checked | 223 | // should already be checked | |||||
| HITCBC | 210 | 33831 | BOOST_ASSERT( | 224 | 33831 | BOOST_ASSERT( | ||
| 211 | uo.size() <= max_size()); | 225 | uo.size() <= max_size()); | |||||
| HITCBC | 212 | 33831 | t_ = table::allocate( | 226 | 33831 | t_ = table::allocate( | ||
| HITCBC | 213 | 33831 | uo.size(), 0, sp_); | 227 | 33831 | uo.size(), 0, sp_); | ||
| 214 | 228 | |||||||
| 215 | // insert all elements, keeping | 229 | // insert all elements, keeping | |||||
| 216 | // the last of any duplicate keys. | 230 | // the last of any duplicate keys. | |||||
| HITCBC | 217 | 33792 | auto dest = begin(); | 231 | 33792 | auto dest = begin(); | ||
| HITCBC | 218 | 33792 | auto src = uo.release(); | 232 | 33792 | auto src = uo.release(); | ||
| HITCBC | 219 | 33792 | auto const end = src + 2 * uo.size(); | 233 | 33792 | auto const end = src + 2 * uo.size(); | ||
| HITCBC | 220 | 33792 | if(t_->is_small()) | 234 | 33792 | if(t_->is_small()) | ||
| 221 | { | 235 | { | |||||
| HITCBC | 222 | 33759 | t_->size = 0; | 236 | 33759 | t_->size = 0; | ||
| HITCBC | 223 | 70269 | while(src != end) | 237 | 70269 | while(src != end) | ||
| 224 | { | 238 | { | |||||
| HITCBC | 225 | 36510 | access::construct_key_value_pair( | 239 | 36510 | access::construct_key_value_pair( | ||
| HITCBC | 226 | 36510 | dest, pilfer(src[0]), pilfer(src[1])); | 240 | 36510 | dest, pilfer(src[0]), pilfer(src[1])); | ||
| HITCBC | 227 | 36510 | src += 2; | 241 | 36510 | src += 2; | ||
| HITCBC | 228 | 36510 | auto result = detail::find_in_object(*this, dest->key()); | 242 | 36510 | auto result = detail::find_in_object(*this, dest->key()); | ||
| HITCBC | 229 | 36510 | if(! result.first) | 243 | 36510 | if(! result.first) | ||
| 230 | { | 244 | { | |||||
| HITCBC | 231 | 36500 | ++dest; | 245 | 36500 | ++dest; | ||
| HITCBC | 232 | 36500 | ++t_->size; | 246 | 36500 | ++t_->size; | ||
| HITCBC | 233 | 36500 | continue; | 247 | 36500 | continue; | ||
| 234 | } | 248 | } | |||||
| 235 | // handle duplicate | 249 | // handle duplicate | |||||
| HITCBC | 236 | 10 | auto& v = *result.first; | 250 | 10 | auto& v = *result.first; | ||
| 237 | // don't bother to check if | 251 | // don't bother to check if | |||||
| 238 | // storage deallocate is trivial | 252 | // storage deallocate is trivial | |||||
| HITCBC | 239 | 10 | v.~key_value_pair(); | 253 | 10 | v.~key_value_pair(); | ||
| 240 | // trivial relocate | 254 | // trivial relocate | |||||
| HITCBC | 241 | 10 | std::memcpy( | 255 | 10 | std::memcpy( | ||
| 242 | static_cast<void*>(&v), | 256 | static_cast<void*>(&v), | |||||
| 243 | dest, sizeof(v)); | 257 | dest, sizeof(v)); | |||||
| 244 | } | 258 | } | |||||
| HITCBC | 245 | 33759 | return; | 259 | 33759 | return; | ||
| 246 | } | 260 | } | |||||
| HITCBC | 247 | 1674 | while(src != end) | 261 | 1674 | while(src != end) | ||
| 248 | { | 262 | { | |||||
| HITCBC | 249 | 1641 | access::construct_key_value_pair( | 263 | 1641 | access::construct_key_value_pair( | ||
| HITCBC | 250 | 1641 | dest, pilfer(src[0]), pilfer(src[1])); | 264 | 1641 | dest, pilfer(src[0]), pilfer(src[1])); | ||
| HITCBC | 251 | 1641 | src += 2; | 265 | 1641 | src += 2; | ||
| HITCBC | 252 | 1641 | auto& head = t_->bucket(dest->key()); | 266 | 1641 | auto& head = t_->bucket(dest->key()); | ||
| HITCBC | 253 | 1641 | auto i = head; | 267 | 1641 | auto i = head; | ||
| 254 | for(;;) | 268 | for(;;) | |||||
| 255 | { | 269 | { | |||||
| HITCBC | 256 | 2437 | if(i == null_index_) | 270 | 2511 | if(i == null_index_) | ||
| 257 | { | 271 | { | |||||
| 258 | // end of bucket | 272 | // end of bucket | |||||
| HITCBC | 259 | 1640 | access::next( | 273 | 1640 | access::next( | ||
| HITCBC | 260 | 1640 | *dest) = head; | 274 | 1640 | *dest) = head; | ||
| HITCBC | 261 | 1640 | head = static_cast<index_t>( | 275 | 1640 | head = static_cast<index_t>( | ||
| HITCBC | 262 | 1640 | dest - begin()); | 276 | 1640 | dest - begin()); | ||
| HITCBC | 263 | 1640 | ++dest; | 277 | 1640 | ++dest; | ||
| HITCBC | 264 | 1640 | break; | 278 | 1640 | break; | ||
| 265 | } | 279 | } | |||||
| HITCBC | 266 | 797 | auto& v = (*t_)[i]; | 280 | 871 | auto& v = (*t_)[i]; | ||
| HITCBC | 267 | 797 | if(v.key() != dest->key()) | 281 | 871 | if(v.key() != dest->key()) | ||
| 268 | { | 282 | { | |||||
| HITCBC | 269 | 796 | i = access::next(v); | 283 | 870 | i = access::next(v); | ||
| HITCBC | 270 | 796 | continue; | 284 | 870 | continue; | ||
| 271 | } | 285 | } | |||||
| 272 | 286 | |||||||
| 273 | // handle duplicate | 287 | // handle duplicate | |||||
| HITCBC | 274 | 1 | access::next(*dest) = | 288 | 1 | access::next(*dest) = | ||
| HITCBC | 275 | 1 | access::next(v); | 289 | 1 | access::next(v); | ||
| 276 | // don't bother to check if | 290 | // don't bother to check if | |||||
| 277 | // storage deallocate is trivial | 291 | // storage deallocate is trivial | |||||
| HITCBC | 278 | 1 | v.~key_value_pair(); | 292 | 1 | v.~key_value_pair(); | ||
| 279 | // trivial relocate | 293 | // trivial relocate | |||||
| HITCBC | 280 | 1 | std::memcpy( | 294 | 1 | std::memcpy( | ||
| 281 | static_cast<void*>(&v), | 295 | static_cast<void*>(&v), | |||||
| 282 | dest, sizeof(v)); | 296 | dest, sizeof(v)); | |||||
| HITCBC | 283 | 1 | break; | 297 | 1 | break; | ||
| HITCBC | 284 | 796 | } | 298 | 870 | } | ||
| 285 | } | 299 | } | |||||
| HITCBC | 286 | 33 | t_->size = static_cast< | 300 | 33 | t_->size = static_cast< | ||
| HITCBC | 287 | 33 | index_t>(dest - begin()); | 301 | 33 | index_t>(dest - begin()); | ||
| HITCBC | 288 | 39 | } | 302 | 39 | } | ||
| 289 | 303 | |||||||
| HITCBC | 290 | 35948 | object:: | 304 | 35987 | object:: | ||
| HITCBC | 291 | 34397 | ~object() noexcept | 305 | 34436 | ~object() noexcept | ||
| 292 | { | 306 | { | |||||
| HITCBC | 293 | 35948 | if(sp_.is_not_shared_and_deallocate_is_trivial()) | 307 | 35987 | if(sp_.is_not_shared_and_deallocate_is_trivial()) | ||
| HITCBC | 294 | 5 | return; | 308 | 5 | return; | ||
| HITCBC | 295 | 35943 | if(t_->capacity == 0) | 309 | 35982 | if(t_->capacity == 0) | ||
| HITCBC | 296 | 1546 | return; | 310 | 1546 | return; | ||
| HITCBC | 297 | 34397 | destroy(); | 311 | 34436 | destroy(); | ||
| HITCBC | 298 | 35948 | } | 312 | 35987 | } | ||
| 299 | 313 | |||||||
| HITCBC | 300 | 7 | object:: | 314 | 7 | object:: | ||
| 301 | object( | 315 | object( | |||||
| 302 | std::size_t min_capacity, | 316 | std::size_t min_capacity, | |||||
| HITCBC | 303 | 7 | storage_ptr sp) | 317 | 7 | storage_ptr sp) | ||
| HITCBC | 304 | 7 | : sp_(std::move(sp)) | 318 | 7 | : sp_(std::move(sp)) | ||
| HITCBC | 305 | 7 | , t_(&empty_) | 319 | 7 | , t_(&empty_) | ||
| 306 | { | 320 | { | |||||
| HITCBC | 307 | 7 | reserve(min_capacity); | 321 | 7 | reserve(min_capacity); | ||
| HITCBC | 308 | 7 | } | 322 | 7 | } | ||
| 309 | 323 | |||||||
| HITCBC | 310 | 71 | object:: | 324 | 71 | object:: | ||
| HITCBC | 311 | 71 | object(object&& other) noexcept | 325 | 71 | object(object&& other) noexcept | ||
| HITCBC | 312 | 71 | : sp_(other.sp_) | 326 | 71 | : sp_(other.sp_) | ||
| HITCBC | 313 | 142 | , t_(detail::exchange( | 327 | 142 | , t_(detail::exchange( | ||
| HITCBC | 314 | 71 | other.t_, &empty_)) | 328 | 71 | other.t_, &empty_)) | ||
| 315 | { | 329 | { | |||||
| HITCBC | 316 | 71 | } | 330 | 71 | } | ||
| 317 | 331 | |||||||
| HITCBC | 318 | 184 | object:: | 332 | 184 | object:: | ||
| 319 | object( | 333 | object( | |||||
| 320 | object&& other, | 334 | object&& other, | |||||
| HITCBC | 321 | 184 | storage_ptr sp) | 335 | 184 | storage_ptr sp) | ||
| HITCBC | 322 | 184 | : sp_(std::move(sp)) | 336 | 184 | : sp_(std::move(sp)) | ||
| 323 | { | 337 | { | |||||
| HITCBC | 324 | 184 | if(*sp_ == *other.sp_) | 338 | 184 | if(*sp_ == *other.sp_) | ||
| 325 | { | 339 | { | |||||
| HITCBC | 326 | 192 | t_ = detail::exchange( | 340 | 192 | t_ = detail::exchange( | ||
| HITCBC | 327 | 96 | other.t_, &empty_); | 341 | 96 | other.t_, &empty_); | ||
| HITCBC | 328 | 96 | return; | 342 | 96 | return; | ||
| 329 | } | 343 | } | |||||
| 330 | 344 | |||||||
| HITCBC | 331 | 88 | t_ = &empty_; | 345 | 88 | t_ = &empty_; | ||
| HITCBC | 332 | 151 | object(other, sp_).swap(*this); | 346 | 151 | object(other, sp_).swap(*this); | ||
| HITCBC | 333 | 63 | } | 347 | 63 | } | ||
| 334 | 348 | |||||||
| HITCBC | 335 | 197 | object:: | 349 | 197 | object:: | ||
| 336 | object( | 350 | object( | |||||
| 337 | object const& other, | 351 | object const& other, | |||||
| HITCBC | 338 | 197 | storage_ptr sp) | 352 | 197 | storage_ptr sp) | ||
| HITCBC | 339 | 197 | : sp_(std::move(sp)) | 353 | 197 | : sp_(std::move(sp)) | ||
| HITCBC | 340 | 197 | , t_(&empty_) | 354 | 197 | , t_(&empty_) | ||
| 341 | { | 355 | { | |||||
| HITCBC | 342 | 197 | reserve(other.size()); | 356 | 197 | reserve(other.size()); | ||
| HITCBC | 343 | 185 | revert_construct r(*this); | 357 | 185 | revert_construct r(*this); | ||
| HITCBC | 344 | 185 | if(t_->is_small()) | 358 | 185 | if(t_->is_small()) | ||
| 345 | { | 359 | { | |||||
| HITCBC | 346 | 712 | for(auto const& v : other) | 360 | 712 | for(auto const& v : other) | ||
| 347 | { | 361 | { | |||||
| HITCBC | 348 | 724 | ::new(end()) | 362 | 724 | ::new(end()) | ||
| HITCBC | 349 | 800 | key_value_pair(v, sp_); | 363 | 800 | key_value_pair(v, sp_); | ||
| HITCBC | 350 | 572 | ++t_->size; | 364 | 572 | ++t_->size; | ||
| 351 | } | 365 | } | |||||
| HITCBC | 352 | 64 | r.commit(); | 366 | 64 | r.commit(); | ||
| HITCBC | 353 | 64 | return; | 367 | 64 | return; | ||
| 354 | } | 368 | } | |||||
| HITCBC | 355 | 2485 | for(auto const& v : other) | 369 | 2485 | for(auto const& v : other) | ||
| 356 | { | 370 | { | |||||
| 357 | // skip duplicate checking | 371 | // skip duplicate checking | |||||
| 358 | auto& head = | 372 | auto& head = | |||||
| HITCBC | 359 | 2480 | t_->bucket(v.key()); | 373 | 2480 | t_->bucket(v.key()); | ||
| HITCBC | 360 | 2480 | auto pv = ::new(end()) | 374 | 2480 | auto pv = ::new(end()) | ||
| HITCBC | 361 | 2520 | key_value_pair(v, sp_); | 375 | 2520 | key_value_pair(v, sp_); | ||
| HITCBC | 362 | 2440 | access::next(*pv) = head; | 376 | 2440 | access::next(*pv) = head; | ||
| HITCBC | 363 | 2440 | head = t_->size; | 377 | 2440 | head = t_->size; | ||
| HITCBC | 364 | 2440 | ++t_->size; | 378 | 2440 | ++t_->size; | ||
| 365 | } | 379 | } | |||||
| HITCBC | 366 | 5 | r.commit(); | 380 | 5 | r.commit(); | ||
| HITCBC | 367 | 313 | } | 381 | 313 | } | ||
| 368 | 382 | |||||||
| HITCBC | 369 | 381 | object:: | 383 | 381 | object:: | ||
| 370 | object( | 384 | object( | |||||
| 371 | std::initializer_list<std::pair< | 385 | std::initializer_list<std::pair< | |||||
| 372 | string_view, value_ref>> init, | 386 | string_view, value_ref>> init, | |||||
| 373 | std::size_t min_capacity, | 387 | std::size_t min_capacity, | |||||
| HITCBC | 374 | 381 | storage_ptr sp) | 388 | 381 | storage_ptr sp) | ||
| HITCBC | 375 | 381 | : sp_(std::move(sp)) | 389 | 381 | : sp_(std::move(sp)) | ||
| HITCBC | 376 | 381 | , t_(&empty_) | 390 | 381 | , t_(&empty_) | ||
| 377 | { | 391 | { | |||||
| HITCBC | 378 | 381 | if( min_capacity < init.size()) | 392 | 381 | if( min_capacity < init.size()) | ||
| HITCBC | 379 | 335 | min_capacity = init.size(); | 393 | 335 | min_capacity = init.size(); | ||
| HITCBC | 380 | 381 | reserve(min_capacity); | 394 | 381 | reserve(min_capacity); | ||
| HITCBC | 381 | 365 | revert_construct r(*this); | 395 | 365 | revert_construct r(*this); | ||
| HITCBC | 382 | 365 | insert(init); | 396 | 365 | insert(init); | ||
| HITCBC | 383 | 252 | r.commit(); | 397 | 252 | r.commit(); | ||
| HITCBC | 384 | 494 | } | 398 | 494 | } | ||
| 385 | 399 | |||||||
| 386 | //---------------------------------------------------------- | 400 | //---------------------------------------------------------- | |||||
| 387 | // | 401 | // | |||||
| 388 | // Assignment | 402 | // Assignment | |||||
| 389 | // | 403 | // | |||||
| 390 | //---------------------------------------------------------- | 404 | //---------------------------------------------------------- | |||||
| 391 | 405 | |||||||
| 392 | object& | 406 | object& | |||||
| HITCBC | 393 | 22 | object:: | 407 | 22 | object:: | ||
| 394 | operator=(object const& other) | 408 | operator=(object const& other) | |||||
| 395 | { | 409 | { | |||||
| HITCBC | 396 | 39 | object tmp(other, sp_); | 410 | 39 | object tmp(other, sp_); | ||
| HITCBC | 397 | 5 | this->~object(); | 411 | 5 | this->~object(); | ||
| HITCBC | 398 | 5 | ::new(this) object(pilfer(tmp)); | 412 | 5 | ::new(this) object(pilfer(tmp)); | ||
| HITCBC | 399 | 5 | return *this; | 413 | 5 | return *this; | ||
| HITCBC | 400 | 5 | } | 414 | 5 | } | ||
| 401 | 415 | |||||||
| 402 | object& | 416 | object& | |||||
| HITCBC | 403 | 7 | object:: | 417 | 7 | object:: | ||
| 404 | operator=(object&& other) | 418 | operator=(object&& other) | |||||
| 405 | { | 419 | { | |||||
| HITCBC | 406 | 11 | object tmp(std::move(other), sp_); | 420 | 11 | object tmp(std::move(other), sp_); | ||
| HITCBC | 407 | 3 | this->~object(); | 421 | 3 | this->~object(); | ||
| HITCBC | 408 | 3 | ::new(this) object(pilfer(tmp)); | 422 | 3 | ::new(this) object(pilfer(tmp)); | ||
| HITCBC | 409 | 3 | return *this; | 423 | 3 | return *this; | ||
| HITCBC | 410 | 3 | } | 424 | 3 | } | ||
| 411 | 425 | |||||||
| 412 | object& | 426 | object& | |||||
| HITCBC | 413 | 7 | object:: | 427 | 7 | object:: | ||
| 414 | operator=( | 428 | operator=( | |||||
| 415 | std::initializer_list<std::pair< | 429 | std::initializer_list<std::pair< | |||||
| 416 | string_view, value_ref>> init) | 430 | string_view, value_ref>> init) | |||||
| 417 | { | 431 | { | |||||
| HITCBC | 418 | 11 | object tmp(init, sp_); | 432 | 11 | object tmp(init, sp_); | ||
| HITCBC | 419 | 3 | this->~object(); | 433 | 3 | this->~object(); | ||
| HITCBC | 420 | 3 | ::new(this) object(pilfer(tmp)); | 434 | 3 | ::new(this) object(pilfer(tmp)); | ||
| HITCBC | 421 | 3 | return *this; | 435 | 3 | return *this; | ||
| HITCBC | 422 | 3 | } | 436 | 3 | } | ||
| 423 | 437 | |||||||
| 424 | //---------------------------------------------------------- | 438 | //---------------------------------------------------------- | |||||
| 425 | // | 439 | // | |||||
| 426 | // Lookup | 440 | // Lookup | |||||
| 427 | // | 441 | // | |||||
| 428 | //---------------------------------------------------------- | 442 | //---------------------------------------------------------- | |||||
| 429 | 443 | |||||||
| 430 | system::result<value&> | 444 | system::result<value&> | |||||
| HITCBC | 431 | 4 | object:: | 445 | 4 | object:: | ||
| 432 | try_at(string_view key) noexcept | 446 | try_at(string_view key) noexcept | |||||
| 433 | { | 447 | { | |||||
| HITCBC | 434 | 4 | auto it = find(key); | 448 | 4 | auto it = find(key); | ||
| HITCBC | 435 | 4 | if( it != end() ) | 449 | 4 | if( it != end() ) | ||
| HITCBC | 436 | 2 | return it->value(); | 450 | 2 | return it->value(); | ||
| 437 | 451 | |||||||
| HITCBC | 438 | 2 | system::error_code ec; | 452 | 2 | system::error_code ec; | ||
| HITCBC | 439 | 2 | BOOST_JSON_FAIL(ec, error::out_of_range); | 453 | 2 | BOOST_JSON_FAIL(ec, error::out_of_range); | ||
| HITCBC | 440 | 2 | return ec; | 454 | 2 | return ec; | ||
| 441 | } | 455 | } | |||||
| 442 | 456 | |||||||
| 443 | system::result<value const&> | 457 | system::result<value const&> | |||||
| HITCBC | 444 | 108 | object:: | 458 | 108 | object:: | ||
| 445 | try_at(string_view key) const noexcept | 459 | try_at(string_view key) const noexcept | |||||
| 446 | { | 460 | { | |||||
| HITCBC | 447 | 108 | auto it = find(key); | 461 | 108 | auto it = find(key); | ||
| HITCBC | 448 | 108 | if( it != end() ) | 462 | 108 | if( it != end() ) | ||
| HITCBC | 449 | 102 | return it->value(); | 463 | 102 | return it->value(); | ||
| 450 | 464 | |||||||
| HITCBC | 451 | 6 | system::error_code ec; | 465 | 6 | system::error_code ec; | ||
| HITCBC | 452 | 6 | BOOST_JSON_FAIL(ec, error::out_of_range); | 466 | 6 | BOOST_JSON_FAIL(ec, error::out_of_range); | ||
| HITCBC | 453 | 6 | return ec; | 467 | 6 | return ec; | ||
| 454 | } | 468 | } | |||||
| 455 | 469 | |||||||
| 456 | value const& | 470 | value const& | |||||
| HITCBC | 457 | 104 | object:: | 471 | 104 | object:: | ||
| 458 | at(string_view key, source_location const& loc) const& | 472 | at(string_view key, source_location const& loc) const& | |||||
| 459 | { | 473 | { | |||||
| HITCBC | 460 | 104 | return try_at(key).value(loc); | 474 | 104 | return try_at(key).value(loc); | ||
| 461 | } | 475 | } | |||||
| 462 | 476 | |||||||
| 463 | //---------------------------------------------------------- | 477 | //---------------------------------------------------------- | |||||
| 464 | // | 478 | // | |||||
| 465 | // Modifiers | 479 | // Modifiers | |||||
| 466 | // | 480 | // | |||||
| 467 | //---------------------------------------------------------- | 481 | //---------------------------------------------------------- | |||||
| 468 | 482 | |||||||
| 469 | void | 483 | void | |||||
| HITCBC | 470 | 7 | object:: | 484 | 7 | object:: | ||
| 471 | clear() noexcept | 485 | clear() noexcept | |||||
| 472 | { | 486 | { | |||||
| HITCBC | 473 | 7 | if(empty()) | 487 | 7 | if(empty()) | ||
| HITCBC | 474 | 2 | return; | 488 | 2 | return; | ||
| HITCBC | 475 | 5 | if(! sp_.is_not_shared_and_deallocate_is_trivial()) | 489 | 5 | if(! sp_.is_not_shared_and_deallocate_is_trivial()) | ||
| HITCBC | 476 | 5 | destroy(begin(), end()); | 490 | 5 | destroy(begin(), end()); | ||
| HITCBC | 477 | 5 | if(! t_->is_small()) | 491 | 5 | if(! t_->is_small()) | ||
| HITCBC | 478 | 4 | t_->clear(); | 492 | 4 | t_->clear(); | ||
| HITCBC | 479 | 5 | t_->size = 0; | 493 | 5 | t_->size = 0; | ||
| 480 | } | 494 | } | |||||
| 481 | 495 | |||||||
| 482 | void | 496 | void | |||||
| HITCBC | 483 | 425 | object:: | 497 | 425 | object:: | ||
| 484 | insert( | 498 | insert( | |||||
| 485 | std::initializer_list<std::pair< | 499 | std::initializer_list<std::pair< | |||||
| 486 | string_view, value_ref>> init) | 500 | string_view, value_ref>> init) | |||||
| 487 | { | 501 | { | |||||
| HITCBC | 488 | 425 | auto const n0 = size(); | 502 | 425 | auto const n0 = size(); | ||
| HITCBC | 489 | 425 | if(init.size() > max_size() - n0) | 503 | 425 | if(init.size() > max_size() - n0) | ||
| 490 | { | 504 | { | |||||
| 491 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 505 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 492 | 1 | detail::throw_system_error( error::object_too_large, &loc ); | 506 | 1 | detail::throw_system_error( error::object_too_large, &loc ); | ||
| 493 | } | 507 | } | |||||
| HITCBC | 494 | 424 | revert_insert r( *this, n0 + init.size() ); | 508 | 424 | revert_insert r( *this, n0 + init.size() ); | ||
| HITCBC | 495 | 417 | if(t_->is_small()) | 509 | 417 | if(t_->is_small()) | ||
| 496 | { | 510 | { | |||||
| HITCBC | 497 | 2032 | for(auto& iv : init) | 511 | 2032 | for(auto& iv : init) | ||
| 498 | { | 512 | { | |||||
| 499 | auto result = | 513 | auto result = | |||||
| HITCBC | 500 | 1832 | detail::find_in_object(*this, iv.first); | 514 | 1832 | detail::find_in_object(*this, iv.first); | ||
| HITCBC | 501 | 1832 | if(result.first) | 515 | 1832 | if(result.first) | ||
| 502 | { | 516 | { | |||||
| 503 | // ignore duplicate | 517 | // ignore duplicate | |||||
| HITCBC | 504 | 4 | continue; | 518 | 4 | continue; | ||
| 505 | } | 519 | } | |||||
| HITCBC | 506 | 1905 | ::new(end()) key_value_pair( | 520 | 1905 | ::new(end()) key_value_pair( | ||
| 507 | iv.first, | 521 | iv.first, | |||||
| HITCBC | 508 | 2056 | iv.second.make_value(sp_)); | 522 | 2056 | iv.second.make_value(sp_)); | ||
| HITCBC | 509 | 1751 | ++t_->size; | 523 | 1751 | ++t_->size; | ||
| 510 | } | 524 | } | |||||
| HITCBC | 511 | 200 | r.commit(); | 525 | 200 | r.commit(); | ||
| HITCBC | 512 | 200 | return; | 526 | 200 | return; | ||
| 513 | } | 527 | } | |||||
| HITCBC | 514 | 1999 | for(auto& iv : init) | 528 | 1999 | for(auto& iv : init) | ||
| 515 | { | 529 | { | |||||
| HITCBC | 516 | 1939 | auto& head = t_->bucket(iv.first); | 530 | 1939 | auto& head = t_->bucket(iv.first); | ||
| HITCBC | 517 | 1939 | auto i = head; | 531 | 1939 | auto i = head; | ||
| 518 | for(;;) | 532 | for(;;) | |||||
| 519 | { | 533 | { | |||||
| HITCBC | 520 | 2713 | if(i == null_index_) | 534 | 2673 | if(i == null_index_) | ||
| 521 | { | 535 | { | |||||
| 522 | // VFALCO value_ref should construct | 536 | // VFALCO value_ref should construct | |||||
| 523 | // a key_value_pair using placement | 537 | // a key_value_pair using placement | |||||
| HITCBC | 524 | 1937 | auto& v = *::new(end()) | 538 | 1937 | auto& v = *::new(end()) | ||
| 525 | key_value_pair( | 539 | key_value_pair( | |||||
| 526 | iv.first, | 540 | iv.first, | |||||
| HITCBC | 527 | 2097 | iv.second.make_value(sp_)); | 541 | 2097 | iv.second.make_value(sp_)); | ||
| HITCBC | 528 | 1857 | access::next(v) = head; | 542 | 1857 | access::next(v) = head; | ||
| HITCBC | 529 | 1857 | head = static_cast<index_t>( | 543 | 1857 | head = static_cast<index_t>( | ||
| HITCBC | 530 | 1857 | t_->size); | 544 | 1857 | t_->size); | ||
| HITCBC | 531 | 1857 | ++t_->size; | 545 | 1857 | ++t_->size; | ||
| HITCBC | 532 | 1857 | break; | 546 | 1857 | break; | ||
| 533 | } | 547 | } | |||||
| HITCBC | 534 | 776 | auto& v = (*t_)[i]; | 548 | 736 | auto& v = (*t_)[i]; | ||
| HITCBC | 535 | 776 | if(v.key() == iv.first) | 549 | 736 | if(v.key() == iv.first) | ||
| 536 | { | 550 | { | |||||
| 537 | // ignore duplicate | 551 | // ignore duplicate | |||||
| HITCBC | 538 | 2 | break; | 552 | 2 | break; | ||
| 539 | } | 553 | } | |||||
| HITCBC | 540 | 774 | i = access::next(v); | 554 | 734 | i = access::next(v); | ||
| HITCBC | 541 | 774 | } | 555 | 734 | } | ||
| 542 | } | 556 | } | |||||
| HITCBC | 543 | 60 | r.commit(); | 557 | 60 | r.commit(); | ||
| HITCBC | 544 | 417 | } | 558 | 417 | } | ||
| 545 | 559 | |||||||
| 546 | auto | 560 | auto | |||||
| HITCBC | 547 | 6 | object:: | 561 | 6 | object:: | ||
| 548 | erase(const_iterator pos) noexcept -> | 562 | erase(const_iterator pos) noexcept -> | |||||
| 549 | iterator | 563 | iterator | |||||
| 550 | { | 564 | { | |||||
| HITCBC | 551 | 6 | return do_erase(pos, | 565 | 6 | return do_erase(pos, | ||
| HITCBC | 552 | 2 | [this](iterator p) { | 566 | 2 | [this](iterator p) { | ||
| 553 | // the casts silence warnings | 567 | // the casts silence warnings | |||||
| HITCBC | 554 | 2 | std::memcpy( | 568 | 2 | std::memcpy( | ||
| 555 | static_cast<void*>(p), | 569 | static_cast<void*>(p), | |||||
| HITCBC | 556 | 2 | static_cast<void const*>(end()), | 570 | 2 | static_cast<void const*>(end()), | ||
| 557 | sizeof(*p)); | 571 | sizeof(*p)); | |||||
| HITCBC | 558 | 2 | }, | 572 | 2 | }, | ||
| HITCBC | 559 | 3 | [this](iterator p) { | 573 | 3 | [this](iterator p) { | ||
| HITCBC | 560 | 3 | reindex_relocate(end(), p); | 574 | 3 | reindex_relocate(end(), p); | ||
| HITCBC | 561 | 6 | }); | 575 | 6 | }); | ||
| 562 | } | 576 | } | |||||
| 563 | 577 | |||||||
| 564 | auto | 578 | auto | |||||
| HITCBC | 565 | 5 | object:: | 579 | 5 | object:: | ||
| 566 | erase(string_view key) noexcept -> | 580 | erase(string_view key) noexcept -> | |||||
| 567 | std::size_t | 581 | std::size_t | |||||
| 568 | { | 582 | { | |||||
| HITCBC | 569 | 5 | auto it = find(key); | 583 | 5 | auto it = find(key); | ||
| HITCBC | 570 | 5 | if(it == end()) | 584 | 5 | if(it == end()) | ||
| HITCBC | 571 | 1 | return 0; | 585 | 1 | return 0; | ||
| HITCBC | 572 | 4 | erase(it); | 586 | 4 | erase(it); | ||
| HITCBC | 573 | 4 | return 1; | 587 | 4 | return 1; | ||
| 574 | } | 588 | } | |||||
| 575 | 589 | |||||||
| 576 | auto | 590 | auto | |||||
| HITCBC | 577 | 3 | object:: | 591 | 3 | object:: | ||
| 578 | stable_erase(const_iterator pos) noexcept -> | 592 | stable_erase(const_iterator pos) noexcept -> | |||||
| 579 | iterator | 593 | iterator | |||||
| 580 | { | 594 | { | |||||
| HITCBC | 581 | 3 | return do_erase(pos, | 595 | 3 | return do_erase(pos, | ||
| HITCBC | 582 | 2 | [this](iterator p) { | 596 | 2 | [this](iterator p) { | ||
| 583 | // the casts silence warnings | 597 | // the casts silence warnings | |||||
| HITCBC | 584 | 2 | std::memmove( | 598 | 2 | std::memmove( | ||
| 585 | static_cast<void*>(p), | 599 | static_cast<void*>(p), | |||||
| HITCBC | 586 | 2 | static_cast<void const*>(p + 1), | 600 | 2 | static_cast<void const*>(p + 1), | ||
| HITCBC | 587 | 2 | sizeof(*p) * (end() - p)); | 601 | 2 | sizeof(*p) * (end() - p)); | ||
| HITCBC | 588 | 2 | }, | 602 | 2 | }, | ||
| HITCBC | 589 | 1 | [this](iterator p) { | 603 | 1 | [this](iterator p) { | ||
| HITCBC | 590 | 10 | for (; p != end(); ++p) | 604 | 10 | for (; p != end(); ++p) | ||
| 591 | { | 605 | { | |||||
| HITCBC | 592 | 9 | reindex_relocate(p + 1, p); | 606 | 9 | reindex_relocate(p + 1, p); | ||
| 593 | } | 607 | } | |||||
| HITCBC | 594 | 3 | }); | 608 | 3 | }); | ||
| 595 | } | 609 | } | |||||
| 596 | 610 | |||||||
| 597 | auto | 611 | auto | |||||
| HITCBC | 598 | 2 | object:: | 612 | 2 | object:: | ||
| 599 | stable_erase(string_view key) noexcept -> | 613 | stable_erase(string_view key) noexcept -> | |||||
| 600 | std::size_t | 614 | std::size_t | |||||
| 601 | { | 615 | { | |||||
| HITCBC | 602 | 2 | auto it = find(key); | 616 | 2 | auto it = find(key); | ||
| HITCBC | 603 | 2 | if(it == end()) | 617 | 2 | if(it == end()) | ||
| HITCBC | 604 | 1 | return 0; | 618 | 1 | return 0; | ||
| HITCBC | 605 | 1 | stable_erase(it); | 619 | 1 | stable_erase(it); | ||
| HITCBC | 606 | 1 | return 1; | 620 | 1 | return 1; | ||
| 607 | } | 621 | } | |||||
| 608 | 622 | |||||||
| 609 | void | 623 | void | |||||
| HITCBC | 610 | 36 | object:: | 624 | 36 | object:: | ||
| 611 | swap(object& other) | 625 | swap(object& other) | |||||
| 612 | { | 626 | { | |||||
| HITCBC | 613 | 36 | if(*sp_ == *other.sp_) | 627 | 36 | if(*sp_ == *other.sp_) | ||
| 614 | { | 628 | { | |||||
| HITCBC | 615 | 52 | t_ = detail::exchange( | 629 | 52 | t_ = detail::exchange( | ||
| HITCBC | 616 | 26 | other.t_, t_); | 630 | 26 | other.t_, t_); | ||
| HITCBC | 617 | 26 | return; | 631 | 26 | return; | ||
| 618 | } | 632 | } | |||||
| 619 | object temp1( | 633 | object temp1( | |||||
| HITCBC | 620 | 10 | std::move(*this), | 634 | 10 | std::move(*this), | ||
| HITCBC | 621 | 24 | other.storage()); | 635 | 24 | other.storage()); | ||
| 622 | object temp2( | 636 | object temp2( | |||||
| HITCBC | 623 | 6 | std::move(other), | 637 | 6 | std::move(other), | ||
| HITCBC | 624 | 16 | this->storage()); | 638 | 16 | this->storage()); | ||
| HITCBC | 625 | 2 | other.~object(); | 639 | 2 | other.~object(); | ||
| HITCBC | 626 | 2 | ::new(&other) object(pilfer(temp1)); | 640 | 2 | ::new(&other) object(pilfer(temp1)); | ||
| HITCBC | 627 | 2 | this->~object(); | 641 | 2 | this->~object(); | ||
| HITCBC | 628 | 2 | ::new(this) object(pilfer(temp2)); | 642 | 2 | ::new(this) object(pilfer(temp2)); | ||
| HITCBC | 629 | 6 | } | 643 | 6 | } | ||
| 630 | 644 | |||||||
| 631 | //---------------------------------------------------------- | 645 | //---------------------------------------------------------- | |||||
| 632 | // | 646 | // | |||||
| 633 | // Lookup | 647 | // Lookup | |||||
| 634 | // | 648 | // | |||||
| 635 | //---------------------------------------------------------- | 649 | //---------------------------------------------------------- | |||||
| 636 | 650 | |||||||
| 637 | auto | 651 | auto | |||||
| HITCBC | 638 | 146 | object:: | 652 | 146 | object:: | ||
| 639 | operator[](string_view key) -> | 653 | operator[](string_view key) -> | |||||
| 640 | value& | 654 | value& | |||||
| 641 | { | 655 | { | |||||
| 642 | auto const result = | 656 | auto const result = | |||||
| HITCBC | 643 | 146 | emplace(key, nullptr); | 657 | 146 | emplace(key, nullptr); | ||
| HITCBC | 644 | 292 | return result.first->value(); | 658 | 292 | return result.first->value(); | ||
| 645 | } | 659 | } | |||||
| 646 | 660 | |||||||
| 647 | auto | 661 | auto | |||||
| HITCBC | 648 | 8 | object:: | 662 | 8 | object:: | ||
| 649 | count(string_view key) const noexcept -> | 663 | count(string_view key) const noexcept -> | |||||
| 650 | std::size_t | 664 | std::size_t | |||||
| 651 | { | 665 | { | |||||
| HITCBC | 652 | 8 | if(find(key) == end()) | 666 | 8 | if(find(key) == end()) | ||
| HITCBC | 653 | 3 | return 0; | 667 | 3 | return 0; | ||
| HITCBC | 654 | 5 | return 1; | 668 | 5 | return 1; | ||
| 655 | } | 669 | } | |||||
| 656 | 670 | |||||||
| 657 | auto | 671 | auto | |||||
| HITCBC | 658 | 27 | object:: | 672 | 966 | object:: | ||
| 659 | find(string_view key) noexcept -> | 673 | find(string_view key) noexcept -> | |||||
| 660 | iterator | 674 | iterator | |||||
| 661 | { | 675 | { | |||||
| HITCBC | 662 | 27 | if(empty()) | 676 | 966 | if(empty()) | ||
| HITCBC | 663 | 1 | return end(); | 677 | 1 | return end(); | ||
| 664 | auto const p = | 678 | auto const p = | |||||
| HITCBC | 665 | 26 | detail::find_in_object(*this, key).first; | 679 | 965 | detail::find_in_object(*this, key).first; | ||
| HITCBC | 666 | 26 | if(p) | 680 | 965 | if(p) | ||
| HITCBC | 667 | 20 | return p; | 681 | 923 | return p; | ||
| HITCBC | 668 | 6 | return end(); | 682 | 42 | return end(); | ||
| 669 | } | 683 | } | |||||
| 670 | 684 | |||||||
| 671 | auto | 685 | auto | |||||
| HITCBC | 672 | 879 | object:: | 686 | 879 | object:: | ||
| 673 | find(string_view key) const noexcept -> | 687 | find(string_view key) const noexcept -> | |||||
| 674 | const_iterator | 688 | const_iterator | |||||
| 675 | { | 689 | { | |||||
| HITCBC | 676 | 879 | if(empty()) | 690 | 879 | if(empty()) | ||
| HITCBC | 677 | 1 | return end(); | 691 | 1 | return end(); | ||
| 678 | auto const p = | 692 | auto const p = | |||||
| HITCBC | 679 | 878 | detail::find_in_object(*this, key).first; | 693 | 878 | detail::find_in_object(*this, key).first; | ||
| HITCBC | 680 | 878 | if(p) | 694 | 878 | if(p) | ||
| HITCBC | 681 | 866 | return p; | 695 | 866 | return p; | ||
| HITCBC | 682 | 12 | return end(); | 696 | 12 | return end(); | ||
| 683 | } | 697 | } | |||||
| 684 | 698 | |||||||
| 685 | bool | 699 | bool | |||||
| HITCBC | 686 | 3 | object:: | 700 | 3 | object:: | ||
| 687 | contains( | 701 | contains( | |||||
| 688 | string_view key) const noexcept | 702 | string_view key) const noexcept | |||||
| 689 | { | 703 | { | |||||
| HITCBC | 690 | 3 | if(empty()) | 704 | 3 | if(empty()) | ||
| HITCBC | 691 | 1 | return false; | 705 | 1 | return false; | ||
| HITCBC | 692 | 2 | return detail::find_in_object(*this, key).first | 706 | 2 | return detail::find_in_object(*this, key).first | ||
| HITCBC | 693 | 2 | != nullptr; | 707 | 2 | != nullptr; | ||
| 694 | } | 708 | } | |||||
| 695 | 709 | |||||||
| 696 | value const* | 710 | value const* | |||||
| HITCBC | 697 | 3 | object:: | 711 | 3 | object:: | ||
| 698 | if_contains( | 712 | if_contains( | |||||
| 699 | string_view key) const noexcept | 713 | string_view key) const noexcept | |||||
| 700 | { | 714 | { | |||||
| HITCBC | 701 | 3 | auto const it = find(key); | 715 | 3 | auto const it = find(key); | ||
| HITCBC | 702 | 3 | if(it != end()) | 716 | 3 | if(it != end()) | ||
| HITCBC | 703 | 2 | return &it->value(); | 717 | 2 | return &it->value(); | ||
| HITCBC | 704 | 1 | return nullptr; | 718 | 1 | return nullptr; | ||
| 705 | } | 719 | } | |||||
| 706 | 720 | |||||||
| 707 | value* | 721 | value* | |||||
| HITCBC | 708 | 5 | object:: | 722 | 5 | object:: | ||
| 709 | if_contains( | 723 | if_contains( | |||||
| 710 | string_view key) noexcept | 724 | string_view key) noexcept | |||||
| 711 | { | 725 | { | |||||
| HITCBC | 712 | 5 | auto const it = find(key); | 726 | 5 | auto const it = find(key); | ||
| HITCBC | 713 | 5 | if(it != end()) | 727 | 5 | if(it != end()) | ||
| HITCBC | 714 | 4 | return &it->value(); | 728 | 4 | return &it->value(); | ||
| HITCBC | 715 | 1 | return nullptr; | 729 | 1 | return nullptr; | ||
| 716 | } | 730 | } | |||||
| 717 | 731 | |||||||
| 718 | //---------------------------------------------------------- | 732 | //---------------------------------------------------------- | |||||
| 719 | // | 733 | // | |||||
| 720 | // (private) | 734 | // (private) | |||||
| 721 | // | 735 | // | |||||
| 722 | //---------------------------------------------------------- | 736 | //---------------------------------------------------------- | |||||
| 723 | 737 | |||||||
| 724 | key_value_pair* | 738 | key_value_pair* | |||||
| HITCBC | 725 | 3781 | object:: | 739 | 4615 | object:: | ||
| 726 | insert_impl( | 740 | insert_impl( | |||||
| 727 | pilfered<key_value_pair> p, | 741 | pilfered<key_value_pair> p, | |||||
| 728 | std::size_t hash) | 742 | std::size_t hash) | |||||
| 729 | { | 743 | { | |||||
| HITCBC | 730 | 3781 | BOOST_ASSERT( | 744 | 4615 | BOOST_ASSERT( | ||
| 731 | capacity() > size()); | 745 | capacity() > size()); | |||||
| HITCBC | 732 | 3781 | if(t_->is_small()) | 746 | 4615 | if(t_->is_small()) | ||
| 733 | { | 747 | { | |||||
| HITCBC | 734 | 2194 | auto const pv = ::new(end()) | 748 | 2194 | auto const pv = ::new(end()) | ||
| HITCBC | 735 | 2194 | key_value_pair(p); | 749 | 2194 | key_value_pair(p); | ||
| HITCBC | 736 | 2194 | ++t_->size; | 750 | 2194 | ++t_->size; | ||
| HITCBC | 737 | 2194 | return pv; | 751 | 2194 | return pv; | ||
| 738 | } | 752 | } | |||||
| 739 | auto& head = | 753 | auto& head = | |||||
| HITCBC | 740 | 1587 | t_->bucket(hash); | 754 | 2421 | t_->bucket(hash); | ||
| HITCBC | 741 | 1587 | auto const pv = ::new(end()) | 755 | 2421 | auto const pv = ::new(end()) | ||
| HITCBC | 742 | 1587 | key_value_pair(p); | 756 | 2421 | key_value_pair(p); | ||
| HITCBC | 743 | 1587 | access::next(*pv) = head; | 757 | 2421 | access::next(*pv) = head; | ||
| HITCBC | 744 | 1587 | head = t_->size; | 758 | 2421 | head = t_->size; | ||
| HITCBC | 745 | 1587 | ++t_->size; | 759 | 2421 | ++t_->size; | ||
| HITCBC | 746 | 1587 | return pv; | 760 | 2421 | return pv; | ||
| 747 | } | 761 | } | |||||
| 748 | 762 | |||||||
| 749 | // allocate new table, copy elements there, and rehash them | 763 | // allocate new table, copy elements there, and rehash them | |||||
| 750 | object::table* | 764 | object::table* | |||||
| HITCBC | 751 | 1656 | object:: | 765 | 1695 | object:: | ||
| 752 | reserve_impl(std::size_t new_capacity) | 766 | reserve_impl(std::size_t new_capacity) | |||||
| 753 | { | 767 | { | |||||
| HITCBC | 754 | 1656 | BOOST_ASSERT( | 768 | 1695 | BOOST_ASSERT( | ||
| 755 | new_capacity > t_->capacity); | 769 | new_capacity > t_->capacity); | |||||
| HITCBC | 756 | 1649 | auto t = table::allocate( | 770 | 1688 | auto t = table::allocate( | ||
| 757 | growth(new_capacity), | 771 | growth(new_capacity), | |||||
| HITCBC | 758 | 1656 | t_->salt, sp_); | 772 | 1695 | t_->salt, sp_); | ||
| HITCBC | 759 | 1582 | if(! empty()) | 773 | 1621 | if(! empty()) | ||
| HITCBC | 760 | 488 | std::memcpy( | 774 | 488 | std::memcpy( | ||
| 761 | static_cast< | 775 | static_cast< | |||||
| HITCBC | 762 | 488 | void*>(&(*t)[0]), | 776 | 488 | void*>(&(*t)[0]), | ||
| HITCBC | 763 | 488 | begin(), | 777 | 488 | begin(), | ||
| HITCBC | 764 | 488 | size() * sizeof( | 778 | 488 | size() * sizeof( | ||
| 765 | key_value_pair)); | 779 | key_value_pair)); | |||||
| HITCBC | 766 | 1582 | t->size = t_->size; | 780 | 1621 | t->size = t_->size; | ||
| HITCBC | 767 | 1582 | std::swap(t_, t); | 781 | 1621 | std::swap(t_, t); | ||
| 768 | 782 | |||||||
| HITCBC | 769 | 1582 | if(! t_->is_small()) | 783 | 1621 | if(! t_->is_small()) | ||
| 770 | { | 784 | { | |||||
| 771 | // rebuild hash table, | 785 | // rebuild hash table, | |||||
| 772 | // without dup checks | 786 | // without dup checks | |||||
| HITCBC | 773 | 355 | auto p = end(); | 787 | 394 | auto p = end(); | ||
| HITCBC | 774 | 355 | index_t i = t_->size; | 788 | 394 | index_t i = t_->size; | ||
| HITCBC | 775 | 1360 | while(i-- > 0) | 789 | 1399 | while(i-- > 0) | ||
| 776 | { | 790 | { | |||||
| HITCBC | 777 | 1005 | --p; | 791 | 1005 | --p; | ||
| 778 | auto& head = | 792 | auto& head = | |||||
| HITCBC | 779 | 1005 | t_->bucket(p->key()); | 793 | 1005 | t_->bucket(p->key()); | ||
| HITCBC | 780 | 1005 | access::next(*p) = head; | 794 | 1005 | access::next(*p) = head; | ||
| HITCBC | 781 | 1005 | head = i; | 795 | 1005 | head = i; | ||
| 782 | } | 796 | } | |||||
| 783 | } | 797 | } | |||||
| 784 | 798 | |||||||
| HITCBC | 785 | 1582 | return t; | 799 | 1621 | return t; | ||
| 786 | } | 800 | } | |||||
| 787 | 801 | |||||||
| 788 | bool | 802 | bool | |||||
| HITCBC | 789 | 75 | object:: | 803 | 75 | object:: | ||
| 790 | equal(object const& other) const noexcept | 804 | equal(object const& other) const noexcept | |||||
| 791 | { | 805 | { | |||||
| HITCBC | 792 | 75 | if(size() != other.size()) | 806 | 75 | if(size() != other.size()) | ||
| HITCBC | 793 | 5 | return false; | 807 | 5 | return false; | ||
| HITCBC | 794 | 70 | auto const end_ = other.end(); | 808 | 70 | auto const end_ = other.end(); | ||
| HITCBC | 795 | 825 | for(auto e : *this) | 809 | 825 | for(auto e : *this) | ||
| 796 | { | 810 | { | |||||
| HITCBC | 797 | 757 | auto it = other.find(e.key()); | 811 | 757 | auto it = other.find(e.key()); | ||
| HITCBC | 798 | 757 | if(it == end_) | 812 | 757 | if(it == end_) | ||
| HITCBC | 799 | 1 | return false; | 813 | 1 | return false; | ||
| HITCBC | 800 | 756 | if(it->value() != e.value()) | 814 | 756 | if(it->value() != e.value()) | ||
| HITCBC | 801 | 1 | return false; | 815 | 1 | return false; | ||
| HITCBC | 802 | 757 | } | 816 | 757 | } | ||
| HITCBC | 803 | 68 | return true; | 817 | 68 | return true; | ||
| 804 | } | 818 | } | |||||
| 805 | 819 | |||||||
| 806 | std::size_t | 820 | std::size_t | |||||
| HITCBC | 807 | 1656 | object:: | 821 | 1695 | object:: | ||
| 808 | growth( | 822 | growth( | |||||
| 809 | std::size_t new_size) const | 823 | std::size_t new_size) const | |||||
| 810 | { | 824 | { | |||||
| HITCBC | 811 | 1656 | if(new_size > max_size()) | 825 | 1695 | if(new_size > max_size()) | ||
| 812 | { | 826 | { | |||||
| 813 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | 827 | BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION; | |||||
| HITCBC | 814 | 7 | detail::throw_system_error( error::object_too_large, &loc ); | 828 | 7 | detail::throw_system_error( error::object_too_large, &loc ); | ||
| 815 | } | 829 | } | |||||
| HITCBC | 816 | 1649 | std::size_t const old = capacity(); | 830 | 1688 | std::size_t const old = capacity(); | ||
| HITCBC | 817 | 1649 | if(old > max_size() - old / 2) | 831 | 1688 | if(old > max_size() - old / 2) | ||
| HITCBC | 818 | 2 | return new_size; | 832 | 2 | return new_size; | ||
| HITCBC | 819 | 1647 | std::size_t const g = | 833 | 1686 | std::size_t const g = | ||
| HITCBC | 820 | 1647 | old + old / 2; // 1.5x | 834 | 1686 | old + old / 2; // 1.5x | ||
| HITCBC | 821 | 1647 | if(g < new_size) | 835 | 1686 | if(g < new_size) | ||
| HITCBC | 822 | 1245 | return new_size; | 836 | 1284 | return new_size; | ||
| HITCBC | 823 | 402 | return g; | 837 | 402 | return g; | ||
| 824 | } | 838 | } | |||||
| 825 | 839 | |||||||
| 826 | void | 840 | void | |||||
| HITCBC | 827 | 17 | object:: | 841 | 543 | object:: | ||
| 828 | remove( | 842 | remove( | |||||
| 829 | index_t& head, | 843 | index_t& head, | |||||
| 830 | key_value_pair& v) noexcept | 844 | key_value_pair& v) noexcept | |||||
| 831 | { | 845 | { | |||||
| HITCBC | 832 | 17 | BOOST_ASSERT(! t_->is_small()); | 846 | 543 | BOOST_ASSERT(! t_->is_small()); | ||
| 833 | auto const i = static_cast< | 847 | auto const i = static_cast< | |||||
| HITCBC | 834 | 17 | index_t>(&v - begin()); | 848 | 543 | index_t>(&v - begin()); | ||
| HITCBC | 835 | 17 | if(head == i) | 849 | 543 | if(head == i) | ||
| 836 | { | 850 | { | |||||
| HITCBC | 837 | 13 | head = access::next(v); | 851 | 537 | head = access::next(v); | ||
| HITCBC | 838 | 13 | return; | 852 | 537 | return; | ||
| 839 | } | 853 | } | |||||
| 840 | auto* pn = | 854 | auto* pn = | |||||
| HITCBC | 841 | 4 | &access::next((*t_)[head]); | 855 | 6 | &access::next((*t_)[head]); | ||
| HITCBC | 842 | 5 | while(*pn != i) | 856 | 7 | while(*pn != i) | ||
| HITCBC | 843 | 1 | pn = &access::next((*t_)[*pn]); | 857 | 1 | pn = &access::next((*t_)[*pn]); | ||
| HITCBC | 844 | 4 | *pn = access::next(v); | 858 | 6 | *pn = access::next(v); | ||
| 845 | } | 859 | } | |||||
| 846 | 860 | |||||||
| 847 | void | 861 | void | |||||
| HITCBC | 848 | 34771 | object:: | 862 | 34810 | object:: | ||
| 849 | destroy() noexcept | 863 | destroy() noexcept | |||||
| 850 | { | 864 | { | |||||
| HITCBC | 851 | 34771 | BOOST_ASSERT(t_->capacity > 0); | 865 | 34810 | BOOST_ASSERT(t_->capacity > 0); | ||
| HITCBC | 852 | 34771 | BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial()); | 866 | 34810 | BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial()); | ||
| HITCBC | 853 | 34771 | destroy(begin(), end()); | 867 | 34810 | destroy(begin(), end()); | ||
| HITCBC | 854 | 34771 | table::deallocate(t_, sp_); | 868 | 34810 | table::deallocate(t_, sp_); | ||
| HITCBC | 855 | 34771 | } | 869 | 34810 | } | ||
| 856 | 870 | |||||||
| 857 | void | 871 | void | |||||
| HITCBC | 858 | 35006 | object:: | 872 | 35057 | object:: | ||
| 859 | destroy( | 873 | destroy( | |||||
| 860 | key_value_pair* first, | 874 | key_value_pair* first, | |||||
| 861 | key_value_pair* last) noexcept | 875 | key_value_pair* last) noexcept | |||||
| 862 | { | 876 | { | |||||
| HITCBC | 863 | 35006 | BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial()); | 877 | 35057 | BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial()); | ||
| HITCBC | 864 | 83516 | while(last != first) | 878 | 84401 | while(last != first) | ||
| HITCBC | 865 | 48510 | (--last)->~key_value_pair(); | 879 | 49344 | (--last)->~key_value_pair(); | ||
| HITCBC | 866 | 35006 | } | 880 | 35057 | } | ||
| 867 | 881 | |||||||
| 868 | template<class FS, class FB> | 882 | template<class FS, class FB> | |||||
| 869 | auto | 883 | auto | |||||
| HITCBC | 870 | 9 | object:: | 884 | 9 | object:: | ||
| 871 | do_erase( | 885 | do_erase( | |||||
| 872 | const_iterator pos, | 886 | const_iterator pos, | |||||
| 873 | FS small_reloc, | 887 | FS small_reloc, | |||||
| 874 | FB big_reloc) noexcept | 888 | FB big_reloc) noexcept | |||||
| 875 | -> iterator | 889 | -> iterator | |||||
| 876 | { | 890 | { | |||||
| HITCBC | 877 | 9 | auto p = begin() + (pos - begin()); | 891 | 9 | auto p = begin() + (pos - begin()); | ||
| HITCBC | 878 | 9 | if(t_->is_small()) | 892 | 9 | if(t_->is_small()) | ||
| 879 | { | 893 | { | |||||
| HITCBC | 880 | 4 | p->~value_type(); | 894 | 4 | p->~value_type(); | ||
| HITCBC | 881 | 4 | --t_->size; | 895 | 4 | --t_->size; | ||
| HITCBC | 882 | 4 | if(p != end()) | 896 | 4 | if(p != end()) | ||
| 883 | { | 897 | { | |||||
| HITCBC | 884 | 4 | small_reloc(p); | 898 | 4 | small_reloc(p); | ||
| 885 | } | 899 | } | |||||
| HITCBC | 886 | 4 | return p; | 900 | 4 | return p; | ||
| 887 | } | 901 | } | |||||
| HITCBC | 888 | 5 | remove(t_->bucket(p->key()), *p); | 902 | 5 | remove(t_->bucket(p->key()), *p); | ||
| HITCBC | 889 | 5 | p->~value_type(); | 903 | 5 | p->~value_type(); | ||
| HITCBC | 890 | 5 | --t_->size; | 904 | 5 | --t_->size; | ||
| HITCBC | 891 | 5 | if(p != end()) | 905 | 5 | if(p != end()) | ||
| 892 | { | 906 | { | |||||
| HITCBC | 893 | 4 | big_reloc(p); | 907 | 4 | big_reloc(p); | ||
| 894 | } | 908 | } | |||||
| HITCBC | 895 | 5 | return p; | 909 | 5 | return p; | ||
| 896 | } | 910 | } | |||||
| 897 | 911 | |||||||
| 898 | void | 912 | void | |||||
| HITCBC | 899 | 12 | object:: | 913 | 12 | object:: | ||
| 900 | reindex_relocate( | 914 | reindex_relocate( | |||||
| 901 | key_value_pair* src, | 915 | key_value_pair* src, | |||||
| 902 | key_value_pair* dst) noexcept | 916 | key_value_pair* dst) noexcept | |||||
| 903 | { | 917 | { | |||||
| HITCBC | 904 | 12 | BOOST_ASSERT(! t_->is_small()); | 918 | 12 | BOOST_ASSERT(! t_->is_small()); | ||
| HITCBC | 905 | 12 | auto& head = t_->bucket(src->key()); | 919 | 12 | auto& head = t_->bucket(src->key()); | ||
| HITCBC | 906 | 12 | remove(head, *src); | 920 | 12 | remove(head, *src); | ||
| 907 | // the casts silence warnings | 921 | // the casts silence warnings | |||||
| HITCBC | 908 | 12 | std::memcpy( | 922 | 12 | std::memcpy( | ||
| 909 | static_cast<void*>(dst), | 923 | static_cast<void*>(dst), | |||||
| 910 | static_cast<void const*>(src), | 924 | static_cast<void const*>(src), | |||||
| 911 | sizeof(*dst)); | 925 | sizeof(*dst)); | |||||
| HITCBC | 912 | 12 | access::next(*dst) = head; | 926 | 12 | access::next(*dst) = head; | ||
| HITCBC | 913 | 12 | head = static_cast< | 927 | 12 | head = static_cast< | ||
| HITCBC | 914 | 12 | index_t>(dst - begin()); | 928 | 12 | index_t>(dst - begin()); | ||
| HITCBC | 915 | 12 | } | 929 | 12 | } | ||
| 916 | 930 | |||||||
| 917 | } // namespace json | 931 | } // namespace json | |||||
| 918 | } // namespace boost | 932 | } // namespace boost | |||||
| 919 | 933 | |||||||
| 920 | //---------------------------------------------------------- | 934 | //---------------------------------------------------------- | |||||
| 921 | // | 935 | // | |||||
| 922 | // std::hash specialization | 936 | // std::hash specialization | |||||
| 923 | // | 937 | // | |||||
| 924 | //---------------------------------------------------------- | 938 | //---------------------------------------------------------- | |||||
| 925 | 939 | |||||||
| 926 | std::size_t | 940 | std::size_t | |||||
| HITCBC | 927 | 8 | std::hash<::boost::json::object>::operator()( | 941 | 8 | std::hash<::boost::json::object>::operator()( | ||
| 928 | ::boost::json::object const& jo) const noexcept | 942 | ::boost::json::object const& jo) const noexcept | |||||
| 929 | { | 943 | { | |||||
| HITCBC | 930 | 8 | return ::boost::hash< ::boost::json::object >()( jo ); | 944 | 8 | return ::boost::hash< ::boost::json::object >()( jo ); | ||
| 931 | } | 945 | } | |||||
| 932 | 946 | |||||||
| 933 | //---------------------------------------------------------- | 947 | //---------------------------------------------------------- | |||||
| 934 | 948 | |||||||
| 935 | 949 | |||||||
| 936 | #endif | 950 | #endif | |||||