| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 // This file defines the map container and its helpers to support protobuf maps. |
| 32 // |
| 33 // The Map and MapIterator types are provided by this header file. |
| 34 // Please avoid using other types defined here, unless they are public |
| 35 // types within Map or MapIterator, such as Map::value_type. |
| 36 |
| 31 #ifndef GOOGLE_PROTOBUF_MAP_H__ | 37 #ifndef GOOGLE_PROTOBUF_MAP_H__ |
| 32 #define GOOGLE_PROTOBUF_MAP_H__ | 38 #define GOOGLE_PROTOBUF_MAP_H__ |
| 33 | 39 |
| 34 #include <google/protobuf/stubs/hash.h> | 40 #include <google/protobuf/stubs/hash.h> |
| 35 #include <iterator> | 41 #include <iterator> |
| 36 #include <limits> // To support Visual Studio 2008 | 42 #include <limits> // To support Visual Studio 2008 |
| 37 #include <set> | 43 #include <set> |
| 38 #include <utility> | 44 #include <utility> |
| 39 | 45 |
| 40 #include <google/protobuf/stubs/common.h> | 46 #include <google/protobuf/stubs/common.h> |
| 41 #include <google/protobuf/arena.h> | 47 #include <google/protobuf/arena.h> |
| 42 #include <google/protobuf/generated_enum_util.h> | 48 #include <google/protobuf/generated_enum_util.h> |
| 43 #include <google/protobuf/map_type_handler.h> | 49 #include <google/protobuf/map_type_handler.h> |
| 44 #include <google/protobuf/message.h> | 50 #include <google/protobuf/message.h> |
| 45 #include <google/protobuf/descriptor.h> | 51 #include <google/protobuf/descriptor.h> |
| 46 #if __cpp_exceptions && LANG_CXX11 | 52 #if __cpp_exceptions && LANG_CXX11 |
| 47 #include <random> | 53 #include <random> |
| 48 #endif | 54 #endif |
| 49 | 55 |
| 50 namespace google { | 56 namespace google { |
| 51 namespace protobuf { | 57 namespace protobuf { |
| 52 | 58 |
| 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> | 59 template <typename Key, typename T> |
| 57 class Map; | 60 class Map; |
| 58 | 61 |
| 59 class MapIterator; | 62 class MapIterator; |
| 60 | 63 |
| 61 template <typename Enum> struct is_proto_enum; | 64 template <typename Enum> struct is_proto_enum; |
| 62 | 65 |
| 63 namespace internal { | 66 namespace internal { |
| 64 template <typename Key, typename T, | 67 template <typename Key, typename T, |
| 65 WireFormatLite::FieldType key_wire_type, | 68 WireFormatLite::FieldType key_wire_type, |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 typedef MapPair<Key, T> value_type; | 516 typedef MapPair<Key, T> value_type; |
| 514 | 517 |
| 515 typedef value_type* pointer; | 518 typedef value_type* pointer; |
| 516 typedef const value_type* const_pointer; | 519 typedef const value_type* const_pointer; |
| 517 typedef value_type& reference; | 520 typedef value_type& reference; |
| 518 typedef const value_type& const_reference; | 521 typedef const value_type& const_reference; |
| 519 | 522 |
| 520 typedef size_t size_type; | 523 typedef size_t size_type; |
| 521 typedef hash<Key> hasher; | 524 typedef hash<Key> hasher; |
| 522 | 525 |
| 523 Map(bool old_style = true) | 526 explicit Map(bool old_style = true) |
| 524 : arena_(NULL), | 527 : arena_(NULL), |
| 525 default_enum_value_(0), | 528 default_enum_value_(0), |
| 526 old_style_(old_style) { | 529 old_style_(old_style) { |
| 527 Init(); | 530 Init(); |
| 528 } | 531 } |
| 529 explicit Map(Arena* arena, bool old_style = true) | 532 explicit Map(Arena* arena, bool old_style = true) |
| 530 : arena_(arena), | 533 : arena_(arena), |
| 531 default_enum_value_(0), | 534 default_enum_value_(0), |
| 532 old_style_(old_style) { | 535 old_style_(old_style) { |
| 533 Init(); | 536 Init(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 555 delete deprecated_elements_; | 558 delete deprecated_elements_; |
| 556 else | 559 else |
| 557 delete elements_; | 560 delete elements_; |
| 558 } | 561 } |
| 559 } | 562 } |
| 560 | 563 |
| 561 private: | 564 private: |
| 562 void Init() { | 565 void Init() { |
| 563 if (old_style_) | 566 if (old_style_) |
| 564 deprecated_elements_ = Arena::Create<DeprecatedInnerMap>( | 567 deprecated_elements_ = Arena::Create<DeprecatedInnerMap>( |
| 565 arena_, 0, hasher(), equal_to<Key>(), | 568 arena_, 0, hasher(), std::equal_to<Key>(), |
| 566 MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_)); | 569 MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_)); |
| 567 else | 570 else |
| 568 elements_ = | 571 elements_ = |
| 569 Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_)); | 572 Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_)); |
| 570 } | 573 } |
| 571 | 574 |
| 572 // re-implement std::allocator to use arena allocator for memory allocation. | 575 // re-implement std::allocator to use arena allocator for memory allocation. |
| 573 // Used for google::protobuf::Map implementation. Users should not use this cl
ass | 576 // Used for google::protobuf::Map implementation. Users should not use this cl
ass |
| 574 // directly. | 577 // directly. |
| 575 template <typename U> | 578 template <typename U> |
| 576 class MapAllocator { | 579 class MapAllocator { |
| 577 public: | 580 public: |
| 578 typedef U value_type; | 581 typedef U value_type; |
| 579 typedef value_type* pointer; | 582 typedef value_type* pointer; |
| 580 typedef const value_type* const_pointer; | 583 typedef const value_type* const_pointer; |
| 581 typedef value_type& reference; | 584 typedef value_type& reference; |
| 582 typedef const value_type& const_reference; | 585 typedef const value_type& const_reference; |
| 583 typedef size_t size_type; | 586 typedef size_t size_type; |
| 584 typedef ptrdiff_t difference_type; | 587 typedef ptrdiff_t difference_type; |
| 585 | 588 |
| 586 MapAllocator() : arena_(NULL) {} | 589 MapAllocator() : arena_(NULL) {} |
| 587 explicit MapAllocator(Arena* arena) : arena_(arena) {} | 590 explicit MapAllocator(Arena* arena) : arena_(arena) {} |
| 588 template <typename X> | 591 template <typename X> |
| 589 MapAllocator(const MapAllocator<X>& allocator) | 592 MapAllocator(const MapAllocator<X>& allocator) |
| 590 : arena_(allocator.arena_) {} | 593 : arena_(allocator.arena()) {} |
| 591 | 594 |
| 592 pointer allocate(size_type n, const_pointer hint = 0) { | 595 pointer allocate(size_type n, const_pointer hint = 0) { |
| 593 // If arena is not given, malloc needs to be called which doesn't | 596 // If arena is not given, malloc needs to be called which doesn't |
| 594 // construct element object. | 597 // construct element object. |
| 595 if (arena_ == NULL) { | 598 if (arena_ == NULL) { |
| 596 return reinterpret_cast<pointer>(malloc(n * sizeof(value_type))); | 599 return static_cast<pointer>(::operator new(n * sizeof(value_type))); |
| 597 } else { | 600 } else { |
| 598 return reinterpret_cast<pointer>( | 601 return reinterpret_cast<pointer>( |
| 599 Arena::CreateArray<uint8>(arena_, n * sizeof(value_type))); | 602 Arena::CreateArray<uint8>(arena_, n * sizeof(value_type))); |
| 600 } | 603 } |
| 601 } | 604 } |
| 602 | 605 |
| 603 void deallocate(pointer p, size_type n) { | 606 void deallocate(pointer p, size_type n) { |
| 604 if (arena_ == NULL) { | 607 if (arena_ == NULL) { |
| 605 free(p); | 608 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) |
| 609 ::operator delete(p, n * sizeof(value_type)); |
| 610 #else |
| 611 ::operator delete(p); |
| 612 #endif |
| 606 } | 613 } |
| 607 } | 614 } |
| 608 | 615 |
| 609 #if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ | 616 #if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ |
| 610 !defined(GOOGLE_PROTOBUF_OS_NACL) && \ | 617 !defined(GOOGLE_PROTOBUF_OS_NACL) && \ |
| 611 !defined(GOOGLE_PROTOBUF_OS_ANDROID) && \ | 618 !defined(GOOGLE_PROTOBUF_OS_ANDROID) && \ |
| 612 !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) | 619 !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) |
| 613 template<class NodeType, class... Args> | 620 template<class NodeType, class... Args> |
| 614 void construct(NodeType* p, Args&&... args) { | 621 void construct(NodeType* p, Args&&... args) { |
| 615 // Clang 3.6 doesn't compile static casting to void* directly. (Issue | 622 // Clang 3.6 doesn't compile static casting to void* directly. (Issue |
| (...skipping 27 matching lines...) Expand all Loading... |
| 643 template <typename X> | 650 template <typename X> |
| 644 bool operator!=(const MapAllocator<X>& other) const { | 651 bool operator!=(const MapAllocator<X>& other) const { |
| 645 return arena_ != other.arena_; | 652 return arena_ != other.arena_; |
| 646 } | 653 } |
| 647 | 654 |
| 648 // To support Visual Studio 2008 | 655 // To support Visual Studio 2008 |
| 649 size_type max_size() const { | 656 size_type max_size() const { |
| 650 return std::numeric_limits<size_type>::max(); | 657 return std::numeric_limits<size_type>::max(); |
| 651 } | 658 } |
| 652 | 659 |
| 660 // To support gcc-4.4, which does not properly |
| 661 // support templated friend classes |
| 662 Arena* arena() const { |
| 663 return arena_; |
| 664 } |
| 665 |
| 653 private: | 666 private: |
| 654 typedef void DestructorSkippable_; | 667 typedef void DestructorSkippable_; |
| 655 Arena* const arena_; | 668 Arena* const arena_; |
| 656 | |
| 657 template <typename X> | |
| 658 friend class MapAllocator; | |
| 659 }; | 669 }; |
| 660 | 670 |
| 661 // InnerMap's key type is Key and its value type is value_type*. We use a | 671 // 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, | 672 // 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 | 673 // allowing safe conversion from pointer to Node to pointer to Key, and vice |
| 664 // versa when appropriate. | 674 // versa when appropriate. |
| 665 class KeyValuePair { | 675 class KeyValuePair { |
| 666 public: | 676 public: |
| 667 KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {} | 677 KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {} |
| 668 | 678 |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 Node* next = node->next; | 1250 Node* next = node->next; |
| 1241 node->next = NULL; | 1251 node->next = NULL; |
| 1242 node = next; | 1252 node = next; |
| 1243 } | 1253 } |
| 1244 return count; | 1254 return count; |
| 1245 } | 1255 } |
| 1246 | 1256 |
| 1247 // Return whether table_[b] is a linked list that seems awfully long. | 1257 // Return whether table_[b] is a linked list that seems awfully long. |
| 1248 // Requires table_[b] to point to a non-empty linked list. | 1258 // Requires table_[b] to point to a non-empty linked list. |
| 1249 bool TableEntryIsTooLong(size_type b) { | 1259 bool TableEntryIsTooLong(size_type b) { |
| 1250 const int kMaxLength = 8; | 1260 const size_type kMaxLength = 8; |
| 1251 size_type count = 0; | 1261 size_type count = 0; |
| 1252 Node* node = static_cast<Node*>(table_[b]); | 1262 Node* node = static_cast<Node*>(table_[b]); |
| 1253 do { | 1263 do { |
| 1254 ++count; | 1264 ++count; |
| 1255 node = node->next; | 1265 node = node->next; |
| 1256 } while (node != NULL); | 1266 } while (node != NULL); |
| 1257 // Invariant: no linked list ever is more than kMaxLength in length. | 1267 // Invariant: no linked list ever is more than kMaxLength in length. |
| 1258 GOOGLE_DCHECK_LE(count, kMaxLength); | 1268 GOOGLE_DCHECK_LE(count, kMaxLength); |
| 1259 return count >= kMaxLength; | 1269 return count >= kMaxLength; |
| 1260 } | 1270 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 | 1348 |
| 1339 size_type num_elements_; | 1349 size_type num_elements_; |
| 1340 size_type num_buckets_; | 1350 size_type num_buckets_; |
| 1341 size_type seed_; | 1351 size_type seed_; |
| 1342 size_type index_of_first_non_null_; | 1352 size_type index_of_first_non_null_; |
| 1343 void** table_; // an array with num_buckets_ entries | 1353 void** table_; // an array with num_buckets_ entries |
| 1344 Allocator alloc_; | 1354 Allocator alloc_; |
| 1345 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); | 1355 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); |
| 1346 }; // end of class InnerMap | 1356 }; // end of class InnerMap |
| 1347 | 1357 |
| 1348 typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, | 1358 typedef hash_map<Key, value_type*, hash<Key>, std::equal_to<Key>, |
| 1349 MapAllocator<std::pair<const Key, MapPair<Key, T>*> > > | 1359 MapAllocator<std::pair<const Key, MapPair<Key, T>*> > > |
| 1350 DeprecatedInnerMap; | 1360 DeprecatedInnerMap; |
| 1351 | 1361 |
| 1352 public: | 1362 public: |
| 1353 // Iterators | 1363 // Iterators |
| 1354 class iterator_base { | 1364 class iterator_base { |
| 1355 public: | 1365 public: |
| 1356 // We support "old style" and "new style" iterators for now. This is | 1366 // We support "old style" and "new style" iterators for now. This is |
| 1357 // temporary. Also, for "iterator()" we have an unknown category. | 1367 // temporary. Also, for "iterator()" we have an unknown category. |
| 1358 // TODO(gpike): get rid of this. | 1368 // TODO(gpike): get rid of this. |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 | 1621 |
| 1612 // Assign | 1622 // Assign |
| 1613 Map& operator=(const Map& other) { | 1623 Map& operator=(const Map& other) { |
| 1614 if (this != &other) { | 1624 if (this != &other) { |
| 1615 clear(); | 1625 clear(); |
| 1616 insert(other.begin(), other.end()); | 1626 insert(other.begin(), other.end()); |
| 1617 } | 1627 } |
| 1618 return *this; | 1628 return *this; |
| 1619 } | 1629 } |
| 1620 | 1630 |
| 1631 void swap(Map& other) { |
| 1632 if (arena_ == other.arena_ && old_style_ == other.old_style_) { |
| 1633 std::swap(default_enum_value_, other.default_enum_value_); |
| 1634 if (old_style_) { |
| 1635 std::swap(deprecated_elements_, other.deprecated_elements_); |
| 1636 } else { |
| 1637 std::swap(elements_, other.elements_); |
| 1638 } |
| 1639 } else { |
| 1640 // TODO(zuguang): optimize this. The temporary copy can be allocated |
| 1641 // in the same arena as the other message, and the "other = copy" can |
| 1642 // be replaced with the fast-path swap above. |
| 1643 Map copy = *this; |
| 1644 *this = other; |
| 1645 other = copy; |
| 1646 } |
| 1647 } |
| 1648 |
| 1621 // Access to hasher. Currently this returns a copy, but it may | 1649 // Access to hasher. Currently this returns a copy, but it may |
| 1622 // be modified to return a const reference in the future. | 1650 // be modified to return a const reference in the future. |
| 1623 hasher hash_function() const { | 1651 hasher hash_function() const { |
| 1624 return old_style_ ? deprecated_elements_->hash_function() | 1652 return old_style_ ? deprecated_elements_->hash_function() |
| 1625 : elements_->hash_function(); | 1653 : elements_->hash_function(); |
| 1626 } | 1654 } |
| 1627 | 1655 |
| 1628 private: | 1656 private: |
| 1629 // Set default enum value only for proto2 map field whose value is enum type. | 1657 // Set default enum value only for proto2 map field whose value is enum type. |
| 1630 void SetDefaultEnumValue(int default_enum_value) { | 1658 void SetDefaultEnumValue(int default_enum_value) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1712 } | 1740 } |
| 1713 bool | 1741 bool |
| 1714 operator()(const google::protobuf::MapKey& map_key1, | 1742 operator()(const google::protobuf::MapKey& map_key1, |
| 1715 const google::protobuf::MapKey& map_key2) const { | 1743 const google::protobuf::MapKey& map_key2) const { |
| 1716 return map_key1 < map_key2; | 1744 return map_key1 < map_key2; |
| 1717 } | 1745 } |
| 1718 }; | 1746 }; |
| 1719 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END | 1747 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END |
| 1720 | 1748 |
| 1721 #endif // GOOGLE_PROTOBUF_MAP_H__ | 1749 #endif // GOOGLE_PROTOBUF_MAP_H__ |
| OLD | NEW |