1*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format 2*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc. All rights reserved. 3*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/ 4*1b3f573fSAndroid Build Coastguard Worker // 5*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without 6*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are 7*1b3f573fSAndroid Build Coastguard Worker // met: 8*1b3f573fSAndroid Build Coastguard Worker // 9*1b3f573fSAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright 10*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer. 11*1b3f573fSAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above 12*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer 13*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the 14*1b3f573fSAndroid Build Coastguard Worker // distribution. 15*1b3f573fSAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its 16*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from 17*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission. 18*1b3f573fSAndroid Build Coastguard Worker // 19*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*1b3f573fSAndroid Build Coastguard Worker 31*1b3f573fSAndroid Build Coastguard Worker // This file defines the map container and its helpers to support protobuf maps. 32*1b3f573fSAndroid Build Coastguard Worker // 33*1b3f573fSAndroid Build Coastguard Worker // The Map and MapIterator types are provided by this header file. 34*1b3f573fSAndroid Build Coastguard Worker // Please avoid using other types defined here, unless they are public 35*1b3f573fSAndroid Build Coastguard Worker // types within Map or MapIterator, such as Map::value_type. 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard Worker #ifndef GOOGLE_PROTOBUF_MAP_H__ 38*1b3f573fSAndroid Build Coastguard Worker #define GOOGLE_PROTOBUF_MAP_H__ 39*1b3f573fSAndroid Build Coastguard Worker 40*1b3f573fSAndroid Build Coastguard Worker 41*1b3f573fSAndroid Build Coastguard Worker #include <functional> 42*1b3f573fSAndroid Build Coastguard Worker #include <initializer_list> 43*1b3f573fSAndroid Build Coastguard Worker #include <iterator> 44*1b3f573fSAndroid Build Coastguard Worker #include <limits> // To support Visual Studio 2008 45*1b3f573fSAndroid Build Coastguard Worker #include <map> 46*1b3f573fSAndroid Build Coastguard Worker #include <string> 47*1b3f573fSAndroid Build Coastguard Worker #include <type_traits> 48*1b3f573fSAndroid Build Coastguard Worker #include <utility> 49*1b3f573fSAndroid Build Coastguard Worker 50*1b3f573fSAndroid Build Coastguard Worker #if defined(__cpp_lib_string_view) 51*1b3f573fSAndroid Build Coastguard Worker #include <string_view> 52*1b3f573fSAndroid Build Coastguard Worker #endif // defined(__cpp_lib_string_view) 53*1b3f573fSAndroid Build Coastguard Worker 54*1b3f573fSAndroid Build Coastguard Worker #if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) 55*1b3f573fSAndroid Build Coastguard Worker #include <mach/mach_time.h> 56*1b3f573fSAndroid Build Coastguard Worker #endif 57*1b3f573fSAndroid Build Coastguard Worker 58*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/stubs/common.h> 59*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/arena.h> 60*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/generated_enum_util.h> 61*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/map_type_handler.h> 62*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/port.h> 63*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/stubs/hash.h> 64*1b3f573fSAndroid Build Coastguard Worker 65*1b3f573fSAndroid Build Coastguard Worker #ifdef SWIG 66*1b3f573fSAndroid Build Coastguard Worker #error "You cannot SWIG proto headers" 67*1b3f573fSAndroid Build Coastguard Worker #endif 68*1b3f573fSAndroid Build Coastguard Worker 69*1b3f573fSAndroid Build Coastguard Worker // Must be included last. 70*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/port_def.inc> 71*1b3f573fSAndroid Build Coastguard Worker 72*1b3f573fSAndroid Build Coastguard Worker namespace google { 73*1b3f573fSAndroid Build Coastguard Worker namespace protobuf { 74*1b3f573fSAndroid Build Coastguard Worker 75*1b3f573fSAndroid Build Coastguard Worker template <typename Key, typename T> 76*1b3f573fSAndroid Build Coastguard Worker class Map; 77*1b3f573fSAndroid Build Coastguard Worker 78*1b3f573fSAndroid Build Coastguard Worker class MapIterator; 79*1b3f573fSAndroid Build Coastguard Worker 80*1b3f573fSAndroid Build Coastguard Worker template <typename Enum> 81*1b3f573fSAndroid Build Coastguard Worker struct is_proto_enum; 82*1b3f573fSAndroid Build Coastguard Worker 83*1b3f573fSAndroid Build Coastguard Worker namespace internal { 84*1b3f573fSAndroid Build Coastguard Worker template <typename Derived, typename Key, typename T, 85*1b3f573fSAndroid Build Coastguard Worker WireFormatLite::FieldType key_wire_type, 86*1b3f573fSAndroid Build Coastguard Worker WireFormatLite::FieldType value_wire_type> 87*1b3f573fSAndroid Build Coastguard Worker class MapFieldLite; 88*1b3f573fSAndroid Build Coastguard Worker 89*1b3f573fSAndroid Build Coastguard Worker template <typename Derived, typename Key, typename T, 90*1b3f573fSAndroid Build Coastguard Worker WireFormatLite::FieldType key_wire_type, 91*1b3f573fSAndroid Build Coastguard Worker WireFormatLite::FieldType value_wire_type> 92*1b3f573fSAndroid Build Coastguard Worker class MapField; 93*1b3f573fSAndroid Build Coastguard Worker 94*1b3f573fSAndroid Build Coastguard Worker template <typename Key, typename T> 95*1b3f573fSAndroid Build Coastguard Worker class TypeDefinedMapFieldBase; 96*1b3f573fSAndroid Build Coastguard Worker 97*1b3f573fSAndroid Build Coastguard Worker class DynamicMapField; 98*1b3f573fSAndroid Build Coastguard Worker 99*1b3f573fSAndroid Build Coastguard Worker class GeneratedMessageReflection; 100*1b3f573fSAndroid Build Coastguard Worker 101*1b3f573fSAndroid Build Coastguard Worker // re-implement std::allocator to use arena allocator for memory allocation. 102*1b3f573fSAndroid Build Coastguard Worker // Used for Map implementation. Users should not use this class 103*1b3f573fSAndroid Build Coastguard Worker // directly. 104*1b3f573fSAndroid Build Coastguard Worker template <typename U> 105*1b3f573fSAndroid Build Coastguard Worker class MapAllocator { 106*1b3f573fSAndroid Build Coastguard Worker public: 107*1b3f573fSAndroid Build Coastguard Worker using value_type = U; 108*1b3f573fSAndroid Build Coastguard Worker using pointer = value_type*; 109*1b3f573fSAndroid Build Coastguard Worker using const_pointer = const value_type*; 110*1b3f573fSAndroid Build Coastguard Worker using reference = value_type&; 111*1b3f573fSAndroid Build Coastguard Worker using const_reference = const value_type&; 112*1b3f573fSAndroid Build Coastguard Worker using size_type = size_t; 113*1b3f573fSAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 114*1b3f573fSAndroid Build Coastguard Worker MapAllocator()115*1b3f573fSAndroid Build Coastguard Worker constexpr MapAllocator() : arena_(nullptr) {} MapAllocator(Arena * arena)116*1b3f573fSAndroid Build Coastguard Worker explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {} 117*1b3f573fSAndroid Build Coastguard Worker template <typename X> MapAllocator(const MapAllocator<X> & allocator)118*1b3f573fSAndroid Build Coastguard Worker MapAllocator(const MapAllocator<X>& allocator) // NOLINT(runtime/explicit) 119*1b3f573fSAndroid Build Coastguard Worker : arena_(allocator.arena()) {} 120*1b3f573fSAndroid Build Coastguard Worker 121*1b3f573fSAndroid Build Coastguard Worker // MapAllocator does not support alignments beyond 8. Technically we should 122*1b3f573fSAndroid Build Coastguard Worker // support up to std::max_align_t, but this fails with ubsan and tcmalloc 123*1b3f573fSAndroid Build Coastguard Worker // debug allocation logic which assume 8 as default alignment. 124*1b3f573fSAndroid Build Coastguard Worker static_assert(alignof(value_type) <= 8, ""); 125*1b3f573fSAndroid Build Coastguard Worker 126*1b3f573fSAndroid Build Coastguard Worker pointer allocate(size_type n, const void* /* hint */ = nullptr) { 127*1b3f573fSAndroid Build Coastguard Worker // If arena is not given, malloc needs to be called which doesn't 128*1b3f573fSAndroid Build Coastguard Worker // construct element object. 129*1b3f573fSAndroid Build Coastguard Worker if (arena_ == nullptr) { 130*1b3f573fSAndroid Build Coastguard Worker return static_cast<pointer>(::operator new(n * sizeof(value_type))); 131*1b3f573fSAndroid Build Coastguard Worker } else { 132*1b3f573fSAndroid Build Coastguard Worker return reinterpret_cast<pointer>( 133*1b3f573fSAndroid Build Coastguard Worker Arena::CreateArray<uint8_t>(arena_, n * sizeof(value_type))); 134*1b3f573fSAndroid Build Coastguard Worker } 135*1b3f573fSAndroid Build Coastguard Worker } 136*1b3f573fSAndroid Build Coastguard Worker deallocate(pointer p,size_type n)137*1b3f573fSAndroid Build Coastguard Worker void deallocate(pointer p, size_type n) { 138*1b3f573fSAndroid Build Coastguard Worker if (arena_ == nullptr) { 139*1b3f573fSAndroid Build Coastguard Worker internal::SizedDelete(p, n * sizeof(value_type)); 140*1b3f573fSAndroid Build Coastguard Worker } 141*1b3f573fSAndroid Build Coastguard Worker } 142*1b3f573fSAndroid Build Coastguard Worker 143*1b3f573fSAndroid Build Coastguard Worker #if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \ 144*1b3f573fSAndroid Build Coastguard Worker !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) 145*1b3f573fSAndroid Build Coastguard Worker template <class NodeType, class... Args> construct(NodeType * p,Args &&...args)146*1b3f573fSAndroid Build Coastguard Worker void construct(NodeType* p, Args&&... args) { 147*1b3f573fSAndroid Build Coastguard Worker // Clang 3.6 doesn't compile static casting to void* directly. (Issue 148*1b3f573fSAndroid Build Coastguard Worker // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall 149*1b3f573fSAndroid Build Coastguard Worker // not cast away constness". So first the maybe const pointer is casted to 150*1b3f573fSAndroid Build Coastguard Worker // const void* and after the const void* is const casted. 151*1b3f573fSAndroid Build Coastguard Worker new (const_cast<void*>(static_cast<const void*>(p))) 152*1b3f573fSAndroid Build Coastguard Worker NodeType(std::forward<Args>(args)...); 153*1b3f573fSAndroid Build Coastguard Worker } 154*1b3f573fSAndroid Build Coastguard Worker 155*1b3f573fSAndroid Build Coastguard Worker template <class NodeType> destroy(NodeType * p)156*1b3f573fSAndroid Build Coastguard Worker void destroy(NodeType* p) { 157*1b3f573fSAndroid Build Coastguard Worker p->~NodeType(); 158*1b3f573fSAndroid Build Coastguard Worker } 159*1b3f573fSAndroid Build Coastguard Worker #else construct(pointer p,const_reference t)160*1b3f573fSAndroid Build Coastguard Worker void construct(pointer p, const_reference t) { new (p) value_type(t); } 161*1b3f573fSAndroid Build Coastguard Worker destroy(pointer p)162*1b3f573fSAndroid Build Coastguard Worker void destroy(pointer p) { p->~value_type(); } 163*1b3f573fSAndroid Build Coastguard Worker #endif 164*1b3f573fSAndroid Build Coastguard Worker 165*1b3f573fSAndroid Build Coastguard Worker template <typename X> 166*1b3f573fSAndroid Build Coastguard Worker struct rebind { 167*1b3f573fSAndroid Build Coastguard Worker using other = MapAllocator<X>; 168*1b3f573fSAndroid Build Coastguard Worker }; 169*1b3f573fSAndroid Build Coastguard Worker 170*1b3f573fSAndroid Build Coastguard Worker template <typename X> 171*1b3f573fSAndroid Build Coastguard Worker bool operator==(const MapAllocator<X>& other) const { 172*1b3f573fSAndroid Build Coastguard Worker return arena_ == other.arena_; 173*1b3f573fSAndroid Build Coastguard Worker } 174*1b3f573fSAndroid Build Coastguard Worker 175*1b3f573fSAndroid Build Coastguard Worker template <typename X> 176*1b3f573fSAndroid Build Coastguard Worker bool operator!=(const MapAllocator<X>& other) const { 177*1b3f573fSAndroid Build Coastguard Worker return arena_ != other.arena_; 178*1b3f573fSAndroid Build Coastguard Worker } 179*1b3f573fSAndroid Build Coastguard Worker 180*1b3f573fSAndroid Build Coastguard Worker // To support Visual Studio 2008 max_size()181*1b3f573fSAndroid Build Coastguard Worker size_type max_size() const { 182*1b3f573fSAndroid Build Coastguard Worker // parentheses around (std::...:max) prevents macro warning of max() 183*1b3f573fSAndroid Build Coastguard Worker return (std::numeric_limits<size_type>::max)(); 184*1b3f573fSAndroid Build Coastguard Worker } 185*1b3f573fSAndroid Build Coastguard Worker 186*1b3f573fSAndroid Build Coastguard Worker // To support gcc-4.4, which does not properly 187*1b3f573fSAndroid Build Coastguard Worker // support templated friend classes arena()188*1b3f573fSAndroid Build Coastguard Worker Arena* arena() const { return arena_; } 189*1b3f573fSAndroid Build Coastguard Worker 190*1b3f573fSAndroid Build Coastguard Worker private: 191*1b3f573fSAndroid Build Coastguard Worker using DestructorSkippable_ = void; 192*1b3f573fSAndroid Build Coastguard Worker Arena* arena_; 193*1b3f573fSAndroid Build Coastguard Worker }; 194*1b3f573fSAndroid Build Coastguard Worker 195*1b3f573fSAndroid Build Coastguard Worker template <typename T> 196*1b3f573fSAndroid Build Coastguard Worker using KeyForTree = 197*1b3f573fSAndroid Build Coastguard Worker typename std::conditional<std::is_scalar<T>::value, T, 198*1b3f573fSAndroid Build Coastguard Worker std::reference_wrapper<const T>>::type; 199*1b3f573fSAndroid Build Coastguard Worker 200*1b3f573fSAndroid Build Coastguard Worker // Default case: Not transparent. 201*1b3f573fSAndroid Build Coastguard Worker // We use std::hash<key_type>/std::less<key_type> and all the lookup functions 202*1b3f573fSAndroid Build Coastguard Worker // only accept `key_type`. 203*1b3f573fSAndroid Build Coastguard Worker template <typename key_type> 204*1b3f573fSAndroid Build Coastguard Worker struct TransparentSupport { 205*1b3f573fSAndroid Build Coastguard Worker using hash = std::hash<key_type>; 206*1b3f573fSAndroid Build Coastguard Worker using less = std::less<key_type>; 207*1b3f573fSAndroid Build Coastguard Worker EqualsTransparentSupport208*1b3f573fSAndroid Build Coastguard Worker static bool Equals(const key_type& a, const key_type& b) { return a == b; } 209*1b3f573fSAndroid Build Coastguard Worker 210*1b3f573fSAndroid Build Coastguard Worker template <typename K> 211*1b3f573fSAndroid Build Coastguard Worker using key_arg = key_type; 212*1b3f573fSAndroid Build Coastguard Worker }; 213*1b3f573fSAndroid Build Coastguard Worker 214*1b3f573fSAndroid Build Coastguard Worker #if defined(__cpp_lib_string_view) 215*1b3f573fSAndroid Build Coastguard Worker // If std::string_view is available, we add transparent support for std::string 216*1b3f573fSAndroid Build Coastguard Worker // keys. We use std::hash<std::string_view> as it supports the input types we 217*1b3f573fSAndroid Build Coastguard Worker // care about. The lookup functions accept arbitrary `K`. This will include any 218*1b3f573fSAndroid Build Coastguard Worker // key type that is convertible to std::string_view. 219*1b3f573fSAndroid Build Coastguard Worker template <> 220*1b3f573fSAndroid Build Coastguard Worker struct TransparentSupport<std::string> { 221*1b3f573fSAndroid Build Coastguard Worker static std::string_view ImplicitConvert(std::string_view str) { return str; } 222*1b3f573fSAndroid Build Coastguard Worker // If the element is not convertible to std::string_view, try to convert to 223*1b3f573fSAndroid Build Coastguard Worker // std::string first. 224*1b3f573fSAndroid Build Coastguard Worker // The template makes this overload lose resolution when both have the same 225*1b3f573fSAndroid Build Coastguard Worker // rank otherwise. 226*1b3f573fSAndroid Build Coastguard Worker template <typename = void> 227*1b3f573fSAndroid Build Coastguard Worker static std::string_view ImplicitConvert(const std::string& str) { 228*1b3f573fSAndroid Build Coastguard Worker return str; 229*1b3f573fSAndroid Build Coastguard Worker } 230*1b3f573fSAndroid Build Coastguard Worker 231*1b3f573fSAndroid Build Coastguard Worker struct hash : private std::hash<std::string_view> { 232*1b3f573fSAndroid Build Coastguard Worker using is_transparent = void; 233*1b3f573fSAndroid Build Coastguard Worker 234*1b3f573fSAndroid Build Coastguard Worker template <typename T> 235*1b3f573fSAndroid Build Coastguard Worker size_t operator()(const T& str) const { 236*1b3f573fSAndroid Build Coastguard Worker return base()(ImplicitConvert(str)); 237*1b3f573fSAndroid Build Coastguard Worker } 238*1b3f573fSAndroid Build Coastguard Worker 239*1b3f573fSAndroid Build Coastguard Worker private: 240*1b3f573fSAndroid Build Coastguard Worker const std::hash<std::string_view>& base() const { return *this; } 241*1b3f573fSAndroid Build Coastguard Worker }; 242*1b3f573fSAndroid Build Coastguard Worker struct less { 243*1b3f573fSAndroid Build Coastguard Worker using is_transparent = void; 244*1b3f573fSAndroid Build Coastguard Worker 245*1b3f573fSAndroid Build Coastguard Worker template <typename T, typename U> 246*1b3f573fSAndroid Build Coastguard Worker bool operator()(const T& t, const U& u) const { 247*1b3f573fSAndroid Build Coastguard Worker return ImplicitConvert(t) < ImplicitConvert(u); 248*1b3f573fSAndroid Build Coastguard Worker } 249*1b3f573fSAndroid Build Coastguard Worker }; 250*1b3f573fSAndroid Build Coastguard Worker 251*1b3f573fSAndroid Build Coastguard Worker template <typename T, typename U> 252*1b3f573fSAndroid Build Coastguard Worker static bool Equals(const T& t, const U& u) { 253*1b3f573fSAndroid Build Coastguard Worker return ImplicitConvert(t) == ImplicitConvert(u); 254*1b3f573fSAndroid Build Coastguard Worker } 255*1b3f573fSAndroid Build Coastguard Worker 256*1b3f573fSAndroid Build Coastguard Worker template <typename K> 257*1b3f573fSAndroid Build Coastguard Worker using key_arg = K; 258*1b3f573fSAndroid Build Coastguard Worker }; 259*1b3f573fSAndroid Build Coastguard Worker #endif // defined(__cpp_lib_string_view) 260*1b3f573fSAndroid Build Coastguard Worker 261*1b3f573fSAndroid Build Coastguard Worker template <typename Key> 262*1b3f573fSAndroid Build Coastguard Worker using TreeForMap = 263*1b3f573fSAndroid Build Coastguard Worker std::map<KeyForTree<Key>, void*, typename TransparentSupport<Key>::less, 264*1b3f573fSAndroid Build Coastguard Worker MapAllocator<std::pair<const KeyForTree<Key>, void*>>>; 265*1b3f573fSAndroid Build Coastguard Worker 266*1b3f573fSAndroid Build Coastguard Worker inline bool TableEntryIsEmpty(void* const* table, size_t b) { 267*1b3f573fSAndroid Build Coastguard Worker return table[b] == nullptr; 268*1b3f573fSAndroid Build Coastguard Worker } 269*1b3f573fSAndroid Build Coastguard Worker inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) { 270*1b3f573fSAndroid Build Coastguard Worker return table[b] != nullptr && table[b] != table[b ^ 1]; 271*1b3f573fSAndroid Build Coastguard Worker } 272*1b3f573fSAndroid Build Coastguard Worker inline bool TableEntryIsTree(void* const* table, size_t b) { 273*1b3f573fSAndroid Build Coastguard Worker return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b); 274*1b3f573fSAndroid Build Coastguard Worker } 275*1b3f573fSAndroid Build Coastguard Worker inline bool TableEntryIsList(void* const* table, size_t b) { 276*1b3f573fSAndroid Build Coastguard Worker return !TableEntryIsTree(table, b); 277*1b3f573fSAndroid Build Coastguard Worker } 278*1b3f573fSAndroid Build Coastguard Worker 279*1b3f573fSAndroid Build Coastguard Worker // This captures all numeric types. 280*1b3f573fSAndroid Build Coastguard Worker inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; } 281*1b3f573fSAndroid Build Coastguard Worker inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) { 282*1b3f573fSAndroid Build Coastguard Worker return StringSpaceUsedExcludingSelfLong(str); 283*1b3f573fSAndroid Build Coastguard Worker } 284*1b3f573fSAndroid Build Coastguard Worker template <typename T, 285*1b3f573fSAndroid Build Coastguard Worker typename = decltype(std::declval<const T&>().SpaceUsedLong())> 286*1b3f573fSAndroid Build Coastguard Worker size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { 287*1b3f573fSAndroid Build Coastguard Worker return message.SpaceUsedLong() - sizeof(T); 288*1b3f573fSAndroid Build Coastguard Worker } 289*1b3f573fSAndroid Build Coastguard Worker 290*1b3f573fSAndroid Build Coastguard Worker constexpr size_t kGlobalEmptyTableSize = 1; 291*1b3f573fSAndroid Build Coastguard Worker PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize]; 292*1b3f573fSAndroid Build Coastguard Worker 293*1b3f573fSAndroid Build Coastguard Worker // Space used for the table, trees, and nodes. 294*1b3f573fSAndroid Build Coastguard Worker // Does not include the indirect space used. Eg the data of a std::string. 295*1b3f573fSAndroid Build Coastguard Worker template <typename Key> 296*1b3f573fSAndroid Build Coastguard Worker PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets, 297*1b3f573fSAndroid Build Coastguard Worker size_t num_elements, 298*1b3f573fSAndroid Build Coastguard Worker size_t sizeof_node) { 299*1b3f573fSAndroid Build Coastguard Worker size_t size = 0; 300*1b3f573fSAndroid Build Coastguard Worker // The size of the table. 301*1b3f573fSAndroid Build Coastguard Worker size += sizeof(void*) * num_buckets; 302*1b3f573fSAndroid Build Coastguard Worker // All the nodes. 303*1b3f573fSAndroid Build Coastguard Worker size += sizeof_node * num_elements; 304*1b3f573fSAndroid Build Coastguard Worker // For each tree, count the overhead of the those nodes. 305*1b3f573fSAndroid Build Coastguard Worker // Two buckets at a time because we only care about trees. 306*1b3f573fSAndroid Build Coastguard Worker for (size_t b = 0; b < num_buckets; b += 2) { 307*1b3f573fSAndroid Build Coastguard Worker if (internal::TableEntryIsTree(table, b)) { 308*1b3f573fSAndroid Build Coastguard Worker using Tree = TreeForMap<Key>; 309*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(table[b]); 310*1b3f573fSAndroid Build Coastguard Worker // Estimated cost of the red-black tree nodes, 3 pointers plus a 311*1b3f573fSAndroid Build Coastguard Worker // bool (plus alignment, so 4 pointers). 312*1b3f573fSAndroid Build Coastguard Worker size += tree->size() * 313*1b3f573fSAndroid Build Coastguard Worker (sizeof(typename Tree::value_type) + sizeof(void*) * 4); 314*1b3f573fSAndroid Build Coastguard Worker } 315*1b3f573fSAndroid Build Coastguard Worker } 316*1b3f573fSAndroid Build Coastguard Worker return size; 317*1b3f573fSAndroid Build Coastguard Worker } 318*1b3f573fSAndroid Build Coastguard Worker 319*1b3f573fSAndroid Build Coastguard Worker template <typename Map, 320*1b3f573fSAndroid Build Coastguard Worker typename = typename std::enable_if< 321*1b3f573fSAndroid Build Coastguard Worker !std::is_scalar<typename Map::key_type>::value || 322*1b3f573fSAndroid Build Coastguard Worker !std::is_scalar<typename Map::mapped_type>::value>::type> 323*1b3f573fSAndroid Build Coastguard Worker size_t SpaceUsedInValues(const Map* map) { 324*1b3f573fSAndroid Build Coastguard Worker size_t size = 0; 325*1b3f573fSAndroid Build Coastguard Worker for (const auto& v : *map) { 326*1b3f573fSAndroid Build Coastguard Worker size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) + 327*1b3f573fSAndroid Build Coastguard Worker internal::MapValueSpaceUsedExcludingSelfLong(v.second); 328*1b3f573fSAndroid Build Coastguard Worker } 329*1b3f573fSAndroid Build Coastguard Worker return size; 330*1b3f573fSAndroid Build Coastguard Worker } 331*1b3f573fSAndroid Build Coastguard Worker 332*1b3f573fSAndroid Build Coastguard Worker inline size_t SpaceUsedInValues(const void*) { return 0; } 333*1b3f573fSAndroid Build Coastguard Worker 334*1b3f573fSAndroid Build Coastguard Worker // Multiply two numbers where overflow is expected. 335*1b3f573fSAndroid Build Coastguard Worker template <typename N> 336*1b3f573fSAndroid Build Coastguard Worker N MultiplyWithOverflow(N a, N b) { 337*1b3f573fSAndroid Build Coastguard Worker #if __has_builtin(__builtin_mul_overflow) 338*1b3f573fSAndroid Build Coastguard Worker N res; 339*1b3f573fSAndroid Build Coastguard Worker (void)__builtin_mul_overflow(a, b, &res); 340*1b3f573fSAndroid Build Coastguard Worker return res; 341*1b3f573fSAndroid Build Coastguard Worker #else 342*1b3f573fSAndroid Build Coastguard Worker return a * b; 343*1b3f573fSAndroid Build Coastguard Worker #endif 344*1b3f573fSAndroid Build Coastguard Worker } 345*1b3f573fSAndroid Build Coastguard Worker 346*1b3f573fSAndroid Build Coastguard Worker } // namespace internal 347*1b3f573fSAndroid Build Coastguard Worker 348*1b3f573fSAndroid Build Coastguard Worker // This is the class for Map's internal value_type. Instead of using 349*1b3f573fSAndroid Build Coastguard Worker // std::pair as value_type, we use this class which provides us more control of 350*1b3f573fSAndroid Build Coastguard Worker // its process of construction and destruction. 351*1b3f573fSAndroid Build Coastguard Worker template <typename Key, typename T> 352*1b3f573fSAndroid Build Coastguard Worker struct PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG MapPair { 353*1b3f573fSAndroid Build Coastguard Worker using first_type = const Key; 354*1b3f573fSAndroid Build Coastguard Worker using second_type = T; 355*1b3f573fSAndroid Build Coastguard Worker 356*1b3f573fSAndroid Build Coastguard Worker MapPair(const Key& other_first, const T& other_second) 357*1b3f573fSAndroid Build Coastguard Worker : first(other_first), second(other_second) {} 358*1b3f573fSAndroid Build Coastguard Worker explicit MapPair(const Key& other_first) : first(other_first), second() {} 359*1b3f573fSAndroid Build Coastguard Worker explicit MapPair(Key&& other_first) 360*1b3f573fSAndroid Build Coastguard Worker : first(std::move(other_first)), second() {} 361*1b3f573fSAndroid Build Coastguard Worker MapPair(const MapPair& other) : first(other.first), second(other.second) {} 362*1b3f573fSAndroid Build Coastguard Worker 363*1b3f573fSAndroid Build Coastguard Worker ~MapPair() {} 364*1b3f573fSAndroid Build Coastguard Worker 365*1b3f573fSAndroid Build Coastguard Worker // Implicitly convertible to std::pair of compatible types. 366*1b3f573fSAndroid Build Coastguard Worker template <typename T1, typename T2> 367*1b3f573fSAndroid Build Coastguard Worker operator std::pair<T1, T2>() const { // NOLINT(runtime/explicit) 368*1b3f573fSAndroid Build Coastguard Worker return std::pair<T1, T2>(first, second); 369*1b3f573fSAndroid Build Coastguard Worker } 370*1b3f573fSAndroid Build Coastguard Worker 371*1b3f573fSAndroid Build Coastguard Worker const Key first; 372*1b3f573fSAndroid Build Coastguard Worker T second; 373*1b3f573fSAndroid Build Coastguard Worker 374*1b3f573fSAndroid Build Coastguard Worker private: 375*1b3f573fSAndroid Build Coastguard Worker friend class Arena; 376*1b3f573fSAndroid Build Coastguard Worker friend class Map<Key, T>; 377*1b3f573fSAndroid Build Coastguard Worker }; 378*1b3f573fSAndroid Build Coastguard Worker 379*1b3f573fSAndroid Build Coastguard Worker // Map is an associative container type used to store protobuf map 380*1b3f573fSAndroid Build Coastguard Worker // fields. Each Map instance may or may not use a different hash function, a 381*1b3f573fSAndroid Build Coastguard Worker // different iteration order, and so on. E.g., please don't examine 382*1b3f573fSAndroid Build Coastguard Worker // implementation details to decide if the following would work: 383*1b3f573fSAndroid Build Coastguard Worker // Map<int, int> m0, m1; 384*1b3f573fSAndroid Build Coastguard Worker // m0[0] = m1[0] = m0[1] = m1[1] = 0; 385*1b3f573fSAndroid Build Coastguard Worker // assert(m0.begin()->first == m1.begin()->first); // Bug! 386*1b3f573fSAndroid Build Coastguard Worker // 387*1b3f573fSAndroid Build Coastguard Worker // Map's interface is similar to std::unordered_map, except that Map is not 388*1b3f573fSAndroid Build Coastguard Worker // designed to play well with exceptions. 389*1b3f573fSAndroid Build Coastguard Worker template <typename Key, typename T> 390*1b3f573fSAndroid Build Coastguard Worker class Map { 391*1b3f573fSAndroid Build Coastguard Worker public: 392*1b3f573fSAndroid Build Coastguard Worker using key_type = Key; 393*1b3f573fSAndroid Build Coastguard Worker using mapped_type = T; 394*1b3f573fSAndroid Build Coastguard Worker using value_type = MapPair<Key, T>; 395*1b3f573fSAndroid Build Coastguard Worker 396*1b3f573fSAndroid Build Coastguard Worker using pointer = value_type*; 397*1b3f573fSAndroid Build Coastguard Worker using const_pointer = const value_type*; 398*1b3f573fSAndroid Build Coastguard Worker using reference = value_type&; 399*1b3f573fSAndroid Build Coastguard Worker using const_reference = const value_type&; 400*1b3f573fSAndroid Build Coastguard Worker 401*1b3f573fSAndroid Build Coastguard Worker using size_type = size_t; 402*1b3f573fSAndroid Build Coastguard Worker using hasher = typename internal::TransparentSupport<Key>::hash; 403*1b3f573fSAndroid Build Coastguard Worker 404*1b3f573fSAndroid Build Coastguard Worker constexpr Map() : elements_(nullptr) {} 405*1b3f573fSAndroid Build Coastguard Worker explicit Map(Arena* arena) : elements_(arena) {} 406*1b3f573fSAndroid Build Coastguard Worker 407*1b3f573fSAndroid Build Coastguard Worker Map(const Map& other) : Map() { insert(other.begin(), other.end()); } 408*1b3f573fSAndroid Build Coastguard Worker 409*1b3f573fSAndroid Build Coastguard Worker Map(Map&& other) noexcept : Map() { 410*1b3f573fSAndroid Build Coastguard Worker if (other.arena() != nullptr) { 411*1b3f573fSAndroid Build Coastguard Worker *this = other; 412*1b3f573fSAndroid Build Coastguard Worker } else { 413*1b3f573fSAndroid Build Coastguard Worker swap(other); 414*1b3f573fSAndroid Build Coastguard Worker } 415*1b3f573fSAndroid Build Coastguard Worker } 416*1b3f573fSAndroid Build Coastguard Worker 417*1b3f573fSAndroid Build Coastguard Worker Map& operator=(Map&& other) noexcept { 418*1b3f573fSAndroid Build Coastguard Worker if (this != &other) { 419*1b3f573fSAndroid Build Coastguard Worker if (arena() != other.arena()) { 420*1b3f573fSAndroid Build Coastguard Worker *this = other; 421*1b3f573fSAndroid Build Coastguard Worker } else { 422*1b3f573fSAndroid Build Coastguard Worker swap(other); 423*1b3f573fSAndroid Build Coastguard Worker } 424*1b3f573fSAndroid Build Coastguard Worker } 425*1b3f573fSAndroid Build Coastguard Worker return *this; 426*1b3f573fSAndroid Build Coastguard Worker } 427*1b3f573fSAndroid Build Coastguard Worker 428*1b3f573fSAndroid Build Coastguard Worker template <class InputIt> 429*1b3f573fSAndroid Build Coastguard Worker Map(const InputIt& first, const InputIt& last) : Map() { 430*1b3f573fSAndroid Build Coastguard Worker insert(first, last); 431*1b3f573fSAndroid Build Coastguard Worker } 432*1b3f573fSAndroid Build Coastguard Worker 433*1b3f573fSAndroid Build Coastguard Worker ~Map() {} 434*1b3f573fSAndroid Build Coastguard Worker 435*1b3f573fSAndroid Build Coastguard Worker private: 436*1b3f573fSAndroid Build Coastguard Worker using Allocator = internal::MapAllocator<void*>; 437*1b3f573fSAndroid Build Coastguard Worker 438*1b3f573fSAndroid Build Coastguard Worker // InnerMap is a generic hash-based map. It doesn't contain any 439*1b3f573fSAndroid Build Coastguard Worker // protocol-buffer-specific logic. It is a chaining hash map with the 440*1b3f573fSAndroid Build Coastguard Worker // additional feature that some buckets can be converted to use an ordered 441*1b3f573fSAndroid Build Coastguard Worker // container. This ensures O(lg n) bounds on find, insert, and erase, while 442*1b3f573fSAndroid Build Coastguard Worker // avoiding the overheads of ordered containers most of the time. 443*1b3f573fSAndroid Build Coastguard Worker // 444*1b3f573fSAndroid Build Coastguard Worker // The implementation doesn't need the full generality of unordered_map, 445*1b3f573fSAndroid Build Coastguard Worker // and it doesn't have it. More bells and whistles can be added as needed. 446*1b3f573fSAndroid Build Coastguard Worker // Some implementation details: 447*1b3f573fSAndroid Build Coastguard Worker // 1. The hash function has type hasher and the equality function 448*1b3f573fSAndroid Build Coastguard Worker // equal_to<Key>. We inherit from hasher to save space 449*1b3f573fSAndroid Build Coastguard Worker // (empty-base-class optimization). 450*1b3f573fSAndroid Build Coastguard Worker // 2. The number of buckets is a power of two. 451*1b3f573fSAndroid Build Coastguard Worker // 3. Buckets are converted to trees in pairs: if we convert bucket b then 452*1b3f573fSAndroid Build Coastguard Worker // buckets b and b^1 will share a tree. Invariant: buckets b and b^1 have 453*1b3f573fSAndroid Build Coastguard Worker // the same non-null value iff they are sharing a tree. (An alternative 454*1b3f573fSAndroid Build Coastguard Worker // implementation strategy would be to have a tag bit per bucket.) 455*1b3f573fSAndroid Build Coastguard Worker // 4. As is typical for hash_map and such, the Keys and Values are always 456*1b3f573fSAndroid Build Coastguard Worker // stored in linked list nodes. Pointers to elements are never invalidated 457*1b3f573fSAndroid Build Coastguard Worker // until the element is deleted. 458*1b3f573fSAndroid Build Coastguard Worker // 5. The trees' payload type is pointer to linked-list node. Tree-converting 459*1b3f573fSAndroid Build Coastguard Worker // a bucket doesn't copy Key-Value pairs. 460*1b3f573fSAndroid Build Coastguard Worker // 6. Once we've tree-converted a bucket, it is never converted back. However, 461*1b3f573fSAndroid Build Coastguard Worker // the items a tree contains may wind up assigned to trees or lists upon a 462*1b3f573fSAndroid Build Coastguard Worker // rehash. 463*1b3f573fSAndroid Build Coastguard Worker // 7. The code requires no C++ features from C++14 or later. 464*1b3f573fSAndroid Build Coastguard Worker // 8. Mutations to a map do not invalidate the map's iterators, pointers to 465*1b3f573fSAndroid Build Coastguard Worker // elements, or references to elements. 466*1b3f573fSAndroid Build Coastguard Worker // 9. Except for erase(iterator), any non-const method can reorder iterators. 467*1b3f573fSAndroid Build Coastguard Worker // 10. InnerMap uses KeyForTree<Key> when using the Tree representation, which 468*1b3f573fSAndroid Build Coastguard Worker // is either `Key`, if Key is a scalar, or `reference_wrapper<const Key>` 469*1b3f573fSAndroid Build Coastguard Worker // otherwise. This avoids unnecessary copies of string keys, for example. 470*1b3f573fSAndroid Build Coastguard Worker class InnerMap : private hasher { 471*1b3f573fSAndroid Build Coastguard Worker public: 472*1b3f573fSAndroid Build Coastguard Worker explicit constexpr InnerMap(Arena* arena) 473*1b3f573fSAndroid Build Coastguard Worker : hasher(), 474*1b3f573fSAndroid Build Coastguard Worker num_elements_(0), 475*1b3f573fSAndroid Build Coastguard Worker num_buckets_(internal::kGlobalEmptyTableSize), 476*1b3f573fSAndroid Build Coastguard Worker seed_(0), 477*1b3f573fSAndroid Build Coastguard Worker index_of_first_non_null_(internal::kGlobalEmptyTableSize), 478*1b3f573fSAndroid Build Coastguard Worker table_(const_cast<void**>(internal::kGlobalEmptyTable)), 479*1b3f573fSAndroid Build Coastguard Worker alloc_(arena) {} 480*1b3f573fSAndroid Build Coastguard Worker 481*1b3f573fSAndroid Build Coastguard Worker ~InnerMap() { 482*1b3f573fSAndroid Build Coastguard Worker if (alloc_.arena() == nullptr && 483*1b3f573fSAndroid Build Coastguard Worker num_buckets_ != internal::kGlobalEmptyTableSize) { 484*1b3f573fSAndroid Build Coastguard Worker clear(); 485*1b3f573fSAndroid Build Coastguard Worker Dealloc<void*>(table_, num_buckets_); 486*1b3f573fSAndroid Build Coastguard Worker } 487*1b3f573fSAndroid Build Coastguard Worker } 488*1b3f573fSAndroid Build Coastguard Worker 489*1b3f573fSAndroid Build Coastguard Worker private: 490*1b3f573fSAndroid Build Coastguard Worker enum { kMinTableSize = 8 }; 491*1b3f573fSAndroid Build Coastguard Worker 492*1b3f573fSAndroid Build Coastguard Worker // Linked-list nodes, as one would expect for a chaining hash table. 493*1b3f573fSAndroid Build Coastguard Worker struct Node { 494*1b3f573fSAndroid Build Coastguard Worker value_type kv; 495*1b3f573fSAndroid Build Coastguard Worker Node* next; 496*1b3f573fSAndroid Build Coastguard Worker }; 497*1b3f573fSAndroid Build Coastguard Worker 498*1b3f573fSAndroid Build Coastguard Worker // Trees. The payload type is a copy of Key, so that we can query the tree 499*1b3f573fSAndroid Build Coastguard Worker // with Keys that are not in any particular data structure. 500*1b3f573fSAndroid Build Coastguard Worker // The value is a void* pointing to Node. We use void* instead of Node* to 501*1b3f573fSAndroid Build Coastguard Worker // avoid code bloat. That way there is only one instantiation of the tree 502*1b3f573fSAndroid Build Coastguard Worker // class per key type. 503*1b3f573fSAndroid Build Coastguard Worker using Tree = internal::TreeForMap<Key>; 504*1b3f573fSAndroid Build Coastguard Worker using TreeIterator = typename Tree::iterator; 505*1b3f573fSAndroid Build Coastguard Worker 506*1b3f573fSAndroid Build Coastguard Worker static Node* NodeFromTreeIterator(TreeIterator it) { 507*1b3f573fSAndroid Build Coastguard Worker return static_cast<Node*>(it->second); 508*1b3f573fSAndroid Build Coastguard Worker } 509*1b3f573fSAndroid Build Coastguard Worker 510*1b3f573fSAndroid Build Coastguard Worker // iterator and const_iterator are instantiations of iterator_base. 511*1b3f573fSAndroid Build Coastguard Worker template <typename KeyValueType> 512*1b3f573fSAndroid Build Coastguard Worker class iterator_base { 513*1b3f573fSAndroid Build Coastguard Worker public: 514*1b3f573fSAndroid Build Coastguard Worker using reference = KeyValueType&; 515*1b3f573fSAndroid Build Coastguard Worker using pointer = KeyValueType*; 516*1b3f573fSAndroid Build Coastguard Worker 517*1b3f573fSAndroid Build Coastguard Worker // Invariants: 518*1b3f573fSAndroid Build Coastguard Worker // node_ is always correct. This is handy because the most common 519*1b3f573fSAndroid Build Coastguard Worker // operations are operator* and operator-> and they only use node_. 520*1b3f573fSAndroid Build Coastguard Worker // When node_ is set to a non-null value, all the other non-const fields 521*1b3f573fSAndroid Build Coastguard Worker // are updated to be correct also, but those fields can become stale 522*1b3f573fSAndroid Build Coastguard Worker // if the underlying map is modified. When those fields are needed they 523*1b3f573fSAndroid Build Coastguard Worker // are rechecked, and updated if necessary. 524*1b3f573fSAndroid Build Coastguard Worker iterator_base() : node_(nullptr), m_(nullptr), bucket_index_(0) {} 525*1b3f573fSAndroid Build Coastguard Worker 526*1b3f573fSAndroid Build Coastguard Worker explicit iterator_base(const InnerMap* m) : m_(m) { 527*1b3f573fSAndroid Build Coastguard Worker SearchFrom(m->index_of_first_non_null_); 528*1b3f573fSAndroid Build Coastguard Worker } 529*1b3f573fSAndroid Build Coastguard Worker 530*1b3f573fSAndroid Build Coastguard Worker // Any iterator_base can convert to any other. This is overkill, and we 531*1b3f573fSAndroid Build Coastguard Worker // rely on the enclosing class to use it wisely. The standard "iterator 532*1b3f573fSAndroid Build Coastguard Worker // can convert to const_iterator" is OK but the reverse direction is not. 533*1b3f573fSAndroid Build Coastguard Worker template <typename U> 534*1b3f573fSAndroid Build Coastguard Worker explicit iterator_base(const iterator_base<U>& it) 535*1b3f573fSAndroid Build Coastguard Worker : node_(it.node_), m_(it.m_), bucket_index_(it.bucket_index_) {} 536*1b3f573fSAndroid Build Coastguard Worker 537*1b3f573fSAndroid Build Coastguard Worker iterator_base(Node* n, const InnerMap* m, size_type index) 538*1b3f573fSAndroid Build Coastguard Worker : node_(n), m_(m), bucket_index_(index) {} 539*1b3f573fSAndroid Build Coastguard Worker 540*1b3f573fSAndroid Build Coastguard Worker iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index) 541*1b3f573fSAndroid Build Coastguard Worker : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) { 542*1b3f573fSAndroid Build Coastguard Worker // Invariant: iterators that use buckets with trees have an even 543*1b3f573fSAndroid Build Coastguard Worker // bucket_index_. 544*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0u); 545*1b3f573fSAndroid Build Coastguard Worker } 546*1b3f573fSAndroid Build Coastguard Worker 547*1b3f573fSAndroid Build Coastguard Worker // Advance through buckets, looking for the first that isn't empty. 548*1b3f573fSAndroid Build Coastguard Worker // If nothing non-empty is found then leave node_ == nullptr. 549*1b3f573fSAndroid Build Coastguard Worker void SearchFrom(size_type start_bucket) { 550*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ || 551*1b3f573fSAndroid Build Coastguard Worker m_->table_[m_->index_of_first_non_null_] != nullptr); 552*1b3f573fSAndroid Build Coastguard Worker node_ = nullptr; 553*1b3f573fSAndroid Build Coastguard Worker for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_; 554*1b3f573fSAndroid Build Coastguard Worker bucket_index_++) { 555*1b3f573fSAndroid Build Coastguard Worker if (m_->TableEntryIsNonEmptyList(bucket_index_)) { 556*1b3f573fSAndroid Build Coastguard Worker node_ = static_cast<Node*>(m_->table_[bucket_index_]); 557*1b3f573fSAndroid Build Coastguard Worker break; 558*1b3f573fSAndroid Build Coastguard Worker } else if (m_->TableEntryIsTree(bucket_index_)) { 559*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); 560*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(!tree->empty()); 561*1b3f573fSAndroid Build Coastguard Worker node_ = NodeFromTreeIterator(tree->begin()); 562*1b3f573fSAndroid Build Coastguard Worker break; 563*1b3f573fSAndroid Build Coastguard Worker } 564*1b3f573fSAndroid Build Coastguard Worker } 565*1b3f573fSAndroid Build Coastguard Worker } 566*1b3f573fSAndroid Build Coastguard Worker 567*1b3f573fSAndroid Build Coastguard Worker reference operator*() const { return node_->kv; } 568*1b3f573fSAndroid Build Coastguard Worker pointer operator->() const { return &(operator*()); } 569*1b3f573fSAndroid Build Coastguard Worker 570*1b3f573fSAndroid Build Coastguard Worker friend bool operator==(const iterator_base& a, const iterator_base& b) { 571*1b3f573fSAndroid Build Coastguard Worker return a.node_ == b.node_; 572*1b3f573fSAndroid Build Coastguard Worker } 573*1b3f573fSAndroid Build Coastguard Worker friend bool operator!=(const iterator_base& a, const iterator_base& b) { 574*1b3f573fSAndroid Build Coastguard Worker return a.node_ != b.node_; 575*1b3f573fSAndroid Build Coastguard Worker } 576*1b3f573fSAndroid Build Coastguard Worker 577*1b3f573fSAndroid Build Coastguard Worker iterator_base& operator++() { 578*1b3f573fSAndroid Build Coastguard Worker if (node_->next == nullptr) { 579*1b3f573fSAndroid Build Coastguard Worker TreeIterator tree_it; 580*1b3f573fSAndroid Build Coastguard Worker const bool is_list = revalidate_if_necessary(&tree_it); 581*1b3f573fSAndroid Build Coastguard Worker if (is_list) { 582*1b3f573fSAndroid Build Coastguard Worker SearchFrom(bucket_index_ + 1); 583*1b3f573fSAndroid Build Coastguard Worker } else { 584*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0u); 585*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); 586*1b3f573fSAndroid Build Coastguard Worker if (++tree_it == tree->end()) { 587*1b3f573fSAndroid Build Coastguard Worker SearchFrom(bucket_index_ + 2); 588*1b3f573fSAndroid Build Coastguard Worker } else { 589*1b3f573fSAndroid Build Coastguard Worker node_ = NodeFromTreeIterator(tree_it); 590*1b3f573fSAndroid Build Coastguard Worker } 591*1b3f573fSAndroid Build Coastguard Worker } 592*1b3f573fSAndroid Build Coastguard Worker } else { 593*1b3f573fSAndroid Build Coastguard Worker node_ = node_->next; 594*1b3f573fSAndroid Build Coastguard Worker } 595*1b3f573fSAndroid Build Coastguard Worker return *this; 596*1b3f573fSAndroid Build Coastguard Worker } 597*1b3f573fSAndroid Build Coastguard Worker 598*1b3f573fSAndroid Build Coastguard Worker iterator_base operator++(int /* unused */) { 599*1b3f573fSAndroid Build Coastguard Worker iterator_base tmp = *this; 600*1b3f573fSAndroid Build Coastguard Worker ++*this; 601*1b3f573fSAndroid Build Coastguard Worker return tmp; 602*1b3f573fSAndroid Build Coastguard Worker } 603*1b3f573fSAndroid Build Coastguard Worker 604*1b3f573fSAndroid Build Coastguard Worker // Assumes node_ and m_ are correct and non-null, but other fields may be 605*1b3f573fSAndroid Build Coastguard Worker // stale. Fix them as needed. Then return true iff node_ points to a 606*1b3f573fSAndroid Build Coastguard Worker // Node in a list. If false is returned then *it is modified to be 607*1b3f573fSAndroid Build Coastguard Worker // a valid iterator for node_. 608*1b3f573fSAndroid Build Coastguard Worker bool revalidate_if_necessary(TreeIterator* it) { 609*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(node_ != nullptr && m_ != nullptr); 610*1b3f573fSAndroid Build Coastguard Worker // Force bucket_index_ to be in range. 611*1b3f573fSAndroid Build Coastguard Worker bucket_index_ &= (m_->num_buckets_ - 1); 612*1b3f573fSAndroid Build Coastguard Worker // Common case: the bucket we think is relevant points to node_. 613*1b3f573fSAndroid Build Coastguard Worker if (m_->table_[bucket_index_] == static_cast<void*>(node_)) return true; 614*1b3f573fSAndroid Build Coastguard Worker // Less common: the bucket is a linked list with node_ somewhere in it, 615*1b3f573fSAndroid Build Coastguard Worker // but not at the head. 616*1b3f573fSAndroid Build Coastguard Worker if (m_->TableEntryIsNonEmptyList(bucket_index_)) { 617*1b3f573fSAndroid Build Coastguard Worker Node* l = static_cast<Node*>(m_->table_[bucket_index_]); 618*1b3f573fSAndroid Build Coastguard Worker while ((l = l->next) != nullptr) { 619*1b3f573fSAndroid Build Coastguard Worker if (l == node_) { 620*1b3f573fSAndroid Build Coastguard Worker return true; 621*1b3f573fSAndroid Build Coastguard Worker } 622*1b3f573fSAndroid Build Coastguard Worker } 623*1b3f573fSAndroid Build Coastguard Worker } 624*1b3f573fSAndroid Build Coastguard Worker // Well, bucket_index_ still might be correct, but probably 625*1b3f573fSAndroid Build Coastguard Worker // not. Revalidate just to be sure. This case is rare enough that we 626*1b3f573fSAndroid Build Coastguard Worker // don't worry about potential optimizations, such as having a custom 627*1b3f573fSAndroid Build Coastguard Worker // find-like method that compares Node* instead of the key. 628*1b3f573fSAndroid Build Coastguard Worker iterator_base i(m_->find(node_->kv.first, it)); 629*1b3f573fSAndroid Build Coastguard Worker bucket_index_ = i.bucket_index_; 630*1b3f573fSAndroid Build Coastguard Worker return m_->TableEntryIsList(bucket_index_); 631*1b3f573fSAndroid Build Coastguard Worker } 632*1b3f573fSAndroid Build Coastguard Worker 633*1b3f573fSAndroid Build Coastguard Worker Node* node_; 634*1b3f573fSAndroid Build Coastguard Worker const InnerMap* m_; 635*1b3f573fSAndroid Build Coastguard Worker size_type bucket_index_; 636*1b3f573fSAndroid Build Coastguard Worker }; 637*1b3f573fSAndroid Build Coastguard Worker 638*1b3f573fSAndroid Build Coastguard Worker public: 639*1b3f573fSAndroid Build Coastguard Worker using iterator = iterator_base<value_type>; 640*1b3f573fSAndroid Build Coastguard Worker using const_iterator = iterator_base<const value_type>; 641*1b3f573fSAndroid Build Coastguard Worker 642*1b3f573fSAndroid Build Coastguard Worker Arena* arena() const { return alloc_.arena(); } 643*1b3f573fSAndroid Build Coastguard Worker 644*1b3f573fSAndroid Build Coastguard Worker void Swap(InnerMap* other) { 645*1b3f573fSAndroid Build Coastguard Worker std::swap(num_elements_, other->num_elements_); 646*1b3f573fSAndroid Build Coastguard Worker std::swap(num_buckets_, other->num_buckets_); 647*1b3f573fSAndroid Build Coastguard Worker std::swap(seed_, other->seed_); 648*1b3f573fSAndroid Build Coastguard Worker std::swap(index_of_first_non_null_, other->index_of_first_non_null_); 649*1b3f573fSAndroid Build Coastguard Worker std::swap(table_, other->table_); 650*1b3f573fSAndroid Build Coastguard Worker std::swap(alloc_, other->alloc_); 651*1b3f573fSAndroid Build Coastguard Worker } 652*1b3f573fSAndroid Build Coastguard Worker 653*1b3f573fSAndroid Build Coastguard Worker iterator begin() { return iterator(this); } 654*1b3f573fSAndroid Build Coastguard Worker iterator end() { return iterator(); } 655*1b3f573fSAndroid Build Coastguard Worker const_iterator begin() const { return const_iterator(this); } 656*1b3f573fSAndroid Build Coastguard Worker const_iterator end() const { return const_iterator(); } 657*1b3f573fSAndroid Build Coastguard Worker 658*1b3f573fSAndroid Build Coastguard Worker void clear() { 659*1b3f573fSAndroid Build Coastguard Worker for (size_type b = 0; b < num_buckets_; b++) { 660*1b3f573fSAndroid Build Coastguard Worker if (TableEntryIsNonEmptyList(b)) { 661*1b3f573fSAndroid Build Coastguard Worker Node* node = static_cast<Node*>(table_[b]); 662*1b3f573fSAndroid Build Coastguard Worker table_[b] = nullptr; 663*1b3f573fSAndroid Build Coastguard Worker do { 664*1b3f573fSAndroid Build Coastguard Worker Node* next = node->next; 665*1b3f573fSAndroid Build Coastguard Worker DestroyNode(node); 666*1b3f573fSAndroid Build Coastguard Worker node = next; 667*1b3f573fSAndroid Build Coastguard Worker } while (node != nullptr); 668*1b3f573fSAndroid Build Coastguard Worker } else if (TableEntryIsTree(b)) { 669*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(table_[b]); 670*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0); 671*1b3f573fSAndroid Build Coastguard Worker table_[b] = table_[b + 1] = nullptr; 672*1b3f573fSAndroid Build Coastguard Worker typename Tree::iterator tree_it = tree->begin(); 673*1b3f573fSAndroid Build Coastguard Worker do { 674*1b3f573fSAndroid Build Coastguard Worker Node* node = NodeFromTreeIterator(tree_it); 675*1b3f573fSAndroid Build Coastguard Worker typename Tree::iterator next = tree_it; 676*1b3f573fSAndroid Build Coastguard Worker ++next; 677*1b3f573fSAndroid Build Coastguard Worker tree->erase(tree_it); 678*1b3f573fSAndroid Build Coastguard Worker DestroyNode(node); 679*1b3f573fSAndroid Build Coastguard Worker tree_it = next; 680*1b3f573fSAndroid Build Coastguard Worker } while (tree_it != tree->end()); 681*1b3f573fSAndroid Build Coastguard Worker DestroyTree(tree); 682*1b3f573fSAndroid Build Coastguard Worker b++; 683*1b3f573fSAndroid Build Coastguard Worker } 684*1b3f573fSAndroid Build Coastguard Worker } 685*1b3f573fSAndroid Build Coastguard Worker num_elements_ = 0; 686*1b3f573fSAndroid Build Coastguard Worker index_of_first_non_null_ = num_buckets_; 687*1b3f573fSAndroid Build Coastguard Worker } 688*1b3f573fSAndroid Build Coastguard Worker 689*1b3f573fSAndroid Build Coastguard Worker const hasher& hash_function() const { return *this; } 690*1b3f573fSAndroid Build Coastguard Worker 691*1b3f573fSAndroid Build Coastguard Worker static size_type max_size() { 692*1b3f573fSAndroid Build Coastguard Worker return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28); 693*1b3f573fSAndroid Build Coastguard Worker } 694*1b3f573fSAndroid Build Coastguard Worker size_type size() const { return num_elements_; } 695*1b3f573fSAndroid Build Coastguard Worker bool empty() const { return size() == 0; } 696*1b3f573fSAndroid Build Coastguard Worker 697*1b3f573fSAndroid Build Coastguard Worker template <typename K> 698*1b3f573fSAndroid Build Coastguard Worker iterator find(const K& k) { 699*1b3f573fSAndroid Build Coastguard Worker return iterator(FindHelper(k).first); 700*1b3f573fSAndroid Build Coastguard Worker } 701*1b3f573fSAndroid Build Coastguard Worker 702*1b3f573fSAndroid Build Coastguard Worker template <typename K> 703*1b3f573fSAndroid Build Coastguard Worker const_iterator find(const K& k) const { 704*1b3f573fSAndroid Build Coastguard Worker return FindHelper(k).first; 705*1b3f573fSAndroid Build Coastguard Worker } 706*1b3f573fSAndroid Build Coastguard Worker 707*1b3f573fSAndroid Build Coastguard Worker // Inserts a new element into the container if there is no element with the 708*1b3f573fSAndroid Build Coastguard Worker // key in the container. 709*1b3f573fSAndroid Build Coastguard Worker // The new element is: 710*1b3f573fSAndroid Build Coastguard Worker // (1) Constructed in-place with the given args, if mapped_type is not 711*1b3f573fSAndroid Build Coastguard Worker // arena constructible. 712*1b3f573fSAndroid Build Coastguard Worker // (2) Constructed in-place with the arena and then assigned with a 713*1b3f573fSAndroid Build Coastguard Worker // mapped_type temporary constructed with the given args, otherwise. 714*1b3f573fSAndroid Build Coastguard Worker template <typename K, typename... Args> 715*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) { 716*1b3f573fSAndroid Build Coastguard Worker return ArenaAwareTryEmplace(Arena::is_arena_constructable<mapped_type>(), 717*1b3f573fSAndroid Build Coastguard Worker std::forward<K>(k), 718*1b3f573fSAndroid Build Coastguard Worker std::forward<Args>(args)...); 719*1b3f573fSAndroid Build Coastguard Worker } 720*1b3f573fSAndroid Build Coastguard Worker 721*1b3f573fSAndroid Build Coastguard Worker // Inserts the key into the map, if not present. In that case, the value 722*1b3f573fSAndroid Build Coastguard Worker // will be value initialized. 723*1b3f573fSAndroid Build Coastguard Worker template <typename K> 724*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> insert(K&& k) { 725*1b3f573fSAndroid Build Coastguard Worker return try_emplace(std::forward<K>(k)); 726*1b3f573fSAndroid Build Coastguard Worker } 727*1b3f573fSAndroid Build Coastguard Worker 728*1b3f573fSAndroid Build Coastguard Worker template <typename K> 729*1b3f573fSAndroid Build Coastguard Worker value_type& operator[](K&& k) { 730*1b3f573fSAndroid Build Coastguard Worker return *try_emplace(std::forward<K>(k)).first; 731*1b3f573fSAndroid Build Coastguard Worker } 732*1b3f573fSAndroid Build Coastguard Worker 733*1b3f573fSAndroid Build Coastguard Worker void erase(iterator it) { 734*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(it.m_, this); 735*1b3f573fSAndroid Build Coastguard Worker typename Tree::iterator tree_it; 736*1b3f573fSAndroid Build Coastguard Worker const bool is_list = it.revalidate_if_necessary(&tree_it); 737*1b3f573fSAndroid Build Coastguard Worker size_type b = it.bucket_index_; 738*1b3f573fSAndroid Build Coastguard Worker Node* const item = it.node_; 739*1b3f573fSAndroid Build Coastguard Worker if (is_list) { 740*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(TableEntryIsNonEmptyList(b)); 741*1b3f573fSAndroid Build Coastguard Worker Node* head = static_cast<Node*>(table_[b]); 742*1b3f573fSAndroid Build Coastguard Worker head = EraseFromLinkedList(item, head); 743*1b3f573fSAndroid Build Coastguard Worker table_[b] = static_cast<void*>(head); 744*1b3f573fSAndroid Build Coastguard Worker } else { 745*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(TableEntryIsTree(b)); 746*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(table_[b]); 747*1b3f573fSAndroid Build Coastguard Worker tree->erase(tree_it); 748*1b3f573fSAndroid Build Coastguard Worker if (tree->empty()) { 749*1b3f573fSAndroid Build Coastguard Worker // Force b to be the minimum of b and b ^ 1. This is important 750*1b3f573fSAndroid Build Coastguard Worker // only because we want index_of_first_non_null_ to be correct. 751*1b3f573fSAndroid Build Coastguard Worker b &= ~static_cast<size_type>(1); 752*1b3f573fSAndroid Build Coastguard Worker DestroyTree(tree); 753*1b3f573fSAndroid Build Coastguard Worker table_[b] = table_[b + 1] = nullptr; 754*1b3f573fSAndroid Build Coastguard Worker } 755*1b3f573fSAndroid Build Coastguard Worker } 756*1b3f573fSAndroid Build Coastguard Worker DestroyNode(item); 757*1b3f573fSAndroid Build Coastguard Worker --num_elements_; 758*1b3f573fSAndroid Build Coastguard Worker if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) { 759*1b3f573fSAndroid Build Coastguard Worker while (index_of_first_non_null_ < num_buckets_ && 760*1b3f573fSAndroid Build Coastguard Worker table_[index_of_first_non_null_] == nullptr) { 761*1b3f573fSAndroid Build Coastguard Worker ++index_of_first_non_null_; 762*1b3f573fSAndroid Build Coastguard Worker } 763*1b3f573fSAndroid Build Coastguard Worker } 764*1b3f573fSAndroid Build Coastguard Worker } 765*1b3f573fSAndroid Build Coastguard Worker 766*1b3f573fSAndroid Build Coastguard Worker size_t SpaceUsedInternal() const { 767*1b3f573fSAndroid Build Coastguard Worker return internal::SpaceUsedInTable<Key>(table_, num_buckets_, 768*1b3f573fSAndroid Build Coastguard Worker num_elements_, sizeof(Node)); 769*1b3f573fSAndroid Build Coastguard Worker } 770*1b3f573fSAndroid Build Coastguard Worker 771*1b3f573fSAndroid Build Coastguard Worker private: 772*1b3f573fSAndroid Build Coastguard Worker template <typename K, typename... Args> 773*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> TryEmplaceInternal(K&& k, Args&&... args) { 774*1b3f573fSAndroid Build Coastguard Worker std::pair<const_iterator, size_type> p = FindHelper(k); 775*1b3f573fSAndroid Build Coastguard Worker // Case 1: key was already present. 776*1b3f573fSAndroid Build Coastguard Worker if (p.first.node_ != nullptr) 777*1b3f573fSAndroid Build Coastguard Worker return std::make_pair(iterator(p.first), false); 778*1b3f573fSAndroid Build Coastguard Worker // Case 2: insert. 779*1b3f573fSAndroid Build Coastguard Worker if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { 780*1b3f573fSAndroid Build Coastguard Worker p = FindHelper(k); 781*1b3f573fSAndroid Build Coastguard Worker } 782*1b3f573fSAndroid Build Coastguard Worker const size_type b = p.second; // bucket number 783*1b3f573fSAndroid Build Coastguard Worker // If K is not key_type, make the conversion to key_type explicit. 784*1b3f573fSAndroid Build Coastguard Worker using TypeToInit = typename std::conditional< 785*1b3f573fSAndroid Build Coastguard Worker std::is_same<typename std::decay<K>::type, key_type>::value, K&&, 786*1b3f573fSAndroid Build Coastguard Worker key_type>::type; 787*1b3f573fSAndroid Build Coastguard Worker Node* node = Alloc<Node>(1); 788*1b3f573fSAndroid Build Coastguard Worker // Even when arena is nullptr, CreateInArenaStorage is still used to 789*1b3f573fSAndroid Build Coastguard Worker // ensure the arena of submessage will be consistent. Otherwise, 790*1b3f573fSAndroid Build Coastguard Worker // submessage may have its own arena when message-owned arena is enabled. 791*1b3f573fSAndroid Build Coastguard Worker // Note: This only works if `Key` is not arena constructible. 792*1b3f573fSAndroid Build Coastguard Worker Arena::CreateInArenaStorage(const_cast<Key*>(&node->kv.first), 793*1b3f573fSAndroid Build Coastguard Worker alloc_.arena(), 794*1b3f573fSAndroid Build Coastguard Worker static_cast<TypeToInit>(std::forward<K>(k))); 795*1b3f573fSAndroid Build Coastguard Worker // Note: if `T` is arena constructible, `Args` needs to be empty. 796*1b3f573fSAndroid Build Coastguard Worker Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena(), 797*1b3f573fSAndroid Build Coastguard Worker std::forward<Args>(args)...); 798*1b3f573fSAndroid Build Coastguard Worker 799*1b3f573fSAndroid Build Coastguard Worker iterator result = InsertUnique(b, node); 800*1b3f573fSAndroid Build Coastguard Worker ++num_elements_; 801*1b3f573fSAndroid Build Coastguard Worker return std::make_pair(result, true); 802*1b3f573fSAndroid Build Coastguard Worker } 803*1b3f573fSAndroid Build Coastguard Worker 804*1b3f573fSAndroid Build Coastguard Worker // A helper function to perform an assignment of `mapped_type`. 805*1b3f573fSAndroid Build Coastguard Worker // If the first argument is true, then it is a regular assignment. 806*1b3f573fSAndroid Build Coastguard Worker // Otherwise, we first create a temporary and then perform an assignment. 807*1b3f573fSAndroid Build Coastguard Worker template <typename V> 808*1b3f573fSAndroid Build Coastguard Worker static void AssignMapped(std::true_type, mapped_type& mapped, V&& v) { 809*1b3f573fSAndroid Build Coastguard Worker mapped = std::forward<V>(v); 810*1b3f573fSAndroid Build Coastguard Worker } 811*1b3f573fSAndroid Build Coastguard Worker template <typename... Args> 812*1b3f573fSAndroid Build Coastguard Worker static void AssignMapped(std::false_type, mapped_type& mapped, 813*1b3f573fSAndroid Build Coastguard Worker Args&&... args) { 814*1b3f573fSAndroid Build Coastguard Worker mapped = mapped_type(std::forward<Args>(args)...); 815*1b3f573fSAndroid Build Coastguard Worker } 816*1b3f573fSAndroid Build Coastguard Worker 817*1b3f573fSAndroid Build Coastguard Worker // Case 1: `mapped_type` is arena constructible. A temporary object is 818*1b3f573fSAndroid Build Coastguard Worker // created and then (if `Args` are not empty) assigned to a mapped value 819*1b3f573fSAndroid Build Coastguard Worker // that was created with the arena. 820*1b3f573fSAndroid Build Coastguard Worker template <typename K> 821*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k) { 822*1b3f573fSAndroid Build Coastguard Worker // case 1.1: "default" constructed (e.g. from arena only). 823*1b3f573fSAndroid Build Coastguard Worker return TryEmplaceInternal(std::forward<K>(k)); 824*1b3f573fSAndroid Build Coastguard Worker } 825*1b3f573fSAndroid Build Coastguard Worker template <typename K, typename... Args> 826*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k, 827*1b3f573fSAndroid Build Coastguard Worker Args&&... args) { 828*1b3f573fSAndroid Build Coastguard Worker // case 1.2: "default" constructed + copy/move assignment 829*1b3f573fSAndroid Build Coastguard Worker auto p = TryEmplaceInternal(std::forward<K>(k)); 830*1b3f573fSAndroid Build Coastguard Worker if (p.second) { 831*1b3f573fSAndroid Build Coastguard Worker AssignMapped(std::is_same<void(typename std::decay<Args>::type...), 832*1b3f573fSAndroid Build Coastguard Worker void(mapped_type)>(), 833*1b3f573fSAndroid Build Coastguard Worker p.first->second, std::forward<Args>(args)...); 834*1b3f573fSAndroid Build Coastguard Worker } 835*1b3f573fSAndroid Build Coastguard Worker return p; 836*1b3f573fSAndroid Build Coastguard Worker } 837*1b3f573fSAndroid Build Coastguard Worker // Case 2: `mapped_type` is not arena constructible. Using in-place 838*1b3f573fSAndroid Build Coastguard Worker // construction. 839*1b3f573fSAndroid Build Coastguard Worker template <typename... Args> 840*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> ArenaAwareTryEmplace(std::false_type, 841*1b3f573fSAndroid Build Coastguard Worker Args&&... args) { 842*1b3f573fSAndroid Build Coastguard Worker return TryEmplaceInternal(std::forward<Args>(args)...); 843*1b3f573fSAndroid Build Coastguard Worker } 844*1b3f573fSAndroid Build Coastguard Worker 845*1b3f573fSAndroid Build Coastguard Worker const_iterator find(const Key& k, TreeIterator* it) const { 846*1b3f573fSAndroid Build Coastguard Worker return FindHelper(k, it).first; 847*1b3f573fSAndroid Build Coastguard Worker } 848*1b3f573fSAndroid Build Coastguard Worker template <typename K> 849*1b3f573fSAndroid Build Coastguard Worker std::pair<const_iterator, size_type> FindHelper(const K& k) const { 850*1b3f573fSAndroid Build Coastguard Worker return FindHelper(k, nullptr); 851*1b3f573fSAndroid Build Coastguard Worker } 852*1b3f573fSAndroid Build Coastguard Worker template <typename K> 853*1b3f573fSAndroid Build Coastguard Worker std::pair<const_iterator, size_type> FindHelper(const K& k, 854*1b3f573fSAndroid Build Coastguard Worker TreeIterator* it) const { 855*1b3f573fSAndroid Build Coastguard Worker size_type b = BucketNumber(k); 856*1b3f573fSAndroid Build Coastguard Worker if (TableEntryIsNonEmptyList(b)) { 857*1b3f573fSAndroid Build Coastguard Worker Node* node = static_cast<Node*>(table_[b]); 858*1b3f573fSAndroid Build Coastguard Worker do { 859*1b3f573fSAndroid Build Coastguard Worker if (internal::TransparentSupport<Key>::Equals(node->kv.first, k)) { 860*1b3f573fSAndroid Build Coastguard Worker return std::make_pair(const_iterator(node, this, b), b); 861*1b3f573fSAndroid Build Coastguard Worker } else { 862*1b3f573fSAndroid Build Coastguard Worker node = node->next; 863*1b3f573fSAndroid Build Coastguard Worker } 864*1b3f573fSAndroid Build Coastguard Worker } while (node != nullptr); 865*1b3f573fSAndroid Build Coastguard Worker } else if (TableEntryIsTree(b)) { 866*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); 867*1b3f573fSAndroid Build Coastguard Worker b &= ~static_cast<size_t>(1); 868*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(table_[b]); 869*1b3f573fSAndroid Build Coastguard Worker auto tree_it = tree->find(k); 870*1b3f573fSAndroid Build Coastguard Worker if (tree_it != tree->end()) { 871*1b3f573fSAndroid Build Coastguard Worker if (it != nullptr) *it = tree_it; 872*1b3f573fSAndroid Build Coastguard Worker return std::make_pair(const_iterator(tree_it, this, b), b); 873*1b3f573fSAndroid Build Coastguard Worker } 874*1b3f573fSAndroid Build Coastguard Worker } 875*1b3f573fSAndroid Build Coastguard Worker return std::make_pair(end(), b); 876*1b3f573fSAndroid Build Coastguard Worker } 877*1b3f573fSAndroid Build Coastguard Worker 878*1b3f573fSAndroid Build Coastguard Worker // Insert the given Node in bucket b. If that would make bucket b too big, 879*1b3f573fSAndroid Build Coastguard Worker // and bucket b is not a tree, create a tree for buckets b and b^1 to share. 880*1b3f573fSAndroid Build Coastguard Worker // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct 881*1b3f573fSAndroid Build Coastguard Worker // bucket. num_elements_ is not modified. 882*1b3f573fSAndroid Build Coastguard Worker iterator InsertUnique(size_type b, Node* node) { 883*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ || 884*1b3f573fSAndroid Build Coastguard Worker table_[index_of_first_non_null_] != nullptr); 885*1b3f573fSAndroid Build Coastguard Worker // In practice, the code that led to this point may have already 886*1b3f573fSAndroid Build Coastguard Worker // determined whether we are inserting into an empty list, a short list, 887*1b3f573fSAndroid Build Coastguard Worker // or whatever. But it's probably cheap enough to recompute that here; 888*1b3f573fSAndroid Build Coastguard Worker // it's likely that we're inserting into an empty or short list. 889*1b3f573fSAndroid Build Coastguard Worker iterator result; 890*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(find(node->kv.first) == end()); 891*1b3f573fSAndroid Build Coastguard Worker if (TableEntryIsEmpty(b)) { 892*1b3f573fSAndroid Build Coastguard Worker result = InsertUniqueInList(b, node); 893*1b3f573fSAndroid Build Coastguard Worker } else if (TableEntryIsNonEmptyList(b)) { 894*1b3f573fSAndroid Build Coastguard Worker if (PROTOBUF_PREDICT_FALSE(TableEntryIsTooLong(b))) { 895*1b3f573fSAndroid Build Coastguard Worker TreeConvert(b); 896*1b3f573fSAndroid Build Coastguard Worker result = InsertUniqueInTree(b, node); 897*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1)); 898*1b3f573fSAndroid Build Coastguard Worker } else { 899*1b3f573fSAndroid Build Coastguard Worker // Insert into a pre-existing list. This case cannot modify 900*1b3f573fSAndroid Build Coastguard Worker // index_of_first_non_null_, so we skip the code to update it. 901*1b3f573fSAndroid Build Coastguard Worker return InsertUniqueInList(b, node); 902*1b3f573fSAndroid Build Coastguard Worker } 903*1b3f573fSAndroid Build Coastguard Worker } else { 904*1b3f573fSAndroid Build Coastguard Worker // Insert into a pre-existing tree. This case cannot modify 905*1b3f573fSAndroid Build Coastguard Worker // index_of_first_non_null_, so we skip the code to update it. 906*1b3f573fSAndroid Build Coastguard Worker return InsertUniqueInTree(b, node); 907*1b3f573fSAndroid Build Coastguard Worker } 908*1b3f573fSAndroid Build Coastguard Worker // parentheses around (std::min) prevents macro expansion of min(...) 909*1b3f573fSAndroid Build Coastguard Worker index_of_first_non_null_ = 910*1b3f573fSAndroid Build Coastguard Worker (std::min)(index_of_first_non_null_, result.bucket_index_); 911*1b3f573fSAndroid Build Coastguard Worker return result; 912*1b3f573fSAndroid Build Coastguard Worker } 913*1b3f573fSAndroid Build Coastguard Worker 914*1b3f573fSAndroid Build Coastguard Worker // Returns whether we should insert after the head of the list. For 915*1b3f573fSAndroid Build Coastguard Worker // non-optimized builds, we randomly decide whether to insert right at the 916*1b3f573fSAndroid Build Coastguard Worker // head of the list or just after the head. This helps add a little bit of 917*1b3f573fSAndroid Build Coastguard Worker // non-determinism to the map ordering. 918*1b3f573fSAndroid Build Coastguard Worker bool ShouldInsertAfterHead(void* node) { 919*1b3f573fSAndroid Build Coastguard Worker #ifdef NDEBUG 920*1b3f573fSAndroid Build Coastguard Worker (void)node; 921*1b3f573fSAndroid Build Coastguard Worker return false; 922*1b3f573fSAndroid Build Coastguard Worker #else 923*1b3f573fSAndroid Build Coastguard Worker // Doing modulo with a prime mixes the bits more. 924*1b3f573fSAndroid Build Coastguard Worker return (reinterpret_cast<uintptr_t>(node) ^ seed_) % 13 > 6; 925*1b3f573fSAndroid Build Coastguard Worker #endif 926*1b3f573fSAndroid Build Coastguard Worker } 927*1b3f573fSAndroid Build Coastguard Worker 928*1b3f573fSAndroid Build Coastguard Worker // Helper for InsertUnique. Handles the case where bucket b is a 929*1b3f573fSAndroid Build Coastguard Worker // not-too-long linked list. 930*1b3f573fSAndroid Build Coastguard Worker iterator InsertUniqueInList(size_type b, Node* node) { 931*1b3f573fSAndroid Build Coastguard Worker if (table_[b] != nullptr && ShouldInsertAfterHead(node)) { 932*1b3f573fSAndroid Build Coastguard Worker Node* first = static_cast<Node*>(table_[b]); 933*1b3f573fSAndroid Build Coastguard Worker node->next = first->next; 934*1b3f573fSAndroid Build Coastguard Worker first->next = node; 935*1b3f573fSAndroid Build Coastguard Worker return iterator(node, this, b); 936*1b3f573fSAndroid Build Coastguard Worker } 937*1b3f573fSAndroid Build Coastguard Worker 938*1b3f573fSAndroid Build Coastguard Worker node->next = static_cast<Node*>(table_[b]); 939*1b3f573fSAndroid Build Coastguard Worker table_[b] = static_cast<void*>(node); 940*1b3f573fSAndroid Build Coastguard Worker return iterator(node, this, b); 941*1b3f573fSAndroid Build Coastguard Worker } 942*1b3f573fSAndroid Build Coastguard Worker 943*1b3f573fSAndroid Build Coastguard Worker // Helper for InsertUnique. Handles the case where bucket b points to a 944*1b3f573fSAndroid Build Coastguard Worker // Tree. 945*1b3f573fSAndroid Build Coastguard Worker iterator InsertUniqueInTree(size_type b, Node* node) { 946*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); 947*1b3f573fSAndroid Build Coastguard Worker // Maintain the invariant that node->next is null for all Nodes in Trees. 948*1b3f573fSAndroid Build Coastguard Worker node->next = nullptr; 949*1b3f573fSAndroid Build Coastguard Worker return iterator( 950*1b3f573fSAndroid Build Coastguard Worker static_cast<Tree*>(table_[b])->insert({node->kv.first, node}).first, 951*1b3f573fSAndroid Build Coastguard Worker this, b & ~static_cast<size_t>(1)); 952*1b3f573fSAndroid Build Coastguard Worker } 953*1b3f573fSAndroid Build Coastguard Worker 954*1b3f573fSAndroid Build Coastguard Worker // Returns whether it did resize. Currently this is only used when 955*1b3f573fSAndroid Build Coastguard Worker // num_elements_ increases, though it could be used in other situations. 956*1b3f573fSAndroid Build Coastguard Worker // It checks for load too low as well as load too high: because any number 957*1b3f573fSAndroid Build Coastguard Worker // of erases can occur between inserts, the load could be as low as 0 here. 958*1b3f573fSAndroid Build Coastguard Worker // Resizing to a lower size is not always helpful, but failing to do so can 959*1b3f573fSAndroid Build Coastguard Worker // destroy the expected big-O bounds for some operations. By having the 960*1b3f573fSAndroid Build Coastguard Worker // policy that sometimes we resize down as well as up, clients can easily 961*1b3f573fSAndroid Build Coastguard Worker // keep O(size()) = O(number of buckets) if they want that. 962*1b3f573fSAndroid Build Coastguard Worker bool ResizeIfLoadIsOutOfRange(size_type new_size) { 963*1b3f573fSAndroid Build Coastguard Worker const size_type kMaxMapLoadTimes16 = 12; // controls RAM vs CPU tradeoff 964*1b3f573fSAndroid Build Coastguard Worker const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16; 965*1b3f573fSAndroid Build Coastguard Worker const size_type lo_cutoff = hi_cutoff / 4; 966*1b3f573fSAndroid Build Coastguard Worker // We don't care how many elements are in trees. If a lot are, 967*1b3f573fSAndroid Build Coastguard Worker // we may resize even though there are many empty buckets. In 968*1b3f573fSAndroid Build Coastguard Worker // practice, this seems fine. 969*1b3f573fSAndroid Build Coastguard Worker if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) { 970*1b3f573fSAndroid Build Coastguard Worker if (num_buckets_ <= max_size() / 2) { 971*1b3f573fSAndroid Build Coastguard Worker Resize(num_buckets_ * 2); 972*1b3f573fSAndroid Build Coastguard Worker return true; 973*1b3f573fSAndroid Build Coastguard Worker } 974*1b3f573fSAndroid Build Coastguard Worker } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff && 975*1b3f573fSAndroid Build Coastguard Worker num_buckets_ > kMinTableSize)) { 976*1b3f573fSAndroid Build Coastguard Worker size_type lg2_of_size_reduction_factor = 1; 977*1b3f573fSAndroid Build Coastguard Worker // It's possible we want to shrink a lot here... size() could even be 0. 978*1b3f573fSAndroid Build Coastguard Worker // So, estimate how much to shrink by making sure we don't shrink so 979*1b3f573fSAndroid Build Coastguard Worker // much that we would need to grow the table after a few inserts. 980*1b3f573fSAndroid Build Coastguard Worker const size_type hypothetical_size = new_size * 5 / 4 + 1; 981*1b3f573fSAndroid Build Coastguard Worker while ((hypothetical_size << lg2_of_size_reduction_factor) < 982*1b3f573fSAndroid Build Coastguard Worker hi_cutoff) { 983*1b3f573fSAndroid Build Coastguard Worker ++lg2_of_size_reduction_factor; 984*1b3f573fSAndroid Build Coastguard Worker } 985*1b3f573fSAndroid Build Coastguard Worker size_type new_num_buckets = std::max<size_type>( 986*1b3f573fSAndroid Build Coastguard Worker kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor); 987*1b3f573fSAndroid Build Coastguard Worker if (new_num_buckets != num_buckets_) { 988*1b3f573fSAndroid Build Coastguard Worker Resize(new_num_buckets); 989*1b3f573fSAndroid Build Coastguard Worker return true; 990*1b3f573fSAndroid Build Coastguard Worker } 991*1b3f573fSAndroid Build Coastguard Worker } 992*1b3f573fSAndroid Build Coastguard Worker return false; 993*1b3f573fSAndroid Build Coastguard Worker } 994*1b3f573fSAndroid Build Coastguard Worker 995*1b3f573fSAndroid Build Coastguard Worker // Resize to the given number of buckets. 996*1b3f573fSAndroid Build Coastguard Worker void Resize(size_t new_num_buckets) { 997*1b3f573fSAndroid Build Coastguard Worker if (num_buckets_ == internal::kGlobalEmptyTableSize) { 998*1b3f573fSAndroid Build Coastguard Worker // This is the global empty array. 999*1b3f573fSAndroid Build Coastguard Worker // Just overwrite with a new one. No need to transfer or free anything. 1000*1b3f573fSAndroid Build Coastguard Worker num_buckets_ = index_of_first_non_null_ = kMinTableSize; 1001*1b3f573fSAndroid Build Coastguard Worker table_ = CreateEmptyTable(num_buckets_); 1002*1b3f573fSAndroid Build Coastguard Worker seed_ = Seed(); 1003*1b3f573fSAndroid Build Coastguard Worker return; 1004*1b3f573fSAndroid Build Coastguard Worker } 1005*1b3f573fSAndroid Build Coastguard Worker 1006*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize); 1007*1b3f573fSAndroid Build Coastguard Worker void** const old_table = table_; 1008*1b3f573fSAndroid Build Coastguard Worker const size_type old_table_size = num_buckets_; 1009*1b3f573fSAndroid Build Coastguard Worker num_buckets_ = new_num_buckets; 1010*1b3f573fSAndroid Build Coastguard Worker table_ = CreateEmptyTable(num_buckets_); 1011*1b3f573fSAndroid Build Coastguard Worker const size_type start = index_of_first_non_null_; 1012*1b3f573fSAndroid Build Coastguard Worker index_of_first_non_null_ = num_buckets_; 1013*1b3f573fSAndroid Build Coastguard Worker for (size_type i = start; i < old_table_size; i++) { 1014*1b3f573fSAndroid Build Coastguard Worker if (internal::TableEntryIsNonEmptyList(old_table, i)) { 1015*1b3f573fSAndroid Build Coastguard Worker TransferList(old_table, i); 1016*1b3f573fSAndroid Build Coastguard Worker } else if (internal::TableEntryIsTree(old_table, i)) { 1017*1b3f573fSAndroid Build Coastguard Worker TransferTree(old_table, i++); 1018*1b3f573fSAndroid Build Coastguard Worker } 1019*1b3f573fSAndroid Build Coastguard Worker } 1020*1b3f573fSAndroid Build Coastguard Worker Dealloc<void*>(old_table, old_table_size); 1021*1b3f573fSAndroid Build Coastguard Worker } 1022*1b3f573fSAndroid Build Coastguard Worker 1023*1b3f573fSAndroid Build Coastguard Worker void TransferList(void* const* table, size_type index) { 1024*1b3f573fSAndroid Build Coastguard Worker Node* node = static_cast<Node*>(table[index]); 1025*1b3f573fSAndroid Build Coastguard Worker do { 1026*1b3f573fSAndroid Build Coastguard Worker Node* next = node->next; 1027*1b3f573fSAndroid Build Coastguard Worker InsertUnique(BucketNumber(node->kv.first), node); 1028*1b3f573fSAndroid Build Coastguard Worker node = next; 1029*1b3f573fSAndroid Build Coastguard Worker } while (node != nullptr); 1030*1b3f573fSAndroid Build Coastguard Worker } 1031*1b3f573fSAndroid Build Coastguard Worker 1032*1b3f573fSAndroid Build Coastguard Worker void TransferTree(void* const* table, size_type index) { 1033*1b3f573fSAndroid Build Coastguard Worker Tree* tree = static_cast<Tree*>(table[index]); 1034*1b3f573fSAndroid Build Coastguard Worker typename Tree::iterator tree_it = tree->begin(); 1035*1b3f573fSAndroid Build Coastguard Worker do { 1036*1b3f573fSAndroid Build Coastguard Worker InsertUnique(BucketNumber(std::cref(tree_it->first).get()), 1037*1b3f573fSAndroid Build Coastguard Worker NodeFromTreeIterator(tree_it)); 1038*1b3f573fSAndroid Build Coastguard Worker } while (++tree_it != tree->end()); 1039*1b3f573fSAndroid Build Coastguard Worker DestroyTree(tree); 1040*1b3f573fSAndroid Build Coastguard Worker } 1041*1b3f573fSAndroid Build Coastguard Worker 1042*1b3f573fSAndroid Build Coastguard Worker Node* EraseFromLinkedList(Node* item, Node* head) { 1043*1b3f573fSAndroid Build Coastguard Worker if (head == item) { 1044*1b3f573fSAndroid Build Coastguard Worker return head->next; 1045*1b3f573fSAndroid Build Coastguard Worker } else { 1046*1b3f573fSAndroid Build Coastguard Worker head->next = EraseFromLinkedList(item, head->next); 1047*1b3f573fSAndroid Build Coastguard Worker return head; 1048*1b3f573fSAndroid Build Coastguard Worker } 1049*1b3f573fSAndroid Build Coastguard Worker } 1050*1b3f573fSAndroid Build Coastguard Worker 1051*1b3f573fSAndroid Build Coastguard Worker bool TableEntryIsEmpty(size_type b) const { 1052*1b3f573fSAndroid Build Coastguard Worker return internal::TableEntryIsEmpty(table_, b); 1053*1b3f573fSAndroid Build Coastguard Worker } 1054*1b3f573fSAndroid Build Coastguard Worker bool TableEntryIsNonEmptyList(size_type b) const { 1055*1b3f573fSAndroid Build Coastguard Worker return internal::TableEntryIsNonEmptyList(table_, b); 1056*1b3f573fSAndroid Build Coastguard Worker } 1057*1b3f573fSAndroid Build Coastguard Worker bool TableEntryIsTree(size_type b) const { 1058*1b3f573fSAndroid Build Coastguard Worker return internal::TableEntryIsTree(table_, b); 1059*1b3f573fSAndroid Build Coastguard Worker } 1060*1b3f573fSAndroid Build Coastguard Worker bool TableEntryIsList(size_type b) const { 1061*1b3f573fSAndroid Build Coastguard Worker return internal::TableEntryIsList(table_, b); 1062*1b3f573fSAndroid Build Coastguard Worker } 1063*1b3f573fSAndroid Build Coastguard Worker 1064*1b3f573fSAndroid Build Coastguard Worker void TreeConvert(size_type b) { 1065*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1)); 1066*1b3f573fSAndroid Build Coastguard Worker Tree* tree = 1067*1b3f573fSAndroid Build Coastguard Worker Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(), 1068*1b3f573fSAndroid Build Coastguard Worker typename Tree::allocator_type(alloc_)); 1069*1b3f573fSAndroid Build Coastguard Worker size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree); 1070*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(count, tree->size()); 1071*1b3f573fSAndroid Build Coastguard Worker table_[b] = table_[b ^ 1] = static_cast<void*>(tree); 1072*1b3f573fSAndroid Build Coastguard Worker } 1073*1b3f573fSAndroid Build Coastguard Worker 1074*1b3f573fSAndroid Build Coastguard Worker // Copy a linked list in the given bucket to a tree. 1075*1b3f573fSAndroid Build Coastguard Worker // Returns the number of things it copied. 1076*1b3f573fSAndroid Build Coastguard Worker size_type CopyListToTree(size_type b, Tree* tree) { 1077*1b3f573fSAndroid Build Coastguard Worker size_type count = 0; 1078*1b3f573fSAndroid Build Coastguard Worker Node* node = static_cast<Node*>(table_[b]); 1079*1b3f573fSAndroid Build Coastguard Worker while (node != nullptr) { 1080*1b3f573fSAndroid Build Coastguard Worker tree->insert({node->kv.first, node}); 1081*1b3f573fSAndroid Build Coastguard Worker ++count; 1082*1b3f573fSAndroid Build Coastguard Worker Node* next = node->next; 1083*1b3f573fSAndroid Build Coastguard Worker node->next = nullptr; 1084*1b3f573fSAndroid Build Coastguard Worker node = next; 1085*1b3f573fSAndroid Build Coastguard Worker } 1086*1b3f573fSAndroid Build Coastguard Worker return count; 1087*1b3f573fSAndroid Build Coastguard Worker } 1088*1b3f573fSAndroid Build Coastguard Worker 1089*1b3f573fSAndroid Build Coastguard Worker // Return whether table_[b] is a linked list that seems awfully long. 1090*1b3f573fSAndroid Build Coastguard Worker // Requires table_[b] to point to a non-empty linked list. 1091*1b3f573fSAndroid Build Coastguard Worker bool TableEntryIsTooLong(size_type b) { 1092*1b3f573fSAndroid Build Coastguard Worker const size_type kMaxLength = 8; 1093*1b3f573fSAndroid Build Coastguard Worker size_type count = 0; 1094*1b3f573fSAndroid Build Coastguard Worker Node* node = static_cast<Node*>(table_[b]); 1095*1b3f573fSAndroid Build Coastguard Worker do { 1096*1b3f573fSAndroid Build Coastguard Worker ++count; 1097*1b3f573fSAndroid Build Coastguard Worker node = node->next; 1098*1b3f573fSAndroid Build Coastguard Worker } while (node != nullptr); 1099*1b3f573fSAndroid Build Coastguard Worker // Invariant: no linked list ever is more than kMaxLength in length. 1100*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_LE(count, kMaxLength); 1101*1b3f573fSAndroid Build Coastguard Worker return count >= kMaxLength; 1102*1b3f573fSAndroid Build Coastguard Worker } 1103*1b3f573fSAndroid Build Coastguard Worker 1104*1b3f573fSAndroid Build Coastguard Worker template <typename K> 1105*1b3f573fSAndroid Build Coastguard Worker size_type BucketNumber(const K& k) const { 1106*1b3f573fSAndroid Build Coastguard Worker // We xor the hash value against the random seed so that we effectively 1107*1b3f573fSAndroid Build Coastguard Worker // have a random hash function. 1108*1b3f573fSAndroid Build Coastguard Worker uint64_t h = hash_function()(k) ^ seed_; 1109*1b3f573fSAndroid Build Coastguard Worker 1110*1b3f573fSAndroid Build Coastguard Worker // We use the multiplication method to determine the bucket number from 1111*1b3f573fSAndroid Build Coastguard Worker // the hash value. The constant kPhi (suggested by Knuth) is roughly 1112*1b3f573fSAndroid Build Coastguard Worker // (sqrt(5) - 1) / 2 * 2^64. 1113*1b3f573fSAndroid Build Coastguard Worker constexpr uint64_t kPhi = uint64_t{0x9e3779b97f4a7c15}; 1114*1b3f573fSAndroid Build Coastguard Worker return (internal::MultiplyWithOverflow(kPhi, h) >> 32) & 1115*1b3f573fSAndroid Build Coastguard Worker (num_buckets_ - 1); 1116*1b3f573fSAndroid Build Coastguard Worker } 1117*1b3f573fSAndroid Build Coastguard Worker 1118*1b3f573fSAndroid Build Coastguard Worker // Return a power of two no less than max(kMinTableSize, n). 1119*1b3f573fSAndroid Build Coastguard Worker // Assumes either n < kMinTableSize or n is a power of two. 1120*1b3f573fSAndroid Build Coastguard Worker size_type TableSize(size_type n) { 1121*1b3f573fSAndroid Build Coastguard Worker return n < static_cast<size_type>(kMinTableSize) 1122*1b3f573fSAndroid Build Coastguard Worker ? static_cast<size_type>(kMinTableSize) 1123*1b3f573fSAndroid Build Coastguard Worker : n; 1124*1b3f573fSAndroid Build Coastguard Worker } 1125*1b3f573fSAndroid Build Coastguard Worker 1126*1b3f573fSAndroid Build Coastguard Worker // Use alloc_ to allocate an array of n objects of type U. 1127*1b3f573fSAndroid Build Coastguard Worker template <typename U> 1128*1b3f573fSAndroid Build Coastguard Worker U* Alloc(size_type n) { 1129*1b3f573fSAndroid Build Coastguard Worker using alloc_type = typename Allocator::template rebind<U>::other; 1130*1b3f573fSAndroid Build Coastguard Worker return alloc_type(alloc_).allocate(n); 1131*1b3f573fSAndroid Build Coastguard Worker } 1132*1b3f573fSAndroid Build Coastguard Worker 1133*1b3f573fSAndroid Build Coastguard Worker // Use alloc_ to deallocate an array of n objects of type U. 1134*1b3f573fSAndroid Build Coastguard Worker template <typename U> 1135*1b3f573fSAndroid Build Coastguard Worker void Dealloc(U* t, size_type n) { 1136*1b3f573fSAndroid Build Coastguard Worker using alloc_type = typename Allocator::template rebind<U>::other; 1137*1b3f573fSAndroid Build Coastguard Worker alloc_type(alloc_).deallocate(t, n); 1138*1b3f573fSAndroid Build Coastguard Worker } 1139*1b3f573fSAndroid Build Coastguard Worker 1140*1b3f573fSAndroid Build Coastguard Worker void DestroyNode(Node* node) { 1141*1b3f573fSAndroid Build Coastguard Worker if (alloc_.arena() == nullptr) { 1142*1b3f573fSAndroid Build Coastguard Worker delete node; 1143*1b3f573fSAndroid Build Coastguard Worker } 1144*1b3f573fSAndroid Build Coastguard Worker } 1145*1b3f573fSAndroid Build Coastguard Worker 1146*1b3f573fSAndroid Build Coastguard Worker void DestroyTree(Tree* tree) { 1147*1b3f573fSAndroid Build Coastguard Worker if (alloc_.arena() == nullptr) { 1148*1b3f573fSAndroid Build Coastguard Worker delete tree; 1149*1b3f573fSAndroid Build Coastguard Worker } 1150*1b3f573fSAndroid Build Coastguard Worker } 1151*1b3f573fSAndroid Build Coastguard Worker 1152*1b3f573fSAndroid Build Coastguard Worker void** CreateEmptyTable(size_type n) { 1153*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK(n >= kMinTableSize); 1154*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DCHECK_EQ(n & (n - 1), 0u); 1155*1b3f573fSAndroid Build Coastguard Worker void** result = Alloc<void*>(n); 1156*1b3f573fSAndroid Build Coastguard Worker memset(result, 0, n * sizeof(result[0])); 1157*1b3f573fSAndroid Build Coastguard Worker return result; 1158*1b3f573fSAndroid Build Coastguard Worker } 1159*1b3f573fSAndroid Build Coastguard Worker 1160*1b3f573fSAndroid Build Coastguard Worker // Return a randomish value. 1161*1b3f573fSAndroid Build Coastguard Worker size_type Seed() const { 1162*1b3f573fSAndroid Build Coastguard Worker // We get a little bit of randomness from the address of the map. The 1163*1b3f573fSAndroid Build Coastguard Worker // lower bits are not very random, due to alignment, so we discard them 1164*1b3f573fSAndroid Build Coastguard Worker // and shift the higher bits into their place. 1165*1b3f573fSAndroid Build Coastguard Worker size_type s = reinterpret_cast<uintptr_t>(this) >> 4; 1166*1b3f573fSAndroid Build Coastguard Worker #if !defined(GOOGLE_PROTOBUF_NO_RDTSC) 1167*1b3f573fSAndroid Build Coastguard Worker #if defined(__APPLE__) 1168*1b3f573fSAndroid Build Coastguard Worker // Use a commpage-based fast time function on Apple environments (MacOS, 1169*1b3f573fSAndroid Build Coastguard Worker // iOS, tvOS, watchOS, etc). 1170*1b3f573fSAndroid Build Coastguard Worker s += mach_absolute_time(); 1171*1b3f573fSAndroid Build Coastguard Worker #elif defined(__x86_64__) && defined(__GNUC__) 1172*1b3f573fSAndroid Build Coastguard Worker uint32_t hi, lo; 1173*1b3f573fSAndroid Build Coastguard Worker asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); 1174*1b3f573fSAndroid Build Coastguard Worker s += ((static_cast<uint64_t>(hi) << 32) | lo); 1175*1b3f573fSAndroid Build Coastguard Worker #elif defined(__aarch64__) && defined(__GNUC__) 1176*1b3f573fSAndroid Build Coastguard Worker // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the 1177*1b3f573fSAndroid Build Coastguard Worker // system timer. It runs at a different frequency than the CPU's, but is 1178*1b3f573fSAndroid Build Coastguard Worker // the best source of time-based entropy we get. 1179*1b3f573fSAndroid Build Coastguard Worker uint64_t virtual_timer_value; 1180*1b3f573fSAndroid Build Coastguard Worker asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); 1181*1b3f573fSAndroid Build Coastguard Worker s += virtual_timer_value; 1182*1b3f573fSAndroid Build Coastguard Worker #endif 1183*1b3f573fSAndroid Build Coastguard Worker #endif // !defined(GOOGLE_PROTOBUF_NO_RDTSC) 1184*1b3f573fSAndroid Build Coastguard Worker return s; 1185*1b3f573fSAndroid Build Coastguard Worker } 1186*1b3f573fSAndroid Build Coastguard Worker 1187*1b3f573fSAndroid Build Coastguard Worker friend class Arena; 1188*1b3f573fSAndroid Build Coastguard Worker using InternalArenaConstructable_ = void; 1189*1b3f573fSAndroid Build Coastguard Worker using DestructorSkippable_ = void; 1190*1b3f573fSAndroid Build Coastguard Worker 1191*1b3f573fSAndroid Build Coastguard Worker size_type num_elements_; 1192*1b3f573fSAndroid Build Coastguard Worker size_type num_buckets_; 1193*1b3f573fSAndroid Build Coastguard Worker size_type seed_; 1194*1b3f573fSAndroid Build Coastguard Worker size_type index_of_first_non_null_; 1195*1b3f573fSAndroid Build Coastguard Worker void** table_; // an array with num_buckets_ entries 1196*1b3f573fSAndroid Build Coastguard Worker Allocator alloc_; 1197*1b3f573fSAndroid Build Coastguard Worker GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); 1198*1b3f573fSAndroid Build Coastguard Worker }; // end of class InnerMap 1199*1b3f573fSAndroid Build Coastguard Worker 1200*1b3f573fSAndroid Build Coastguard Worker template <typename LookupKey> 1201*1b3f573fSAndroid Build Coastguard Worker using key_arg = typename internal::TransparentSupport< 1202*1b3f573fSAndroid Build Coastguard Worker key_type>::template key_arg<LookupKey>; 1203*1b3f573fSAndroid Build Coastguard Worker 1204*1b3f573fSAndroid Build Coastguard Worker public: 1205*1b3f573fSAndroid Build Coastguard Worker // Iterators 1206*1b3f573fSAndroid Build Coastguard Worker class const_iterator { 1207*1b3f573fSAndroid Build Coastguard Worker using InnerIt = typename InnerMap::const_iterator; 1208*1b3f573fSAndroid Build Coastguard Worker 1209*1b3f573fSAndroid Build Coastguard Worker public: 1210*1b3f573fSAndroid Build Coastguard Worker using iterator_category = std::forward_iterator_tag; 1211*1b3f573fSAndroid Build Coastguard Worker using value_type = typename Map::value_type; 1212*1b3f573fSAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 1213*1b3f573fSAndroid Build Coastguard Worker using pointer = const value_type*; 1214*1b3f573fSAndroid Build Coastguard Worker using reference = const value_type&; 1215*1b3f573fSAndroid Build Coastguard Worker 1216*1b3f573fSAndroid Build Coastguard Worker const_iterator() {} 1217*1b3f573fSAndroid Build Coastguard Worker explicit const_iterator(const InnerIt& it) : it_(it) {} 1218*1b3f573fSAndroid Build Coastguard Worker 1219*1b3f573fSAndroid Build Coastguard Worker const_reference operator*() const { return *it_; } 1220*1b3f573fSAndroid Build Coastguard Worker const_pointer operator->() const { return &(operator*()); } 1221*1b3f573fSAndroid Build Coastguard Worker 1222*1b3f573fSAndroid Build Coastguard Worker const_iterator& operator++() { 1223*1b3f573fSAndroid Build Coastguard Worker ++it_; 1224*1b3f573fSAndroid Build Coastguard Worker return *this; 1225*1b3f573fSAndroid Build Coastguard Worker } 1226*1b3f573fSAndroid Build Coastguard Worker const_iterator operator++(int) { return const_iterator(it_++); } 1227*1b3f573fSAndroid Build Coastguard Worker 1228*1b3f573fSAndroid Build Coastguard Worker friend bool operator==(const const_iterator& a, const const_iterator& b) { 1229*1b3f573fSAndroid Build Coastguard Worker return a.it_ == b.it_; 1230*1b3f573fSAndroid Build Coastguard Worker } 1231*1b3f573fSAndroid Build Coastguard Worker friend bool operator!=(const const_iterator& a, const const_iterator& b) { 1232*1b3f573fSAndroid Build Coastguard Worker return !(a == b); 1233*1b3f573fSAndroid Build Coastguard Worker } 1234*1b3f573fSAndroid Build Coastguard Worker 1235*1b3f573fSAndroid Build Coastguard Worker private: 1236*1b3f573fSAndroid Build Coastguard Worker InnerIt it_; 1237*1b3f573fSAndroid Build Coastguard Worker }; 1238*1b3f573fSAndroid Build Coastguard Worker 1239*1b3f573fSAndroid Build Coastguard Worker class iterator { 1240*1b3f573fSAndroid Build Coastguard Worker using InnerIt = typename InnerMap::iterator; 1241*1b3f573fSAndroid Build Coastguard Worker 1242*1b3f573fSAndroid Build Coastguard Worker public: 1243*1b3f573fSAndroid Build Coastguard Worker using iterator_category = std::forward_iterator_tag; 1244*1b3f573fSAndroid Build Coastguard Worker using value_type = typename Map::value_type; 1245*1b3f573fSAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 1246*1b3f573fSAndroid Build Coastguard Worker using pointer = value_type*; 1247*1b3f573fSAndroid Build Coastguard Worker using reference = value_type&; 1248*1b3f573fSAndroid Build Coastguard Worker 1249*1b3f573fSAndroid Build Coastguard Worker iterator() {} 1250*1b3f573fSAndroid Build Coastguard Worker explicit iterator(const InnerIt& it) : it_(it) {} 1251*1b3f573fSAndroid Build Coastguard Worker 1252*1b3f573fSAndroid Build Coastguard Worker reference operator*() const { return *it_; } 1253*1b3f573fSAndroid Build Coastguard Worker pointer operator->() const { return &(operator*()); } 1254*1b3f573fSAndroid Build Coastguard Worker 1255*1b3f573fSAndroid Build Coastguard Worker iterator& operator++() { 1256*1b3f573fSAndroid Build Coastguard Worker ++it_; 1257*1b3f573fSAndroid Build Coastguard Worker return *this; 1258*1b3f573fSAndroid Build Coastguard Worker } 1259*1b3f573fSAndroid Build Coastguard Worker iterator operator++(int) { return iterator(it_++); } 1260*1b3f573fSAndroid Build Coastguard Worker 1261*1b3f573fSAndroid Build Coastguard Worker // Allow implicit conversion to const_iterator. 1262*1b3f573fSAndroid Build Coastguard Worker operator const_iterator() const { // NOLINT(runtime/explicit) 1263*1b3f573fSAndroid Build Coastguard Worker return const_iterator(typename InnerMap::const_iterator(it_)); 1264*1b3f573fSAndroid Build Coastguard Worker } 1265*1b3f573fSAndroid Build Coastguard Worker 1266*1b3f573fSAndroid Build Coastguard Worker friend bool operator==(const iterator& a, const iterator& b) { 1267*1b3f573fSAndroid Build Coastguard Worker return a.it_ == b.it_; 1268*1b3f573fSAndroid Build Coastguard Worker } 1269*1b3f573fSAndroid Build Coastguard Worker friend bool operator!=(const iterator& a, const iterator& b) { 1270*1b3f573fSAndroid Build Coastguard Worker return !(a == b); 1271*1b3f573fSAndroid Build Coastguard Worker } 1272*1b3f573fSAndroid Build Coastguard Worker 1273*1b3f573fSAndroid Build Coastguard Worker private: 1274*1b3f573fSAndroid Build Coastguard Worker friend class Map; 1275*1b3f573fSAndroid Build Coastguard Worker 1276*1b3f573fSAndroid Build Coastguard Worker InnerIt it_; 1277*1b3f573fSAndroid Build Coastguard Worker }; 1278*1b3f573fSAndroid Build Coastguard Worker 1279*1b3f573fSAndroid Build Coastguard Worker iterator begin() { return iterator(elements_.begin()); } 1280*1b3f573fSAndroid Build Coastguard Worker iterator end() { return iterator(elements_.end()); } 1281*1b3f573fSAndroid Build Coastguard Worker const_iterator begin() const { return const_iterator(elements_.begin()); } 1282*1b3f573fSAndroid Build Coastguard Worker const_iterator end() const { return const_iterator(elements_.end()); } 1283*1b3f573fSAndroid Build Coastguard Worker const_iterator cbegin() const { return begin(); } 1284*1b3f573fSAndroid Build Coastguard Worker const_iterator cend() const { return end(); } 1285*1b3f573fSAndroid Build Coastguard Worker 1286*1b3f573fSAndroid Build Coastguard Worker // Capacity 1287*1b3f573fSAndroid Build Coastguard Worker size_type size() const { return elements_.size(); } 1288*1b3f573fSAndroid Build Coastguard Worker bool empty() const { return size() == 0; } 1289*1b3f573fSAndroid Build Coastguard Worker 1290*1b3f573fSAndroid Build Coastguard Worker // Element access 1291*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1292*1b3f573fSAndroid Build Coastguard Worker T& operator[](const key_arg<K>& key) { 1293*1b3f573fSAndroid Build Coastguard Worker return elements_[key].second; 1294*1b3f573fSAndroid Build Coastguard Worker } 1295*1b3f573fSAndroid Build Coastguard Worker template < 1296*1b3f573fSAndroid Build Coastguard Worker typename K = key_type, 1297*1b3f573fSAndroid Build Coastguard Worker // Disable for integral types to reduce code bloat. 1298*1b3f573fSAndroid Build Coastguard Worker typename = typename std::enable_if<!std::is_integral<K>::value>::type> 1299*1b3f573fSAndroid Build Coastguard Worker T& operator[](key_arg<K>&& key) { 1300*1b3f573fSAndroid Build Coastguard Worker return elements_[std::forward<K>(key)].second; 1301*1b3f573fSAndroid Build Coastguard Worker } 1302*1b3f573fSAndroid Build Coastguard Worker 1303*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1304*1b3f573fSAndroid Build Coastguard Worker const T& at(const key_arg<K>& key) const { 1305*1b3f573fSAndroid Build Coastguard Worker const_iterator it = find(key); 1306*1b3f573fSAndroid Build Coastguard Worker GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key); 1307*1b3f573fSAndroid Build Coastguard Worker return it->second; 1308*1b3f573fSAndroid Build Coastguard Worker } 1309*1b3f573fSAndroid Build Coastguard Worker 1310*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1311*1b3f573fSAndroid Build Coastguard Worker T& at(const key_arg<K>& key) { 1312*1b3f573fSAndroid Build Coastguard Worker iterator it = find(key); 1313*1b3f573fSAndroid Build Coastguard Worker GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key); 1314*1b3f573fSAndroid Build Coastguard Worker return it->second; 1315*1b3f573fSAndroid Build Coastguard Worker } 1316*1b3f573fSAndroid Build Coastguard Worker 1317*1b3f573fSAndroid Build Coastguard Worker // Lookup 1318*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1319*1b3f573fSAndroid Build Coastguard Worker size_type count(const key_arg<K>& key) const { 1320*1b3f573fSAndroid Build Coastguard Worker return find(key) == end() ? 0 : 1; 1321*1b3f573fSAndroid Build Coastguard Worker } 1322*1b3f573fSAndroid Build Coastguard Worker 1323*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1324*1b3f573fSAndroid Build Coastguard Worker const_iterator find(const key_arg<K>& key) const { 1325*1b3f573fSAndroid Build Coastguard Worker return const_iterator(elements_.find(key)); 1326*1b3f573fSAndroid Build Coastguard Worker } 1327*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1328*1b3f573fSAndroid Build Coastguard Worker iterator find(const key_arg<K>& key) { 1329*1b3f573fSAndroid Build Coastguard Worker return iterator(elements_.find(key)); 1330*1b3f573fSAndroid Build Coastguard Worker } 1331*1b3f573fSAndroid Build Coastguard Worker 1332*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1333*1b3f573fSAndroid Build Coastguard Worker bool contains(const key_arg<K>& key) const { 1334*1b3f573fSAndroid Build Coastguard Worker return find(key) != end(); 1335*1b3f573fSAndroid Build Coastguard Worker } 1336*1b3f573fSAndroid Build Coastguard Worker 1337*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1338*1b3f573fSAndroid Build Coastguard Worker std::pair<const_iterator, const_iterator> equal_range( 1339*1b3f573fSAndroid Build Coastguard Worker const key_arg<K>& key) const { 1340*1b3f573fSAndroid Build Coastguard Worker const_iterator it = find(key); 1341*1b3f573fSAndroid Build Coastguard Worker if (it == end()) { 1342*1b3f573fSAndroid Build Coastguard Worker return std::pair<const_iterator, const_iterator>(it, it); 1343*1b3f573fSAndroid Build Coastguard Worker } else { 1344*1b3f573fSAndroid Build Coastguard Worker const_iterator begin = it++; 1345*1b3f573fSAndroid Build Coastguard Worker return std::pair<const_iterator, const_iterator>(begin, it); 1346*1b3f573fSAndroid Build Coastguard Worker } 1347*1b3f573fSAndroid Build Coastguard Worker } 1348*1b3f573fSAndroid Build Coastguard Worker 1349*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1350*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, iterator> equal_range(const key_arg<K>& key) { 1351*1b3f573fSAndroid Build Coastguard Worker iterator it = find(key); 1352*1b3f573fSAndroid Build Coastguard Worker if (it == end()) { 1353*1b3f573fSAndroid Build Coastguard Worker return std::pair<iterator, iterator>(it, it); 1354*1b3f573fSAndroid Build Coastguard Worker } else { 1355*1b3f573fSAndroid Build Coastguard Worker iterator begin = it++; 1356*1b3f573fSAndroid Build Coastguard Worker return std::pair<iterator, iterator>(begin, it); 1357*1b3f573fSAndroid Build Coastguard Worker } 1358*1b3f573fSAndroid Build Coastguard Worker } 1359*1b3f573fSAndroid Build Coastguard Worker 1360*1b3f573fSAndroid Build Coastguard Worker // insert 1361*1b3f573fSAndroid Build Coastguard Worker template <typename K, typename... Args> 1362*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) { 1363*1b3f573fSAndroid Build Coastguard Worker auto p = 1364*1b3f573fSAndroid Build Coastguard Worker elements_.try_emplace(std::forward<K>(k), std::forward<Args>(args)...); 1365*1b3f573fSAndroid Build Coastguard Worker return std::pair<iterator, bool>(iterator(p.first), p.second); 1366*1b3f573fSAndroid Build Coastguard Worker } 1367*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> insert(const value_type& value) { 1368*1b3f573fSAndroid Build Coastguard Worker return try_emplace(value.first, value.second); 1369*1b3f573fSAndroid Build Coastguard Worker } 1370*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> insert(value_type&& value) { 1371*1b3f573fSAndroid Build Coastguard Worker return try_emplace(value.first, std::move(value.second)); 1372*1b3f573fSAndroid Build Coastguard Worker } 1373*1b3f573fSAndroid Build Coastguard Worker template <typename... Args> 1374*1b3f573fSAndroid Build Coastguard Worker std::pair<iterator, bool> emplace(Args&&... args) { 1375*1b3f573fSAndroid Build Coastguard Worker return insert(value_type(std::forward<Args>(args)...)); 1376*1b3f573fSAndroid Build Coastguard Worker } 1377*1b3f573fSAndroid Build Coastguard Worker template <class InputIt> 1378*1b3f573fSAndroid Build Coastguard Worker void insert(InputIt first, InputIt last) { 1379*1b3f573fSAndroid Build Coastguard Worker for (; first != last; ++first) { 1380*1b3f573fSAndroid Build Coastguard Worker try_emplace(first->first, first->second); 1381*1b3f573fSAndroid Build Coastguard Worker } 1382*1b3f573fSAndroid Build Coastguard Worker } 1383*1b3f573fSAndroid Build Coastguard Worker void insert(std::initializer_list<value_type> values) { 1384*1b3f573fSAndroid Build Coastguard Worker insert(values.begin(), values.end()); 1385*1b3f573fSAndroid Build Coastguard Worker } 1386*1b3f573fSAndroid Build Coastguard Worker 1387*1b3f573fSAndroid Build Coastguard Worker // Erase and clear 1388*1b3f573fSAndroid Build Coastguard Worker template <typename K = key_type> 1389*1b3f573fSAndroid Build Coastguard Worker size_type erase(const key_arg<K>& key) { 1390*1b3f573fSAndroid Build Coastguard Worker iterator it = find(key); 1391*1b3f573fSAndroid Build Coastguard Worker if (it == end()) { 1392*1b3f573fSAndroid Build Coastguard Worker return 0; 1393*1b3f573fSAndroid Build Coastguard Worker } else { 1394*1b3f573fSAndroid Build Coastguard Worker erase(it); 1395*1b3f573fSAndroid Build Coastguard Worker return 1; 1396*1b3f573fSAndroid Build Coastguard Worker } 1397*1b3f573fSAndroid Build Coastguard Worker } 1398*1b3f573fSAndroid Build Coastguard Worker iterator erase(iterator pos) { 1399*1b3f573fSAndroid Build Coastguard Worker iterator i = pos++; 1400*1b3f573fSAndroid Build Coastguard Worker elements_.erase(i.it_); 1401*1b3f573fSAndroid Build Coastguard Worker return pos; 1402*1b3f573fSAndroid Build Coastguard Worker } 1403*1b3f573fSAndroid Build Coastguard Worker void erase(iterator first, iterator last) { 1404*1b3f573fSAndroid Build Coastguard Worker while (first != last) { 1405*1b3f573fSAndroid Build Coastguard Worker first = erase(first); 1406*1b3f573fSAndroid Build Coastguard Worker } 1407*1b3f573fSAndroid Build Coastguard Worker } 1408*1b3f573fSAndroid Build Coastguard Worker void clear() { elements_.clear(); } 1409*1b3f573fSAndroid Build Coastguard Worker 1410*1b3f573fSAndroid Build Coastguard Worker // Assign 1411*1b3f573fSAndroid Build Coastguard Worker Map& operator=(const Map& other) { 1412*1b3f573fSAndroid Build Coastguard Worker if (this != &other) { 1413*1b3f573fSAndroid Build Coastguard Worker clear(); 1414*1b3f573fSAndroid Build Coastguard Worker insert(other.begin(), other.end()); 1415*1b3f573fSAndroid Build Coastguard Worker } 1416*1b3f573fSAndroid Build Coastguard Worker return *this; 1417*1b3f573fSAndroid Build Coastguard Worker } 1418*1b3f573fSAndroid Build Coastguard Worker 1419*1b3f573fSAndroid Build Coastguard Worker void swap(Map& other) { 1420*1b3f573fSAndroid Build Coastguard Worker if (arena() == other.arena()) { 1421*1b3f573fSAndroid Build Coastguard Worker InternalSwap(other); 1422*1b3f573fSAndroid Build Coastguard Worker } else { 1423*1b3f573fSAndroid Build Coastguard Worker // TODO(zuguang): optimize this. The temporary copy can be allocated 1424*1b3f573fSAndroid Build Coastguard Worker // in the same arena as the other message, and the "other = copy" can 1425*1b3f573fSAndroid Build Coastguard Worker // be replaced with the fast-path swap above. 1426*1b3f573fSAndroid Build Coastguard Worker Map copy = *this; 1427*1b3f573fSAndroid Build Coastguard Worker *this = other; 1428*1b3f573fSAndroid Build Coastguard Worker other = copy; 1429*1b3f573fSAndroid Build Coastguard Worker } 1430*1b3f573fSAndroid Build Coastguard Worker } 1431*1b3f573fSAndroid Build Coastguard Worker 1432*1b3f573fSAndroid Build Coastguard Worker void InternalSwap(Map& other) { elements_.Swap(&other.elements_); } 1433*1b3f573fSAndroid Build Coastguard Worker 1434*1b3f573fSAndroid Build Coastguard Worker // Access to hasher. Currently this returns a copy, but it may 1435*1b3f573fSAndroid Build Coastguard Worker // be modified to return a const reference in the future. 1436*1b3f573fSAndroid Build Coastguard Worker hasher hash_function() const { return elements_.hash_function(); } 1437*1b3f573fSAndroid Build Coastguard Worker 1438*1b3f573fSAndroid Build Coastguard Worker size_t SpaceUsedExcludingSelfLong() const { 1439*1b3f573fSAndroid Build Coastguard Worker if (empty()) return 0; 1440*1b3f573fSAndroid Build Coastguard Worker return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this); 1441*1b3f573fSAndroid Build Coastguard Worker } 1442*1b3f573fSAndroid Build Coastguard Worker 1443*1b3f573fSAndroid Build Coastguard Worker private: 1444*1b3f573fSAndroid Build Coastguard Worker Arena* arena() const { return elements_.arena(); } 1445*1b3f573fSAndroid Build Coastguard Worker InnerMap elements_; 1446*1b3f573fSAndroid Build Coastguard Worker 1447*1b3f573fSAndroid Build Coastguard Worker friend class Arena; 1448*1b3f573fSAndroid Build Coastguard Worker using InternalArenaConstructable_ = void; 1449*1b3f573fSAndroid Build Coastguard Worker using DestructorSkippable_ = void; 1450*1b3f573fSAndroid Build Coastguard Worker template <typename Derived, typename K, typename V, 1451*1b3f573fSAndroid Build Coastguard Worker internal::WireFormatLite::FieldType key_wire_type, 1452*1b3f573fSAndroid Build Coastguard Worker internal::WireFormatLite::FieldType value_wire_type> 1453*1b3f573fSAndroid Build Coastguard Worker friend class internal::MapFieldLite; 1454*1b3f573fSAndroid Build Coastguard Worker }; 1455*1b3f573fSAndroid Build Coastguard Worker 1456*1b3f573fSAndroid Build Coastguard Worker } // namespace protobuf 1457*1b3f573fSAndroid Build Coastguard Worker } // namespace google 1458*1b3f573fSAndroid Build Coastguard Worker 1459*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/port_undef.inc> 1460*1b3f573fSAndroid Build Coastguard Worker 1461*1b3f573fSAndroid Build Coastguard Worker #endif // GOOGLE_PROTOBUF_MAP_H__ 1462