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