1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 #ifndef GOOGLE_PROTOBUF_MAP_H__ 32 #define GOOGLE_PROTOBUF_MAP_H__ 33 34 #include <google/protobuf/stubs/hash.h> 35 #include <iterator> 36 #include <limits> // To support Visual Studio 2008 37 #include <set> 38 #include <utility> 39 40 #include <google/protobuf/stubs/common.h> 41 #include <google/protobuf/arena.h> 42 #include <google/protobuf/generated_enum_util.h> 43 #include <google/protobuf/map_type_handler.h> 44 #include <google/protobuf/message.h> 45 #include <google/protobuf/descriptor.h> 46 #if __cpp_exceptions && LANG_CXX11 47 #include <random> 48 #endif 49 50 namespace google { 51 namespace protobuf { 52 53 // The Map and MapIterator types are provided by this header file. 54 // Please avoid using other types defined here, unless they are public 55 // types within Map or MapIterator, such as Map::value_type. 56 template <typename Key, typename T> 57 class Map; 58 59 class MapIterator; 60 61 template <typename Enum> struct is_proto_enum; 62 63 namespace internal { 64 template <typename Key, typename T, 65 WireFormatLite::FieldType key_wire_type, 66 WireFormatLite::FieldType value_wire_type, 67 int default_enum_value> 68 class MapFieldLite; 69 70 template <typename Key, typename T, 71 WireFormatLite::FieldType key_wire_type, 72 WireFormatLite::FieldType value_wire_type, 73 int default_enum_value> 74 class MapField; 75 76 template <typename Key, typename T> 77 class TypeDefinedMapFieldBase; 78 79 class DynamicMapField; 80 81 class GeneratedMessageReflection; 82 } // namespace internal 83 84 #define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ 85 if (type() != EXPECTEDTYPE) { \ 86 GOOGLE_LOG(FATAL) \ 87 << "Protocol Buffer map usage error:\n" \ 88 << METHOD << " type does not match\n" \ 89 << " Expected : " \ 90 << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ 91 << " Actual : " \ 92 << FieldDescriptor::CppTypeName(type()); \ 93 } 94 95 // MapKey is an union type for representing any possible 96 // map key. 97 class LIBPROTOBUF_EXPORT MapKey { 98 public: MapKey()99 MapKey() : type_(0) { 100 } MapKey(const MapKey & other)101 MapKey(const MapKey& other) : type_(0) { 102 CopyFrom(other); 103 } 104 ~MapKey()105 ~MapKey() { 106 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 107 delete val_.string_value_; 108 } 109 } 110 type()111 FieldDescriptor::CppType type() const { 112 if (type_ == 0) { 113 GOOGLE_LOG(FATAL) 114 << "Protocol Buffer map usage error:\n" 115 << "MapKey::type MapKey is not initialized. " 116 << "Call set methods to initialize MapKey."; 117 } 118 return (FieldDescriptor::CppType)type_; 119 } 120 SetInt64Value(int64 value)121 void SetInt64Value(int64 value) { 122 SetType(FieldDescriptor::CPPTYPE_INT64); 123 val_.int64_value_ = value; 124 } SetUInt64Value(uint64 value)125 void SetUInt64Value(uint64 value) { 126 SetType(FieldDescriptor::CPPTYPE_UINT64); 127 val_.uint64_value_ = value; 128 } SetInt32Value(int32 value)129 void SetInt32Value(int32 value) { 130 SetType(FieldDescriptor::CPPTYPE_INT32); 131 val_.int32_value_ = value; 132 } SetUInt32Value(uint32 value)133 void SetUInt32Value(uint32 value) { 134 SetType(FieldDescriptor::CPPTYPE_UINT32); 135 val_.uint32_value_ = value; 136 } SetBoolValue(bool value)137 void SetBoolValue(bool value) { 138 SetType(FieldDescriptor::CPPTYPE_BOOL); 139 val_.bool_value_ = value; 140 } SetStringValue(const string & val)141 void SetStringValue(const string& val) { 142 SetType(FieldDescriptor::CPPTYPE_STRING); 143 *val_.string_value_ = val; 144 } 145 GetInt64Value()146 int64 GetInt64Value() const { 147 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, 148 "MapKey::GetInt64Value"); 149 return val_.int64_value_; 150 } GetUInt64Value()151 uint64 GetUInt64Value() const { 152 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, 153 "MapKey::GetUInt64Value"); 154 return val_.uint64_value_; 155 } GetInt32Value()156 int32 GetInt32Value() const { 157 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, 158 "MapKey::GetInt32Value"); 159 return val_.int32_value_; 160 } GetUInt32Value()161 uint32 GetUInt32Value() const { 162 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, 163 "MapKey::GetUInt32Value"); 164 return val_.uint32_value_; 165 } GetBoolValue()166 bool GetBoolValue() const { 167 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, 168 "MapKey::GetBoolValue"); 169 return val_.bool_value_; 170 } GetStringValue()171 const string& GetStringValue() const { 172 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, 173 "MapKey::GetStringValue"); 174 return *val_.string_value_; 175 } 176 177 bool operator<(const MapKey& other) const { 178 if (type_ != other.type_) { 179 // We could define a total order that handles this case, but 180 // there currently no need. So, for now, fail. 181 GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; 182 } 183 switch (type()) { 184 case FieldDescriptor::CPPTYPE_DOUBLE: 185 case FieldDescriptor::CPPTYPE_FLOAT: 186 case FieldDescriptor::CPPTYPE_ENUM: 187 case FieldDescriptor::CPPTYPE_MESSAGE: 188 GOOGLE_LOG(FATAL) << "Unsupported"; 189 return false; 190 case FieldDescriptor::CPPTYPE_STRING: 191 return *val_.string_value_ < *other.val_.string_value_; 192 case FieldDescriptor::CPPTYPE_INT64: 193 return val_.int64_value_ < other.val_.int64_value_; 194 case FieldDescriptor::CPPTYPE_INT32: 195 return val_.int32_value_ < other.val_.int32_value_; 196 case FieldDescriptor::CPPTYPE_UINT64: 197 return val_.uint64_value_ < other.val_.uint64_value_; 198 case FieldDescriptor::CPPTYPE_UINT32: 199 return val_.uint32_value_ < other.val_.uint32_value_; 200 case FieldDescriptor::CPPTYPE_BOOL: 201 return val_.bool_value_ < other.val_.bool_value_; 202 } 203 return false; 204 } 205 206 bool operator==(const MapKey& other) const { 207 if (type_ != other.type_) { 208 // To be consistent with operator<, we don't allow this either. 209 GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; 210 } 211 switch (type()) { 212 case FieldDescriptor::CPPTYPE_DOUBLE: 213 case FieldDescriptor::CPPTYPE_FLOAT: 214 case FieldDescriptor::CPPTYPE_ENUM: 215 case FieldDescriptor::CPPTYPE_MESSAGE: 216 GOOGLE_LOG(FATAL) << "Unsupported"; 217 break; 218 case FieldDescriptor::CPPTYPE_STRING: 219 return *val_.string_value_ == *other.val_.string_value_; 220 case FieldDescriptor::CPPTYPE_INT64: 221 return val_.int64_value_ == other.val_.int64_value_; 222 case FieldDescriptor::CPPTYPE_INT32: 223 return val_.int32_value_ == other.val_.int32_value_; 224 case FieldDescriptor::CPPTYPE_UINT64: 225 return val_.uint64_value_ == other.val_.uint64_value_; 226 case FieldDescriptor::CPPTYPE_UINT32: 227 return val_.uint32_value_ == other.val_.uint32_value_; 228 case FieldDescriptor::CPPTYPE_BOOL: 229 return val_.bool_value_ == other.val_.bool_value_; 230 } 231 GOOGLE_LOG(FATAL) << "Can't get here."; 232 return false; 233 } 234 CopyFrom(const MapKey & other)235 void CopyFrom(const MapKey& other) { 236 SetType(other.type()); 237 switch (type_) { 238 case FieldDescriptor::CPPTYPE_DOUBLE: 239 case FieldDescriptor::CPPTYPE_FLOAT: 240 case FieldDescriptor::CPPTYPE_ENUM: 241 case FieldDescriptor::CPPTYPE_MESSAGE: 242 GOOGLE_LOG(FATAL) << "Unsupported"; 243 break; 244 case FieldDescriptor::CPPTYPE_STRING: 245 *val_.string_value_ = *other.val_.string_value_; 246 break; 247 case FieldDescriptor::CPPTYPE_INT64: 248 val_.int64_value_ = other.val_.int64_value_; 249 break; 250 case FieldDescriptor::CPPTYPE_INT32: 251 val_.int32_value_ = other.val_.int32_value_; 252 break; 253 case FieldDescriptor::CPPTYPE_UINT64: 254 val_.uint64_value_ = other.val_.uint64_value_; 255 break; 256 case FieldDescriptor::CPPTYPE_UINT32: 257 val_.uint32_value_ = other.val_.uint32_value_; 258 break; 259 case FieldDescriptor::CPPTYPE_BOOL: 260 val_.bool_value_ = other.val_.bool_value_; 261 break; 262 } 263 } 264 265 private: 266 template <typename K, typename V> 267 friend class internal::TypeDefinedMapFieldBase; 268 friend class MapIterator; 269 friend class internal::DynamicMapField; 270 271 union KeyValue { KeyValue()272 KeyValue() {} 273 string* string_value_; 274 int64 int64_value_; 275 int32 int32_value_; 276 uint64 uint64_value_; 277 uint32 uint32_value_; 278 bool bool_value_; 279 } val_; 280 SetType(FieldDescriptor::CppType type)281 void SetType(FieldDescriptor::CppType type) { 282 if (type_ == type) return; 283 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 284 delete val_.string_value_; 285 } 286 type_ = type; 287 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 288 val_.string_value_ = new string; 289 } 290 } 291 292 // type_ is 0 or a valid FieldDescriptor::CppType. 293 int type_; 294 }; 295 296 // MapValueRef points to a map value. 297 class LIBPROTOBUF_EXPORT MapValueRef { 298 public: MapValueRef()299 MapValueRef() : data_(NULL), type_(0) {} 300 SetInt64Value(int64 value)301 void SetInt64Value(int64 value) { 302 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, 303 "MapValueRef::SetInt64Value"); 304 *reinterpret_cast<int64*>(data_) = value; 305 } SetUInt64Value(uint64 value)306 void SetUInt64Value(uint64 value) { 307 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, 308 "MapValueRef::SetUInt64Value"); 309 *reinterpret_cast<uint64*>(data_) = value; 310 } SetInt32Value(int32 value)311 void SetInt32Value(int32 value) { 312 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, 313 "MapValueRef::SetInt32Value"); 314 *reinterpret_cast<int32*>(data_) = value; 315 } SetUInt32Value(uint32 value)316 void SetUInt32Value(uint32 value) { 317 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, 318 "MapValueRef::SetUInt32Value"); 319 *reinterpret_cast<uint32*>(data_) = value; 320 } SetBoolValue(bool value)321 void SetBoolValue(bool value) { 322 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, 323 "MapValueRef::SetBoolValue"); 324 *reinterpret_cast<bool*>(data_) = value; 325 } 326 // TODO(jieluo) - Checks that enum is member. SetEnumValue(int value)327 void SetEnumValue(int value) { 328 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, 329 "MapValueRef::SetEnumValue"); 330 *reinterpret_cast<int*>(data_) = value; 331 } SetStringValue(const string & value)332 void SetStringValue(const string& value) { 333 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, 334 "MapValueRef::SetStringValue"); 335 *reinterpret_cast<string*>(data_) = value; 336 } SetFloatValue(float value)337 void SetFloatValue(float value) { 338 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, 339 "MapValueRef::SetFloatValue"); 340 *reinterpret_cast<float*>(data_) = value; 341 } SetDoubleValue(double value)342 void SetDoubleValue(double value) { 343 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, 344 "MapValueRef::SetDoubleValue"); 345 *reinterpret_cast<double*>(data_) = value; 346 } 347 GetInt64Value()348 int64 GetInt64Value() const { 349 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, 350 "MapValueRef::GetInt64Value"); 351 return *reinterpret_cast<int64*>(data_); 352 } GetUInt64Value()353 uint64 GetUInt64Value() const { 354 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, 355 "MapValueRef::GetUInt64Value"); 356 return *reinterpret_cast<uint64*>(data_); 357 } GetInt32Value()358 int32 GetInt32Value() const { 359 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, 360 "MapValueRef::GetInt32Value"); 361 return *reinterpret_cast<int32*>(data_); 362 } GetUInt32Value()363 uint32 GetUInt32Value() const { 364 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, 365 "MapValueRef::GetUInt32Value"); 366 return *reinterpret_cast<uint32*>(data_); 367 } GetBoolValue()368 bool GetBoolValue() const { 369 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, 370 "MapValueRef::GetBoolValue"); 371 return *reinterpret_cast<bool*>(data_); 372 } GetEnumValue()373 int GetEnumValue() const { 374 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, 375 "MapValueRef::GetEnumValue"); 376 return *reinterpret_cast<int*>(data_); 377 } GetStringValue()378 const string& GetStringValue() const { 379 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, 380 "MapValueRef::GetStringValue"); 381 return *reinterpret_cast<string*>(data_); 382 } GetFloatValue()383 float GetFloatValue() const { 384 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, 385 "MapValueRef::GetFloatValue"); 386 return *reinterpret_cast<float*>(data_); 387 } GetDoubleValue()388 double GetDoubleValue() const { 389 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, 390 "MapValueRef::GetDoubleValue"); 391 return *reinterpret_cast<double*>(data_); 392 } 393 GetMessageValue()394 const Message& GetMessageValue() const { 395 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, 396 "MapValueRef::GetMessageValue"); 397 return *reinterpret_cast<Message*>(data_); 398 } 399 MutableMessageValue()400 Message* MutableMessageValue() { 401 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, 402 "MapValueRef::MutableMessageValue"); 403 return reinterpret_cast<Message*>(data_); 404 } 405 406 private: 407 template <typename K, typename V, 408 internal::WireFormatLite::FieldType key_wire_type, 409 internal::WireFormatLite::FieldType value_wire_type, 410 int default_enum_value> 411 friend class internal::MapField; 412 template <typename K, typename V> 413 friend class internal::TypeDefinedMapFieldBase; 414 friend class MapIterator; 415 friend class internal::GeneratedMessageReflection; 416 friend class internal::DynamicMapField; 417 SetType(FieldDescriptor::CppType type)418 void SetType(FieldDescriptor::CppType type) { 419 type_ = type; 420 } 421 type()422 FieldDescriptor::CppType type() const { 423 if (type_ == 0 || data_ == NULL) { 424 GOOGLE_LOG(FATAL) 425 << "Protocol Buffer map usage error:\n" 426 << "MapValueRef::type MapValueRef is not initialized."; 427 } 428 return (FieldDescriptor::CppType)type_; 429 } SetValue(const void * val)430 void SetValue(const void* val) { 431 data_ = const_cast<void*>(val); 432 } CopyFrom(const MapValueRef & other)433 void CopyFrom(const MapValueRef& other) { 434 type_ = other.type_; 435 data_ = other.data_; 436 } 437 // Only used in DynamicMapField DeleteData()438 void DeleteData() { 439 switch (type_) { 440 #define HANDLE_TYPE(CPPTYPE, TYPE) \ 441 case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ 442 delete reinterpret_cast<TYPE*>(data_); \ 443 break; \ 444 } 445 HANDLE_TYPE(INT32, int32); 446 HANDLE_TYPE(INT64, int64); 447 HANDLE_TYPE(UINT32, uint32); 448 HANDLE_TYPE(UINT64, uint64); 449 HANDLE_TYPE(DOUBLE, double); 450 HANDLE_TYPE(FLOAT, float); 451 HANDLE_TYPE(BOOL, bool); 452 HANDLE_TYPE(STRING, string); 453 HANDLE_TYPE(ENUM, int32); 454 HANDLE_TYPE(MESSAGE, Message); 455 #undef HANDLE_TYPE 456 } 457 } 458 // data_ point to a map value. MapValueRef does not 459 // own this value. 460 void* data_; 461 // type_ is 0 or a valid FieldDescriptor::CppType. 462 int type_; 463 }; 464 465 #undef TYPE_CHECK 466 467 // This is the class for google::protobuf::Map's internal value_type. Instead of using 468 // std::pair as value_type, we use this class which provides us more control of 469 // its process of construction and destruction. 470 template <typename Key, typename T> 471 class MapPair { 472 public: 473 typedef const Key first_type; 474 typedef T second_type; 475 MapPair(const Key & other_first,const T & other_second)476 MapPair(const Key& other_first, const T& other_second) 477 : first(other_first), second(other_second) {} MapPair(const Key & other_first)478 explicit MapPair(const Key& other_first) : first(other_first), second() {} MapPair(const MapPair & other)479 MapPair(const MapPair& other) 480 : first(other.first), second(other.second) {} 481 ~MapPair()482 ~MapPair() {} 483 484 // Implicitly convertible to std::pair of compatible types. 485 template <typename T1, typename T2> 486 operator std::pair<T1, T2>() const { 487 return std::pair<T1, T2>(first, second); 488 } 489 490 const Key first; 491 T second; 492 493 private: 494 friend class ::google::protobuf::Arena; 495 friend class Map<Key, T>; 496 }; 497 498 // google::protobuf::Map is an associative container type used to store protobuf map 499 // fields. Each Map instance may or may not use a different hash function, a 500 // different iteration order, and so on. E.g., please don't examine 501 // implementation details to decide if the following would work: 502 // Map<int, int> m0, m1; 503 // m0[0] = m1[0] = m0[1] = m1[1] = 0; 504 // assert(m0.begin()->first == m1.begin()->first); // Bug! 505 // 506 // Map's interface is similar to std::unordered_map, except that Map is not 507 // designed to play well with exceptions. 508 template <typename Key, typename T> 509 class Map { 510 public: 511 typedef Key key_type; 512 typedef T mapped_type; 513 typedef MapPair<Key, T> value_type; 514 515 typedef value_type* pointer; 516 typedef const value_type* const_pointer; 517 typedef value_type& reference; 518 typedef const value_type& const_reference; 519 520 typedef size_t size_type; 521 typedef hash<Key> hasher; 522 523 Map(bool old_style = true) arena_(NULL)524 : arena_(NULL), 525 default_enum_value_(0), 526 old_style_(old_style) { 527 Init(); 528 } 529 explicit Map(Arena* arena, bool old_style = true) arena_(arena)530 : arena_(arena), 531 default_enum_value_(0), 532 old_style_(old_style) { 533 Init(); 534 } Map(const Map & other)535 Map(const Map& other) 536 : arena_(NULL), 537 default_enum_value_(other.default_enum_value_), 538 old_style_(other.old_style_) { 539 Init(); 540 insert(other.begin(), other.end()); 541 } 542 template <class InputIt> 543 Map(const InputIt& first, const InputIt& last, bool old_style = true) arena_(NULL)544 : arena_(NULL), 545 default_enum_value_(0), 546 old_style_(old_style) { 547 Init(); 548 insert(first, last); 549 } 550 ~Map()551 ~Map() { 552 clear(); 553 if (arena_ == NULL) { 554 if (old_style_) 555 delete deprecated_elements_; 556 else 557 delete elements_; 558 } 559 } 560 561 private: Init()562 void Init() { 563 if (old_style_) 564 deprecated_elements_ = Arena::Create<DeprecatedInnerMap>( 565 arena_, 0, hasher(), equal_to<Key>(), 566 MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_)); 567 else 568 elements_ = 569 Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_)); 570 } 571 572 // re-implement std::allocator to use arena allocator for memory allocation. 573 // Used for google::protobuf::Map implementation. Users should not use this class 574 // directly. 575 template <typename U> 576 class MapAllocator { 577 public: 578 typedef U value_type; 579 typedef value_type* pointer; 580 typedef const value_type* const_pointer; 581 typedef value_type& reference; 582 typedef const value_type& const_reference; 583 typedef size_t size_type; 584 typedef ptrdiff_t difference_type; 585 MapAllocator()586 MapAllocator() : arena_(NULL) {} MapAllocator(Arena * arena)587 explicit MapAllocator(Arena* arena) : arena_(arena) {} 588 template <typename X> MapAllocator(const MapAllocator<X> & allocator)589 MapAllocator(const MapAllocator<X>& allocator) 590 : arena_(allocator.arena_) {} 591 592 pointer allocate(size_type n, const_pointer hint = 0) { 593 // If arena is not given, malloc needs to be called which doesn't 594 // construct element object. 595 if (arena_ == NULL) { 596 return reinterpret_cast<pointer>(malloc(n * sizeof(value_type))); 597 } else { 598 return reinterpret_cast<pointer>( 599 Arena::CreateArray<uint8>(arena_, n * sizeof(value_type))); 600 } 601 } 602 deallocate(pointer p,size_type n)603 void deallocate(pointer p, size_type n) { 604 if (arena_ == NULL) { 605 free(p); 606 } 607 } 608 609 #if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ 610 !defined(GOOGLE_PROTOBUF_OS_NACL) && \ 611 !defined(GOOGLE_PROTOBUF_OS_ANDROID) && \ 612 !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) 613 template<class NodeType, class... Args> construct(NodeType * p,Args &&...args)614 void construct(NodeType* p, Args&&... args) { 615 // Clang 3.6 doesn't compile static casting to void* directly. (Issue 616 // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall 617 // not cast away constness". So first the maybe const pointer is casted to 618 // const void* and after the const void* is const casted. 619 new (const_cast<void*>(static_cast<const void*>(p))) 620 NodeType(std::forward<Args>(args)...); 621 } 622 623 template<class NodeType> destroy(NodeType * p)624 void destroy(NodeType* p) { 625 p->~NodeType(); 626 } 627 #else construct(pointer p,const_reference t)628 void construct(pointer p, const_reference t) { new (p) value_type(t); } 629 destroy(pointer p)630 void destroy(pointer p) { p->~value_type(); } 631 #endif 632 633 template <typename X> 634 struct rebind { 635 typedef MapAllocator<X> other; 636 }; 637 638 template <typename X> 639 bool operator==(const MapAllocator<X>& other) const { 640 return arena_ == other.arena_; 641 } 642 643 template <typename X> 644 bool operator!=(const MapAllocator<X>& other) const { 645 return arena_ != other.arena_; 646 } 647 648 // To support Visual Studio 2008 max_size()649 size_type max_size() const { 650 return std::numeric_limits<size_type>::max(); 651 } 652 653 private: 654 typedef void DestructorSkippable_; 655 Arena* const arena_; 656 657 template <typename X> 658 friend class MapAllocator; 659 }; 660 661 // InnerMap's key type is Key and its value type is value_type*. We use a 662 // custom class here and for Node, below, to ensure that k_ is at offset 0, 663 // allowing safe conversion from pointer to Node to pointer to Key, and vice 664 // versa when appropriate. 665 class KeyValuePair { 666 public: KeyValuePair(const Key & k,value_type * v)667 KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {} 668 key()669 const Key& key() const { return k_; } key()670 Key& key() { return k_; } value()671 value_type* const value() const { return v_; } value()672 value_type*& value() { return v_; } 673 674 private: 675 Key k_; 676 value_type* v_; 677 }; 678 679 typedef MapAllocator<KeyValuePair> Allocator; 680 681 // InnerMap is a generic hash-based map. It doesn't contain any 682 // protocol-buffer-specific logic. It is a chaining hash map with the 683 // additional feature that some buckets can be converted to use an ordered 684 // container. This ensures O(lg n) bounds on find, insert, and erase, while 685 // avoiding the overheads of ordered containers most of the time. 686 // 687 // The implementation doesn't need the full generality of unordered_map, 688 // and it doesn't have it. More bells and whistles can be added as needed. 689 // Some implementation details: 690 // 1. The hash function has type hasher and the equality function 691 // equal_to<Key>. We inherit from hasher to save space 692 // (empty-base-class optimization). 693 // 2. The number of buckets is a power of two. 694 // 3. Buckets are converted to trees in pairs: if we convert bucket b then 695 // buckets b and b^1 will share a tree. Invariant: buckets b and b^1 have 696 // the same non-NULL value iff they are sharing a tree. (An alternative 697 // implementation strategy would be to have a tag bit per bucket.) 698 // 4. As is typical for hash_map and such, the Keys and Values are always 699 // stored in linked list nodes. Pointers to elements are never invalidated 700 // until the element is deleted. 701 // 5. The trees' payload type is pointer to linked-list node. Tree-converting 702 // a bucket doesn't copy Key-Value pairs. 703 // 6. Once we've tree-converted a bucket, it is never converted back. However, 704 // the items a tree contains may wind up assigned to trees or lists upon a 705 // rehash. 706 // 7. The code requires no C++ features from C++11 or later. 707 // 8. Mutations to a map do not invalidate the map's iterators, pointers to 708 // elements, or references to elements. 709 // 9. Except for erase(iterator), any non-const method can reorder iterators. 710 class InnerMap : private hasher { 711 public: 712 typedef value_type* Value; 713 InnerMap(size_type n,hasher h,Allocator alloc)714 InnerMap(size_type n, hasher h, Allocator alloc) 715 : hasher(h), 716 num_elements_(0), 717 seed_(Seed()), 718 table_(NULL), 719 alloc_(alloc) { 720 n = TableSize(n); 721 table_ = CreateEmptyTable(n); 722 num_buckets_ = index_of_first_non_null_ = n; 723 } 724 ~InnerMap()725 ~InnerMap() { 726 if (table_ != NULL) { 727 clear(); 728 Dealloc<void*>(table_, num_buckets_); 729 } 730 } 731 732 private: 733 enum { kMinTableSize = 8 }; 734 735 // Linked-list nodes, as one would expect for a chaining hash table. 736 struct Node { 737 KeyValuePair kv; 738 Node* next; 739 }; 740 741 // This is safe only if the given pointer is known to point to a Key that is 742 // part of a Node. NodePtrFromKeyPtr(Key * k)743 static Node* NodePtrFromKeyPtr(Key* k) { 744 return reinterpret_cast<Node*>(k); 745 } 746 KeyPtrFromNodePtr(Node * node)747 static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); } 748 749 // Trees. The payload type is pointer to Key, so that we can query the tree 750 // with Keys that are not in any particular data structure. When we insert, 751 // though, the pointer is always pointing to a Key that is inside a Node. 752 struct KeyCompare { operatorKeyCompare753 bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; } 754 }; 755 typedef typename Allocator::template rebind<Key*>::other KeyPtrAllocator; 756 typedef std::set<Key*, KeyCompare, KeyPtrAllocator> Tree; 757 758 // iterator and const_iterator are instantiations of iterator_base. 759 template <typename KeyValueType> 760 class iterator_base { 761 public: 762 typedef KeyValueType& reference; 763 typedef KeyValueType* pointer; 764 typedef typename Tree::iterator TreeIterator; 765 766 // Invariants: 767 // node_ is always correct. This is handy because the most common 768 // operations are operator* and operator-> and they only use node_. 769 // When node_ is set to a non-NULL value, all the other non-const fields 770 // are updated to be correct also, but those fields can become stale 771 // if the underlying map is modified. When those fields are needed they 772 // are rechecked, and updated if necessary. iterator_base()773 iterator_base() : node_(NULL) {} 774 iterator_base(const InnerMap * m)775 explicit iterator_base(const InnerMap* m) : m_(m) { 776 SearchFrom(m->index_of_first_non_null_); 777 } 778 779 // Any iterator_base can convert to any other. This is overkill, and we 780 // rely on the enclosing class to use it wisely. The standard "iterator 781 // can convert to const_iterator" is OK but the reverse direction is not. 782 template <typename U> iterator_base(const iterator_base<U> & it)783 explicit iterator_base(const iterator_base<U>& it) 784 : node_(it.node_), 785 m_(it.m_), 786 bucket_index_(it.bucket_index_), 787 tree_it_(it.tree_it_) {} 788 iterator_base(Node * n,const InnerMap * m,size_type index)789 iterator_base(Node* n, const InnerMap* m, size_type index) 790 : node_(n), 791 m_(m), 792 bucket_index_(index) {} 793 iterator_base(TreeIterator tree_it,const InnerMap * m,size_type index)794 iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index) 795 : node_(NodePtrFromKeyPtr(*tree_it)), 796 m_(m), 797 bucket_index_(index), 798 tree_it_(tree_it) { 799 // Invariant: iterators that use tree_it_ have an even bucket_index_. 800 GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0); 801 } 802 803 // Advance through buckets, looking for the first that isn't empty. 804 // If nothing non-empty is found then leave node_ == NULL. SearchFrom(size_type start_bucket)805 void SearchFrom(size_type start_bucket) { 806 GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ || 807 m_->table_[m_->index_of_first_non_null_] != NULL); 808 node_ = NULL; 809 for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_; 810 bucket_index_++) { 811 if (m_->TableEntryIsNonEmptyList(bucket_index_)) { 812 node_ = static_cast<Node*>(m_->table_[bucket_index_]); 813 break; 814 } else if (m_->TableEntryIsTree(bucket_index_)) { 815 Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); 816 GOOGLE_DCHECK(!tree->empty()); 817 tree_it_ = tree->begin(); 818 node_ = NodePtrFromKeyPtr(*tree_it_); 819 break; 820 } 821 } 822 } 823 824 reference operator*() const { return node_->kv; } 825 pointer operator->() const { return &(operator*()); } 826 827 friend bool operator==(const iterator_base& a, const iterator_base& b) { 828 return a.node_ == b.node_; 829 } 830 friend bool operator!=(const iterator_base& a, const iterator_base& b) { 831 return a.node_ != b.node_; 832 } 833 834 iterator_base& operator++() { 835 if (node_->next == NULL) { 836 const bool is_list = revalidate_if_necessary(); 837 if (is_list) { 838 SearchFrom(bucket_index_ + 1); 839 } else { 840 GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0); 841 Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); 842 if (++tree_it_ == tree->end()) { 843 SearchFrom(bucket_index_ + 2); 844 } else { 845 node_ = NodePtrFromKeyPtr(*tree_it_); 846 } 847 } 848 } else { 849 node_ = node_->next; 850 } 851 return *this; 852 } 853 854 iterator_base operator++(int /* unused */) { 855 iterator_base tmp = *this; 856 ++*this; 857 return tmp; 858 } 859 860 // Assumes node_ and m_ are correct and non-NULL, but other fields may be 861 // stale. Fix them as needed. Then return true iff node_ points to a 862 // Node in a list. revalidate_if_necessary()863 bool revalidate_if_necessary() { 864 GOOGLE_DCHECK(node_ != NULL && m_ != NULL); 865 // Force bucket_index_ to be in range. 866 bucket_index_ &= (m_->num_buckets_ - 1); 867 // Common case: the bucket we think is relevant points to node_. 868 if (m_->table_[bucket_index_] == static_cast<void*>(node_)) 869 return true; 870 // Less common: the bucket is a linked list with node_ somewhere in it, 871 // but not at the head. 872 if (m_->TableEntryIsNonEmptyList(bucket_index_)) { 873 Node* l = static_cast<Node*>(m_->table_[bucket_index_]); 874 while ((l = l->next) != NULL) { 875 if (l == node_) { 876 return true; 877 } 878 } 879 } 880 // Well, bucket_index_ still might be correct, but probably 881 // not. Revalidate just to be sure. This case is rare enough that we 882 // don't worry about potential optimizations, such as having a custom 883 // find-like method that compares Node* instead of const Key&. 884 iterator_base i(m_->find(*KeyPtrFromNodePtr(node_))); 885 bucket_index_ = i.bucket_index_; 886 tree_it_ = i.tree_it_; 887 return m_->TableEntryIsList(bucket_index_); 888 } 889 890 Node* node_; 891 const InnerMap* m_; 892 size_type bucket_index_; 893 TreeIterator tree_it_; 894 }; 895 896 public: 897 typedef iterator_base<KeyValuePair> iterator; 898 typedef iterator_base<const KeyValuePair> const_iterator; 899 begin()900 iterator begin() { return iterator(this); } end()901 iterator end() { return iterator(); } begin()902 const_iterator begin() const { return const_iterator(this); } end()903 const_iterator end() const { return const_iterator(); } 904 clear()905 void clear() { 906 for (size_type b = 0; b < num_buckets_; b++) { 907 if (TableEntryIsNonEmptyList(b)) { 908 Node* node = static_cast<Node*>(table_[b]); 909 table_[b] = NULL; 910 do { 911 Node* next = node->next; 912 DestroyNode(node); 913 node = next; 914 } while (node != NULL); 915 } else if (TableEntryIsTree(b)) { 916 Tree* tree = static_cast<Tree*>(table_[b]); 917 GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0); 918 table_[b] = table_[b + 1] = NULL; 919 typename Tree::iterator tree_it = tree->begin(); 920 do { 921 Node* node = NodePtrFromKeyPtr(*tree_it); 922 typename Tree::iterator next = tree_it; 923 ++next; 924 tree->erase(tree_it); 925 DestroyNode(node); 926 tree_it = next; 927 } while (tree_it != tree->end()); 928 DestroyTree(tree); 929 b++; 930 } 931 } 932 num_elements_ = 0; 933 index_of_first_non_null_ = num_buckets_; 934 } 935 hash_function()936 const hasher& hash_function() const { return *this; } 937 max_size()938 static size_type max_size() { 939 return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28); 940 } size()941 size_type size() const { return num_elements_; } empty()942 bool empty() const { return size() == 0; } 943 find(const Key & k)944 iterator find(const Key& k) { return iterator(FindHelper(k).first); } find(const Key & k)945 const_iterator find(const Key& k) const { return FindHelper(k).first; } 946 947 // In traditional C++ style, this performs "insert if not present." insert(const KeyValuePair & kv)948 std::pair<iterator, bool> insert(const KeyValuePair& kv) { 949 std::pair<const_iterator, size_type> p = FindHelper(kv.key()); 950 // Case 1: key was already present. 951 if (p.first.node_ != NULL) 952 return std::make_pair(iterator(p.first), false); 953 // Case 2: insert. 954 if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { 955 p = FindHelper(kv.key()); 956 } 957 const size_type b = p.second; // bucket number 958 Node* node = Alloc<Node>(1); 959 alloc_.construct(&node->kv, kv); 960 iterator result = InsertUnique(b, node); 961 ++num_elements_; 962 return std::make_pair(result, true); 963 } 964 965 // The same, but if an insertion is necessary then the value portion of the 966 // inserted key-value pair is left uninitialized. insert(const Key & k)967 std::pair<iterator, bool> insert(const Key& k) { 968 std::pair<const_iterator, size_type> p = FindHelper(k); 969 // Case 1: key was already present. 970 if (p.first.node_ != NULL) 971 return std::make_pair(iterator(p.first), false); 972 // Case 2: insert. 973 if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { 974 p = FindHelper(k); 975 } 976 const size_type b = p.second; // bucket number 977 Node* node = Alloc<Node>(1); 978 typedef typename Allocator::template rebind<Key>::other KeyAllocator; 979 KeyAllocator(alloc_).construct(&node->kv.key(), k); 980 iterator result = InsertUnique(b, node); 981 ++num_elements_; 982 return std::make_pair(result, true); 983 } 984 985 Value& operator[](const Key& k) { 986 KeyValuePair kv(k, Value()); 987 return insert(kv).first->value(); 988 } 989 erase(iterator it)990 void erase(iterator it) { 991 GOOGLE_DCHECK_EQ(it.m_, this); 992 const bool is_list = it.revalidate_if_necessary(); 993 size_type b = it.bucket_index_; 994 Node* const item = it.node_; 995 if (is_list) { 996 GOOGLE_DCHECK(TableEntryIsNonEmptyList(b)); 997 Node* head = static_cast<Node*>(table_[b]); 998 head = EraseFromLinkedList(item, head); 999 table_[b] = static_cast<void*>(head); 1000 } else { 1001 GOOGLE_DCHECK(TableEntryIsTree(b)); 1002 Tree* tree = static_cast<Tree*>(table_[b]); 1003 tree->erase(it.tree_it_); 1004 if (tree->empty()) { 1005 // Force b to be the minimum of b and b ^ 1. This is important 1006 // only because we want index_of_first_non_null_ to be correct. 1007 b &= ~static_cast<size_type>(1); 1008 DestroyTree(tree); 1009 table_[b] = table_[b + 1] = NULL; 1010 } 1011 } 1012 DestroyNode(item); 1013 --num_elements_; 1014 if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) { 1015 while (index_of_first_non_null_ < num_buckets_ && 1016 table_[index_of_first_non_null_] == NULL) { 1017 ++index_of_first_non_null_; 1018 } 1019 } 1020 } 1021 1022 private: FindHelper(const Key & k)1023 std::pair<const_iterator, size_type> FindHelper(const Key& k) const { 1024 size_type b = BucketNumber(k); 1025 if (TableEntryIsNonEmptyList(b)) { 1026 Node* node = static_cast<Node*>(table_[b]); 1027 do { 1028 if (IsMatch(*KeyPtrFromNodePtr(node), k)) { 1029 return std::make_pair(const_iterator(node, this, b), b); 1030 } else { 1031 node = node->next; 1032 } 1033 } while (node != NULL); 1034 } else if (TableEntryIsTree(b)) { 1035 GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); 1036 b &= ~static_cast<size_t>(1); 1037 Tree* tree = static_cast<Tree*>(table_[b]); 1038 Key* key = const_cast<Key*>(&k); 1039 typename Tree::iterator tree_it = tree->find(key); 1040 if (tree_it != tree->end()) { 1041 return std::make_pair(const_iterator(tree_it, this, b), b); 1042 } 1043 } 1044 return std::make_pair(end(), b); 1045 } 1046 1047 // Insert the given Node in bucket b. If that would make bucket b too big, 1048 // and bucket b is not a tree, create a tree for buckets b and b^1 to share. 1049 // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct 1050 // bucket. num_elements_ is not modified. InsertUnique(size_type b,Node * node)1051 iterator InsertUnique(size_type b, Node* node) { 1052 GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ || 1053 table_[index_of_first_non_null_] != NULL); 1054 // In practice, the code that led to this point may have already 1055 // determined whether we are inserting into an empty list, a short list, 1056 // or whatever. But it's probably cheap enough to recompute that here; 1057 // it's likely that we're inserting into an empty or short list. 1058 iterator result; 1059 GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end()); 1060 if (TableEntryIsEmpty(b)) { 1061 result = InsertUniqueInList(b, node); 1062 } else if (TableEntryIsNonEmptyList(b)) { 1063 if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) { 1064 TreeConvert(b); 1065 result = InsertUniqueInTree(b, node); 1066 GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1)); 1067 } else { 1068 // Insert into a pre-existing list. This case cannot modify 1069 // index_of_first_non_null_, so we skip the code to update it. 1070 return InsertUniqueInList(b, node); 1071 } 1072 } else { 1073 // Insert into a pre-existing tree. This case cannot modify 1074 // index_of_first_non_null_, so we skip the code to update it. 1075 return InsertUniqueInTree(b, node); 1076 } 1077 index_of_first_non_null_ = 1078 std::min(index_of_first_non_null_, result.bucket_index_); 1079 return result; 1080 } 1081 1082 // Helper for InsertUnique. Handles the case where bucket b is a 1083 // not-too-long linked list. InsertUniqueInList(size_type b,Node * node)1084 iterator InsertUniqueInList(size_type b, Node* node) { 1085 node->next = static_cast<Node*>(table_[b]); 1086 table_[b] = static_cast<void*>(node); 1087 return iterator(node, this, b); 1088 } 1089 1090 // Helper for InsertUnique. Handles the case where bucket b points to a 1091 // Tree. InsertUniqueInTree(size_type b,Node * node)1092 iterator InsertUniqueInTree(size_type b, Node* node) { 1093 GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); 1094 // Maintain the invariant that node->next is NULL for all Nodes in Trees. 1095 node->next = NULL; 1096 return iterator(static_cast<Tree*>(table_[b]) 1097 ->insert(KeyPtrFromNodePtr(node)) 1098 .first, 1099 this, b & ~static_cast<size_t>(1)); 1100 } 1101 1102 // Returns whether it did resize. Currently this is only used when 1103 // num_elements_ increases, though it could be used in other situations. 1104 // It checks for load too low as well as load too high: because any number 1105 // of erases can occur between inserts, the load could be as low as 0 here. 1106 // Resizing to a lower size is not always helpful, but failing to do so can 1107 // destroy the expected big-O bounds for some operations. By having the 1108 // policy that sometimes we resize down as well as up, clients can easily 1109 // keep O(size()) = O(number of buckets) if they want that. ResizeIfLoadIsOutOfRange(size_type new_size)1110 bool ResizeIfLoadIsOutOfRange(size_type new_size) { 1111 const size_type kMaxMapLoadTimes16 = 12; // controls RAM vs CPU tradeoff 1112 const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16; 1113 const size_type lo_cutoff = hi_cutoff / 4; 1114 // We don't care how many elements are in trees. If a lot are, 1115 // we may resize even though there are many empty buckets. In 1116 // practice, this seems fine. 1117 if (GOOGLE_PREDICT_FALSE(new_size >= hi_cutoff)) { 1118 if (num_buckets_ <= max_size() / 2) { 1119 Resize(num_buckets_ * 2); 1120 return true; 1121 } 1122 } else if (GOOGLE_PREDICT_FALSE(new_size <= lo_cutoff && 1123 num_buckets_ > kMinTableSize)) { 1124 size_type lg2_of_size_reduction_factor = 1; 1125 // It's possible we want to shrink a lot here... size() could even be 0. 1126 // So, estimate how much to shrink by making sure we don't shrink so 1127 // much that we would need to grow the table after a few inserts. 1128 const size_type hypothetical_size = new_size * 5 / 4 + 1; 1129 while ((hypothetical_size << lg2_of_size_reduction_factor) < 1130 hi_cutoff) { 1131 ++lg2_of_size_reduction_factor; 1132 } 1133 size_type new_num_buckets = std::max<size_type>( 1134 kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor); 1135 if (new_num_buckets != num_buckets_) { 1136 Resize(new_num_buckets); 1137 return true; 1138 } 1139 } 1140 return false; 1141 } 1142 1143 // Resize to the given number of buckets. Resize(size_t new_num_buckets)1144 void Resize(size_t new_num_buckets) { 1145 GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize); 1146 void** const old_table = table_; 1147 const size_type old_table_size = num_buckets_; 1148 num_buckets_ = new_num_buckets; 1149 table_ = CreateEmptyTable(num_buckets_); 1150 const size_type start = index_of_first_non_null_; 1151 index_of_first_non_null_ = num_buckets_; 1152 for (size_type i = start; i < old_table_size; i++) { 1153 if (TableEntryIsNonEmptyList(old_table, i)) { 1154 TransferList(old_table, i); 1155 } else if (TableEntryIsTree(old_table, i)) { 1156 TransferTree(old_table, i++); 1157 } 1158 } 1159 Dealloc<void*>(old_table, old_table_size); 1160 } 1161 TransferList(void * const * table,size_type index)1162 void TransferList(void* const* table, size_type index) { 1163 Node* node = static_cast<Node*>(table[index]); 1164 do { 1165 Node* next = node->next; 1166 InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node); 1167 node = next; 1168 } while (node != NULL); 1169 } 1170 TransferTree(void * const * table,size_type index)1171 void TransferTree(void* const* table, size_type index) { 1172 Tree* tree = static_cast<Tree*>(table[index]); 1173 typename Tree::iterator tree_it = tree->begin(); 1174 do { 1175 Node* node = NodePtrFromKeyPtr(*tree_it); 1176 InsertUnique(BucketNumber(**tree_it), node); 1177 } while (++tree_it != tree->end()); 1178 DestroyTree(tree); 1179 } 1180 EraseFromLinkedList(Node * item,Node * head)1181 Node* EraseFromLinkedList(Node* item, Node* head) { 1182 if (head == item) { 1183 return head->next; 1184 } else { 1185 head->next = EraseFromLinkedList(item, head->next); 1186 return head; 1187 } 1188 } 1189 TableEntryIsEmpty(size_type b)1190 bool TableEntryIsEmpty(size_type b) const { 1191 return TableEntryIsEmpty(table_, b); 1192 } TableEntryIsNonEmptyList(size_type b)1193 bool TableEntryIsNonEmptyList(size_type b) const { 1194 return TableEntryIsNonEmptyList(table_, b); 1195 } TableEntryIsTree(size_type b)1196 bool TableEntryIsTree(size_type b) const { 1197 return TableEntryIsTree(table_, b); 1198 } TableEntryIsList(size_type b)1199 bool TableEntryIsList(size_type b) const { 1200 return TableEntryIsList(table_, b); 1201 } TableEntryIsEmpty(void * const * table,size_type b)1202 static bool TableEntryIsEmpty(void* const* table, size_type b) { 1203 return table[b] == NULL; 1204 } TableEntryIsNonEmptyList(void * const * table,size_type b)1205 static bool TableEntryIsNonEmptyList(void* const* table, size_type b) { 1206 return table[b] != NULL && table[b] != table[b ^ 1]; 1207 } TableEntryIsTree(void * const * table,size_type b)1208 static bool TableEntryIsTree(void* const* table, size_type b) { 1209 return !TableEntryIsEmpty(table, b) && 1210 !TableEntryIsNonEmptyList(table, b); 1211 } TableEntryIsList(void * const * table,size_type b)1212 static bool TableEntryIsList(void* const* table, size_type b) { 1213 return !TableEntryIsTree(table, b); 1214 } 1215 TreeConvert(size_type b)1216 void TreeConvert(size_type b) { 1217 GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1)); 1218 typename Allocator::template rebind<Tree>::other tree_allocator(alloc_); 1219 Tree* tree = tree_allocator.allocate(1); 1220 // We want to use the three-arg form of construct, if it exists, but we 1221 // create a temporary and use the two-arg construct that's known to exist. 1222 // It's clunky, but the compiler should be able to generate more-or-less 1223 // the same code. 1224 tree_allocator.construct(tree, 1225 Tree(KeyCompare(), KeyPtrAllocator(alloc_))); 1226 // Now the tree is ready to use. 1227 size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree); 1228 GOOGLE_DCHECK_EQ(count, tree->size()); 1229 table_[b] = table_[b ^ 1] = static_cast<void*>(tree); 1230 } 1231 1232 // Copy a linked list in the given bucket to a tree. 1233 // Returns the number of things it copied. CopyListToTree(size_type b,Tree * tree)1234 size_type CopyListToTree(size_type b, Tree* tree) { 1235 size_type count = 0; 1236 Node* node = static_cast<Node*>(table_[b]); 1237 while (node != NULL) { 1238 tree->insert(KeyPtrFromNodePtr(node)); 1239 ++count; 1240 Node* next = node->next; 1241 node->next = NULL; 1242 node = next; 1243 } 1244 return count; 1245 } 1246 1247 // Return whether table_[b] is a linked list that seems awfully long. 1248 // Requires table_[b] to point to a non-empty linked list. TableEntryIsTooLong(size_type b)1249 bool TableEntryIsTooLong(size_type b) { 1250 const int kMaxLength = 8; 1251 size_type count = 0; 1252 Node* node = static_cast<Node*>(table_[b]); 1253 do { 1254 ++count; 1255 node = node->next; 1256 } while (node != NULL); 1257 // Invariant: no linked list ever is more than kMaxLength in length. 1258 GOOGLE_DCHECK_LE(count, kMaxLength); 1259 return count >= kMaxLength; 1260 } 1261 BucketNumber(const Key & k)1262 size_type BucketNumber(const Key& k) const { 1263 // We inherit from hasher, so one-arg operator() provides a hash function. 1264 size_type h = (*const_cast<InnerMap*>(this))(k); 1265 // To help prevent people from making assumptions about the hash function, 1266 // we use the seed differently depending on NDEBUG. The default hash 1267 // function, the seeding, etc., are all likely to change in the future. 1268 #ifndef NDEBUG 1269 return (h * (seed_ | 1)) & (num_buckets_ - 1); 1270 #else 1271 return (h + seed_) & (num_buckets_ - 1); 1272 #endif 1273 } 1274 IsMatch(const Key & k0,const Key & k1)1275 bool IsMatch(const Key& k0, const Key& k1) const { 1276 return std::equal_to<Key>()(k0, k1); 1277 } 1278 1279 // Return a power of two no less than max(kMinTableSize, n). 1280 // Assumes either n < kMinTableSize or n is a power of two. TableSize(size_type n)1281 size_type TableSize(size_type n) { 1282 return n < kMinTableSize ? kMinTableSize : n; 1283 } 1284 1285 // Use alloc_ to allocate an array of n objects of type U. 1286 template <typename U> Alloc(size_type n)1287 U* Alloc(size_type n) { 1288 typedef typename Allocator::template rebind<U>::other alloc_type; 1289 return alloc_type(alloc_).allocate(n); 1290 } 1291 1292 // Use alloc_ to deallocate an array of n objects of type U. 1293 template <typename U> Dealloc(U * t,size_type n)1294 void Dealloc(U* t, size_type n) { 1295 typedef typename Allocator::template rebind<U>::other alloc_type; 1296 alloc_type(alloc_).deallocate(t, n); 1297 } 1298 DestroyNode(Node * node)1299 void DestroyNode(Node* node) { 1300 alloc_.destroy(&node->kv); 1301 Dealloc<Node>(node, 1); 1302 } 1303 DestroyTree(Tree * tree)1304 void DestroyTree(Tree* tree) { 1305 typename Allocator::template rebind<Tree>::other tree_allocator(alloc_); 1306 tree_allocator.destroy(tree); 1307 tree_allocator.deallocate(tree, 1); 1308 } 1309 CreateEmptyTable(size_type n)1310 void** CreateEmptyTable(size_type n) { 1311 GOOGLE_DCHECK(n >= kMinTableSize); 1312 GOOGLE_DCHECK_EQ(n & (n - 1), 0); 1313 void** result = Alloc<void*>(n); 1314 memset(result, 0, n * sizeof(result[0])); 1315 return result; 1316 } 1317 1318 // Return a randomish value. Seed()1319 size_type Seed() const { 1320 // random_device can throw, so avoid it unless we are compiling with 1321 // exceptions enabled. 1322 #if __cpp_exceptions && LANG_CXX11 1323 try { 1324 std::random_device rd; 1325 std::knuth_b knuth(rd()); 1326 std::uniform_int_distribution<size_type> u; 1327 return u(knuth); 1328 } catch (...) { } 1329 #endif 1330 size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this)); 1331 #if defined(__x86_64__) && defined(__GNUC__) 1332 uint32 hi, lo; 1333 asm("rdtsc" : "=a" (lo), "=d" (hi)); 1334 s += ((static_cast<uint64>(hi) << 32) | lo); 1335 #endif 1336 return s; 1337 } 1338 1339 size_type num_elements_; 1340 size_type num_buckets_; 1341 size_type seed_; 1342 size_type index_of_first_non_null_; 1343 void** table_; // an array with num_buckets_ entries 1344 Allocator alloc_; 1345 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); 1346 }; // end of class InnerMap 1347 1348 typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, 1349 MapAllocator<std::pair<const Key, MapPair<Key, T>*> > > 1350 DeprecatedInnerMap; 1351 1352 public: 1353 // Iterators 1354 class iterator_base { 1355 public: 1356 // We support "old style" and "new style" iterators for now. This is 1357 // temporary. Also, for "iterator()" we have an unknown category. 1358 // TODO(gpike): get rid of this. 1359 enum IteratorStyle { kUnknown, kOld, kNew }; iterator_base(IteratorStyle style)1360 explicit iterator_base(IteratorStyle style) : iterator_style_(style) {} 1361 OldStyle()1362 bool OldStyle() const { 1363 GOOGLE_DCHECK_NE(iterator_style_, kUnknown); 1364 return iterator_style_ == kOld; 1365 } UnknownStyle()1366 bool UnknownStyle() const { 1367 return iterator_style_ == kUnknown; 1368 } SameStyle(const iterator_base & other)1369 bool SameStyle(const iterator_base& other) const { 1370 return iterator_style_ == other.iterator_style_; 1371 } 1372 1373 private: 1374 IteratorStyle iterator_style_; 1375 }; 1376 1377 class const_iterator 1378 : private iterator_base, 1379 public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t, 1380 const value_type*, const value_type&> { 1381 typedef typename InnerMap::const_iterator InnerIt; 1382 typedef typename DeprecatedInnerMap::const_iterator DeprecatedInnerIt; 1383 1384 public: const_iterator()1385 const_iterator() : iterator_base(iterator_base::kUnknown) {} const_iterator(const DeprecatedInnerIt & dit)1386 explicit const_iterator(const DeprecatedInnerIt& dit) 1387 : iterator_base(iterator_base::kOld), dit_(dit) {} const_iterator(const InnerIt & it)1388 explicit const_iterator(const InnerIt& it) 1389 : iterator_base(iterator_base::kNew), it_(it) {} 1390 const_iterator(const const_iterator & other)1391 const_iterator(const const_iterator& other) 1392 : iterator_base(other), it_(other.it_), dit_(other.dit_) {} 1393 1394 const_reference operator*() const { 1395 return this->OldStyle() ? *dit_->second : *it_->value(); 1396 } 1397 const_pointer operator->() const { return &(operator*()); } 1398 1399 const_iterator& operator++() { 1400 if (this->OldStyle()) 1401 ++dit_; 1402 else 1403 ++it_; 1404 return *this; 1405 } 1406 const_iterator operator++(int) { 1407 return this->OldStyle() ? const_iterator(dit_++) : const_iterator(it_++); 1408 } 1409 1410 friend bool operator==(const const_iterator& a, const const_iterator& b) { 1411 if (!a.SameStyle(b)) return false; 1412 if (a.UnknownStyle()) return true; 1413 return a.OldStyle() ? (a.dit_ == b.dit_) : (a.it_ == b.it_); 1414 } 1415 friend bool operator!=(const const_iterator& a, const const_iterator& b) { 1416 return !(a == b); 1417 } 1418 1419 private: 1420 InnerIt it_; 1421 DeprecatedInnerIt dit_; 1422 }; 1423 1424 class iterator : private iterator_base, 1425 public std::iterator<std::forward_iterator_tag, value_type> { 1426 typedef typename InnerMap::iterator InnerIt; 1427 typedef typename DeprecatedInnerMap::iterator DeprecatedInnerIt; 1428 1429 public: iterator()1430 iterator() : iterator_base(iterator_base::kUnknown) {} iterator(const DeprecatedInnerIt & dit)1431 explicit iterator(const DeprecatedInnerIt& dit) 1432 : iterator_base(iterator_base::kOld), dit_(dit) {} iterator(const InnerIt & it)1433 explicit iterator(const InnerIt& it) 1434 : iterator_base(iterator_base::kNew), it_(it) {} 1435 1436 reference operator*() const { 1437 return this->OldStyle() ? *dit_->second : *it_->value(); 1438 } 1439 pointer operator->() const { return &(operator*()); } 1440 1441 iterator& operator++() { 1442 if (this->OldStyle()) 1443 ++dit_; 1444 else 1445 ++it_; 1446 return *this; 1447 } 1448 iterator operator++(int) { 1449 return this->OldStyle() ? iterator(dit_++) : iterator(it_++); 1450 } 1451 1452 // Allow implicit conversion to const_iterator. const_iterator()1453 operator const_iterator() const { 1454 return this->OldStyle() ? 1455 const_iterator(typename DeprecatedInnerMap::const_iterator(dit_)) : 1456 const_iterator(typename InnerMap::const_iterator(it_)); 1457 } 1458 1459 friend bool operator==(const iterator& a, const iterator& b) { 1460 if (!a.SameStyle(b)) return false; 1461 if (a.UnknownStyle()) return true; 1462 return a.OldStyle() ? a.dit_ == b.dit_ : a.it_ == b.it_; 1463 } 1464 friend bool operator!=(const iterator& a, const iterator& b) { 1465 return !(a == b); 1466 } 1467 1468 private: 1469 friend class Map; 1470 1471 InnerIt it_; 1472 DeprecatedInnerIt dit_; 1473 }; 1474 begin()1475 iterator begin() { 1476 return old_style_ ? iterator(deprecated_elements_->begin()) 1477 : iterator(elements_->begin()); 1478 } end()1479 iterator end() { 1480 return old_style_ ? iterator(deprecated_elements_->end()) 1481 : iterator(elements_->end()); 1482 } begin()1483 const_iterator begin() const { 1484 return old_style_ ? const_iterator(deprecated_elements_->begin()) 1485 : const_iterator(iterator(elements_->begin())); 1486 } end()1487 const_iterator end() const { 1488 return old_style_ ? const_iterator(deprecated_elements_->end()) 1489 : const_iterator(iterator(elements_->end())); 1490 } cbegin()1491 const_iterator cbegin() const { return begin(); } cend()1492 const_iterator cend() const { return end(); } 1493 1494 // Capacity size()1495 size_type size() const { 1496 return old_style_ ? deprecated_elements_->size() : elements_->size(); 1497 } empty()1498 bool empty() const { return size() == 0; } 1499 1500 // Element access 1501 T& operator[](const key_type& key) { 1502 value_type** value = 1503 old_style_ ? &(*deprecated_elements_)[key] : &(*elements_)[key]; 1504 if (*value == NULL) { 1505 *value = CreateValueTypeInternal(key); 1506 internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value, 1507 T>::Initialize((*value)->second, 1508 default_enum_value_); 1509 } 1510 return (*value)->second; 1511 } at(const key_type & key)1512 const T& at(const key_type& key) const { 1513 const_iterator it = find(key); 1514 GOOGLE_CHECK(it != end()); 1515 return it->second; 1516 } at(const key_type & key)1517 T& at(const key_type& key) { 1518 iterator it = find(key); 1519 GOOGLE_CHECK(it != end()); 1520 return it->second; 1521 } 1522 1523 // Lookup count(const key_type & key)1524 size_type count(const key_type& key) const { 1525 if (find(key) != end()) assert(key == find(key)->first); 1526 return find(key) == end() ? 0 : 1; 1527 } find(const key_type & key)1528 const_iterator find(const key_type& key) const { 1529 return old_style_ ? const_iterator(deprecated_elements_->find(key)) 1530 : const_iterator(iterator(elements_->find(key))); 1531 } find(const key_type & key)1532 iterator find(const key_type& key) { 1533 return old_style_ ? iterator(deprecated_elements_->find(key)) 1534 : iterator(elements_->find(key)); 1535 } equal_range(const key_type & key)1536 std::pair<const_iterator, const_iterator> equal_range( 1537 const key_type& key) const { 1538 const_iterator it = find(key); 1539 if (it == end()) { 1540 return std::pair<const_iterator, const_iterator>(it, it); 1541 } else { 1542 const_iterator begin = it++; 1543 return std::pair<const_iterator, const_iterator>(begin, it); 1544 } 1545 } equal_range(const key_type & key)1546 std::pair<iterator, iterator> equal_range(const key_type& key) { 1547 iterator it = find(key); 1548 if (it == end()) { 1549 return std::pair<iterator, iterator>(it, it); 1550 } else { 1551 iterator begin = it++; 1552 return std::pair<iterator, iterator>(begin, it); 1553 } 1554 } 1555 1556 // insert insert(const value_type & value)1557 std::pair<iterator, bool> insert(const value_type& value) { 1558 if (old_style_) { 1559 iterator it = find(value.first); 1560 if (it != end()) { 1561 return std::pair<iterator, bool>(it, false); 1562 } else { 1563 return std::pair<iterator, bool>( 1564 iterator(deprecated_elements_->insert(std::pair<Key, value_type*>( 1565 value.first, CreateValueTypeInternal(value))).first), true); 1566 } 1567 } else { 1568 std::pair<typename InnerMap::iterator, bool> p = 1569 elements_->insert(value.first); 1570 if (p.second) { 1571 p.first->value() = CreateValueTypeInternal(value); 1572 } 1573 return std::pair<iterator, bool>(iterator(p.first), p.second); 1574 } 1575 } 1576 template <class InputIt> insert(InputIt first,InputIt last)1577 void insert(InputIt first, InputIt last) { 1578 for (InputIt it = first; it != last; ++it) { 1579 iterator exist_it = find(it->first); 1580 if (exist_it == end()) { 1581 operator[](it->first) = it->second; 1582 } 1583 } 1584 } 1585 1586 // Erase and clear erase(const key_type & key)1587 size_type erase(const key_type& key) { 1588 iterator it = find(key); 1589 if (it == end()) { 1590 return 0; 1591 } else { 1592 erase(it); 1593 return 1; 1594 } 1595 } erase(iterator pos)1596 iterator erase(iterator pos) { 1597 if (arena_ == NULL) delete pos.operator->(); 1598 iterator i = pos++; 1599 if (old_style_) 1600 deprecated_elements_->erase(i.dit_); 1601 else 1602 elements_->erase(i.it_); 1603 return pos; 1604 } erase(iterator first,iterator last)1605 void erase(iterator first, iterator last) { 1606 while (first != last) { 1607 first = erase(first); 1608 } 1609 } clear()1610 void clear() { erase(begin(), end()); } 1611 1612 // Assign 1613 Map& operator=(const Map& other) { 1614 if (this != &other) { 1615 clear(); 1616 insert(other.begin(), other.end()); 1617 } 1618 return *this; 1619 } 1620 1621 // Access to hasher. Currently this returns a copy, but it may 1622 // be modified to return a const reference in the future. hash_function()1623 hasher hash_function() const { 1624 return old_style_ ? deprecated_elements_->hash_function() 1625 : elements_->hash_function(); 1626 } 1627 1628 private: 1629 // Set default enum value only for proto2 map field whose value is enum type. SetDefaultEnumValue(int default_enum_value)1630 void SetDefaultEnumValue(int default_enum_value) { 1631 default_enum_value_ = default_enum_value; 1632 } 1633 CreateValueTypeInternal(const Key & key)1634 value_type* CreateValueTypeInternal(const Key& key) { 1635 if (arena_ == NULL) { 1636 return new value_type(key); 1637 } else { 1638 value_type* value = reinterpret_cast<value_type*>( 1639 Arena::CreateArray<uint8>(arena_, sizeof(value_type))); 1640 Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_); 1641 Arena::CreateInArenaStorage(&value->second, arena_); 1642 const_cast<Key&>(value->first) = key; 1643 return value; 1644 } 1645 } 1646 CreateValueTypeInternal(const value_type & value)1647 value_type* CreateValueTypeInternal(const value_type& value) { 1648 if (arena_ == NULL) { 1649 return new value_type(value); 1650 } else { 1651 value_type* p = reinterpret_cast<value_type*>( 1652 Arena::CreateArray<uint8>(arena_, sizeof(value_type))); 1653 Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_); 1654 Arena::CreateInArenaStorage(&p->second, arena_); 1655 const_cast<Key&>(p->first) = value.first; 1656 p->second = value.second; 1657 return p; 1658 } 1659 } 1660 1661 Arena* arena_; 1662 int default_enum_value_; 1663 // The following is a tagged union because we support two map styles 1664 // for now. 1665 // TODO(gpike): get rid of the old style. 1666 const bool old_style_; 1667 union { 1668 InnerMap* elements_; 1669 DeprecatedInnerMap* deprecated_elements_; 1670 }; 1671 1672 friend class ::google::protobuf::Arena; 1673 typedef void InternalArenaConstructable_; 1674 typedef void DestructorSkippable_; 1675 template <typename K, typename V, 1676 internal::WireFormatLite::FieldType key_wire_type, 1677 internal::WireFormatLite::FieldType value_wire_type, 1678 int default_enum_value> 1679 friend class internal::MapFieldLite; 1680 }; 1681 1682 } // namespace protobuf 1683 } // namespace google 1684 1685 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START 1686 template<> 1687 struct hash<google::protobuf::MapKey> { 1688 size_t 1689 operator()(const google::protobuf::MapKey& map_key) const { 1690 switch (map_key.type()) { 1691 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: 1692 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: 1693 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: 1694 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: 1695 GOOGLE_LOG(FATAL) << "Unsupported"; 1696 break; 1697 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: 1698 return hash<string>()(map_key.GetStringValue()); 1699 case google::protobuf::FieldDescriptor::CPPTYPE_INT64: 1700 return hash< ::google::protobuf::int64>()(map_key.GetInt64Value()); 1701 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: 1702 return hash< ::google::protobuf::int32>()(map_key.GetInt32Value()); 1703 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: 1704 return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value()); 1705 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: 1706 return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value()); 1707 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: 1708 return hash<bool>()(map_key.GetBoolValue()); 1709 } 1710 GOOGLE_LOG(FATAL) << "Can't get here."; 1711 return 0; 1712 } 1713 bool 1714 operator()(const google::protobuf::MapKey& map_key1, 1715 const google::protobuf::MapKey& map_key2) const { 1716 return map_key1 < map_key2; 1717 } 1718 }; 1719 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END 1720 1721 #endif // GOOGLE_PROTOBUF_MAP_H__ 1722