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