| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 #include <string> | 54 #include <string> |
| 55 #include <iterator> | 55 #include <iterator> |
| 56 #include <google/protobuf/stubs/casts.h> | 56 #include <google/protobuf/stubs/casts.h> |
| 57 #include <google/protobuf/stubs/logging.h> | 57 #include <google/protobuf/stubs/logging.h> |
| 58 #include <google/protobuf/stubs/common.h> | 58 #include <google/protobuf/stubs/common.h> |
| 59 #include <google/protobuf/stubs/type_traits.h> | 59 #include <google/protobuf/stubs/type_traits.h> |
| 60 #include <google/protobuf/arena.h> | 60 #include <google/protobuf/arena.h> |
| 61 #include <google/protobuf/generated_message_util.h> | 61 #include <google/protobuf/generated_message_util.h> |
| 62 #include <google/protobuf/message_lite.h> | 62 #include <google/protobuf/message_lite.h> |
| 63 | 63 |
| 64 |
| 65 // Forward-declare these so that we can make them friends. |
| 64 namespace google { | 66 namespace google { |
| 65 | |
| 66 namespace upb { | 67 namespace upb { |
| 67 namespace google_opensource { | 68 namespace google_opensource { |
| 68 class GMR_Handlers; | 69 class GMR_Handlers; |
| 69 } // namespace google_opensource | 70 } // namespace google_opensource |
| 70 } // namespace upb | 71 } // namespace upb |
| 71 | 72 |
| 72 namespace protobuf { | 73 namespace protobuf { |
| 73 | 74 |
| 74 class Message; | 75 class Message; |
| 75 | 76 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 97 return CalculateReserve(begin, end, Category()); | 98 return CalculateReserve(begin, end, Category()); |
| 98 } | 99 } |
| 99 } // namespace internal | 100 } // namespace internal |
| 100 | 101 |
| 101 | 102 |
| 102 // RepeatedField is used to represent repeated fields of a primitive type (in | 103 // RepeatedField is used to represent repeated fields of a primitive type (in |
| 103 // other words, everything except strings and nested Messages). Most users will | 104 // other words, everything except strings and nested Messages). Most users will |
| 104 // not ever use a RepeatedField directly; they will use the get-by-index, | 105 // not ever use a RepeatedField directly; they will use the get-by-index, |
| 105 // set-by-index, and add accessors that are generated for all repeated fields. | 106 // set-by-index, and add accessors that are generated for all repeated fields. |
| 106 template <typename Element> | 107 template <typename Element> |
| 107 class RepeatedField { | 108 class RepeatedField PROTOBUF_FINAL { |
| 108 public: | 109 public: |
| 109 RepeatedField(); | 110 RepeatedField(); |
| 110 explicit RepeatedField(Arena* arena); | 111 explicit RepeatedField(Arena* arena); |
| 111 RepeatedField(const RepeatedField& other); | 112 RepeatedField(const RepeatedField& other); |
| 112 template <typename Iter> | 113 template <typename Iter> |
| 113 RepeatedField(Iter begin, const Iter& end); | 114 RepeatedField(Iter begin, const Iter& end); |
| 114 ~RepeatedField(); | 115 ~RepeatedField(); |
| 115 | 116 |
| 116 RepeatedField& operator=(const RepeatedField& other); | 117 RepeatedField& operator=(const RepeatedField& other); |
| 117 | 118 |
| 118 bool empty() const; | 119 bool empty() const; |
| 119 int size() const; | 120 int size() const; |
| 120 | 121 |
| 121 const Element& Get(int index) const; | 122 const Element& Get(int index) const; |
| 122 Element* Mutable(int index); | 123 Element* Mutable(int index); |
| 124 |
| 125 const Element& operator[](int index) const { return Get(index); } |
| 126 Element& operator[](int index) { return *Mutable(index); } |
| 127 |
| 123 void Set(int index, const Element& value); | 128 void Set(int index, const Element& value); |
| 124 void Add(const Element& value); | 129 void Add(const Element& value); |
| 130 // Appends a new element and return a pointer to it. |
| 131 // The new element is uninitialized if |Element| is a POD type. |
| 125 Element* Add(); | 132 Element* Add(); |
| 126 // Remove the last element in the array. | 133 // Remove the last element in the array. |
| 127 void RemoveLast(); | 134 void RemoveLast(); |
| 128 | 135 |
| 129 // Extract elements with indices in "[start .. start+num-1]". | 136 // Extract elements with indices in "[start .. start+num-1]". |
| 130 // Copy them into "elements[0 .. num-1]" if "elements" is not NULL. | 137 // Copy them into "elements[0 .. num-1]" if "elements" is not NULL. |
| 131 // Caution: implementation also moves elements with indices [start+num ..]. | 138 // Caution: implementation also moves elements with indices [start+num ..]. |
| 132 // Calling this routine inside a loop can cause quadratic behavior. | 139 // Calling this routine inside a loop can cause quadratic behavior. |
| 133 void ExtractSubrange(int start, int num, Element* elements); | 140 void ExtractSubrange(int start, int num, Element* elements); |
| 134 | 141 |
| 135 void Clear(); | 142 void Clear(); |
| 136 void MergeFrom(const RepeatedField& other); | 143 void MergeFrom(const RepeatedField& other); |
| 137 void CopyFrom(const RepeatedField& other); | 144 void CopyFrom(const RepeatedField& other); |
| 138 | 145 |
| 139 // Reserve space to expand the field to at least the given size. If the | 146 // Reserve space to expand the field to at least the given size. If the |
| 140 // array is grown, it will always be at least doubled in size. | 147 // array is grown, it will always be at least doubled in size. |
| 141 void Reserve(int new_size); | 148 void Reserve(int new_size); |
| 142 | 149 |
| 143 // Resize the RepeatedField to a new, smaller size. This is O(1). | 150 // Resize the RepeatedField to a new, smaller size. This is O(1). |
| 144 void Truncate(int new_size); | 151 void Truncate(int new_size); |
| 145 | 152 |
| 146 void AddAlreadyReserved(const Element& value); | 153 void AddAlreadyReserved(const Element& value); |
| 154 // Appends a new element and return a pointer to it. |
| 155 // The new element is uninitialized if |Element| is a POD type. |
| 156 // Should be called only if Capacity() > Size(). |
| 147 Element* AddAlreadyReserved(); | 157 Element* AddAlreadyReserved(); |
| 148 int Capacity() const; | 158 int Capacity() const; |
| 149 | 159 |
| 150 // Like STL resize. Uses value to fill appended elements. | 160 // Like STL resize. Uses value to fill appended elements. |
| 151 // Like Truncate() if new_size <= size(), otherwise this is | 161 // Like Truncate() if new_size <= size(), otherwise this is |
| 152 // O(new_size - size()). | 162 // O(new_size - size()). |
| 153 void Resize(int new_size, const Element& value); | 163 void Resize(int new_size, const Element& value); |
| 154 | 164 |
| 155 // Gets the underlying array. This pointer is possibly invalidated by | 165 // Gets the underlying array. This pointer is possibly invalidated by |
| 156 // any add or remove operation. | 166 // any add or remove operation. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 // If Element has a trivial destructor (for example, if it's a fundamental | 287 // If Element has a trivial destructor (for example, if it's a fundamental |
| 278 // type, like int32), the loop will be removed by the optimizer. | 288 // type, like int32), the loop will be removed by the optimizer. |
| 279 void InternalDeallocate(Rep* rep, int size) { | 289 void InternalDeallocate(Rep* rep, int size) { |
| 280 if (rep != NULL) { | 290 if (rep != NULL) { |
| 281 Element* e = &rep->elements[0]; | 291 Element* e = &rep->elements[0]; |
| 282 Element* limit = &rep->elements[size]; | 292 Element* limit = &rep->elements[size]; |
| 283 for (; e < limit; e++) { | 293 for (; e < limit; e++) { |
| 284 e->Element::~Element(); | 294 e->Element::~Element(); |
| 285 } | 295 } |
| 286 if (rep->arena == NULL) { | 296 if (rep->arena == NULL) { |
| 287 delete[] reinterpret_cast<char*>(rep); | 297 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) |
| 298 const size_t bytes = size * sizeof(*e) + kRepHeaderSize; |
| 299 ::operator delete(static_cast<void*>(rep), bytes); |
| 300 #else |
| 301 ::operator delete(static_cast<void*>(rep)); |
| 302 #endif |
| 288 } | 303 } |
| 289 } | 304 } |
| 290 } | 305 } |
| 291 }; | 306 }; |
| 292 | 307 |
| 293 template<typename Element> | 308 template<typename Element> |
| 294 const size_t RepeatedField<Element>::kRepHeaderSize = | 309 const size_t RepeatedField<Element>::kRepHeaderSize = |
| 295 reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16; | 310 reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16; |
| 296 | 311 |
| 297 namespace internal { | 312 namespace internal { |
| 298 template <typename It> class RepeatedPtrIterator; | 313 template <typename It> class RepeatedPtrIterator; |
| 299 template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator; | 314 template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator; |
| 300 } // namespace internal | 315 } // namespace internal |
| 301 | 316 |
| 302 namespace internal { | 317 namespace internal { |
| 303 | 318 |
| 304 // This is a helper template to copy an array of elements effeciently when they | 319 // This is a helper template to copy an array of elements efficiently when they |
| 305 // have a trivial copy constructor, and correctly otherwise. This really | 320 // have a trivial copy constructor, and correctly otherwise. This really |
| 306 // shouldn't be necessary, but our compiler doesn't optimize std::copy very | 321 // shouldn't be necessary, but our compiler doesn't optimize std::copy very |
| 307 // effectively. | 322 // effectively. |
| 308 template <typename Element, | 323 template <typename Element, |
| 309 bool HasTrivialCopy = has_trivial_copy<Element>::value> | 324 bool HasTrivialCopy = has_trivial_copy<Element>::value> |
| 310 struct ElementCopier { | 325 struct ElementCopier { |
| 311 void operator()(Element* to, const Element* from, int array_size); | 326 void operator()(Element* to, const Element* from, int array_size); |
| 312 }; | 327 }; |
| 313 | 328 |
| 314 } // namespace internal | 329 } // namespace internal |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 }; | 572 }; |
| 558 | 573 |
| 559 template <typename GenericType> | 574 template <typename GenericType> |
| 560 class GenericTypeHandler { | 575 class GenericTypeHandler { |
| 561 public: | 576 public: |
| 562 typedef GenericType Type; | 577 typedef GenericType Type; |
| 563 static inline GenericType* New(Arena* arena) { | 578 static inline GenericType* New(Arena* arena) { |
| 564 return ::google::protobuf::Arena::CreateMaybeMessage<Type>( | 579 return ::google::protobuf::Arena::CreateMaybeMessage<Type>( |
| 565 arena, static_cast<GenericType*>(0)); | 580 arena, static_cast<GenericType*>(0)); |
| 566 } | 581 } |
| 567 // We force NewFromPrototype() and Delete() to be non-inline to reduce code | 582 // We force NewFromPrototype() to be non-inline to reduce code size: |
| 568 // size: else, several other methods get inlined copies of message types' | 583 // else, several other methods get inlined copies of message types' |
| 569 // constructors and destructors. | 584 // constructors. |
| 570 GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype( | 585 GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype( |
| 571 const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); | 586 const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); |
| 572 GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena)
; | 587 static inline void Delete(GenericType* value, Arena* arena) { |
| 588 if (arena == NULL) { |
| 589 delete value; |
| 590 } |
| 591 } |
| 573 static inline ::google::protobuf::Arena* GetArena(GenericType* value) { | 592 static inline ::google::protobuf::Arena* GetArena(GenericType* value) { |
| 574 return ::google::protobuf::Arena::GetArena<Type>(value); | 593 return ::google::protobuf::Arena::GetArena<Type>(value); |
| 575 } | 594 } |
| 576 static inline void* GetMaybeArenaPointer(GenericType* value) { | 595 static inline void* GetMaybeArenaPointer(GenericType* value) { |
| 577 return ::google::protobuf::Arena::GetArena<Type>(value); | 596 return ::google::protobuf::Arena::GetArena<Type>(value); |
| 578 } | 597 } |
| 579 | 598 |
| 580 static inline void Clear(GenericType* value) { value->Clear(); } | 599 static inline void Clear(GenericType* value) { value->Clear(); } |
| 581 GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from, | 600 GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from, |
| 582 GenericType* to); | 601 GenericType* to); |
| 583 static inline int SpaceUsed(const GenericType& value) { | 602 static inline int SpaceUsed(const GenericType& value) { |
| 584 return value.SpaceUsed(); | 603 return value.SpaceUsed(); |
| 585 } | 604 } |
| 586 static inline const Type& default_instance() { | 605 static inline const Type& default_instance() { |
| 587 return Type::default_instance(); | 606 return Type::default_instance(); |
| 588 } | 607 } |
| 589 }; | 608 }; |
| 590 | 609 |
| 591 template <typename GenericType> | 610 template <typename GenericType> |
| 592 GenericType* GenericTypeHandler<GenericType>::NewFromPrototype( | 611 GenericType* GenericTypeHandler<GenericType>::NewFromPrototype( |
| 593 const GenericType* /* prototype */, ::google::protobuf::Arena* arena) { | 612 const GenericType* /* prototype */, ::google::protobuf::Arena* arena) { |
| 594 return New(arena); | 613 return New(arena); |
| 595 } | 614 } |
| 596 template <typename GenericType> | 615 template <typename GenericType> |
| 597 void GenericTypeHandler<GenericType>::Delete(GenericType* value, Arena* arena) { | |
| 598 if (arena == NULL) { | |
| 599 delete value; | |
| 600 } | |
| 601 } | |
| 602 template <typename GenericType> | |
| 603 void GenericTypeHandler<GenericType>::Merge(const GenericType& from, | 616 void GenericTypeHandler<GenericType>::Merge(const GenericType& from, |
| 604 GenericType* to) { | 617 GenericType* to) { |
| 605 to->MergeFrom(from); | 618 to->MergeFrom(from); |
| 606 } | 619 } |
| 607 | 620 |
| 608 // NewFromPrototype() and Merge() cannot be defined here; if they're declared | 621 // NewFromPrototype() and Merge() cannot be defined here; if they're declared |
| 609 // inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLIN
E | 622 // inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLIN
E |
| 610 // above, and if not, compilation will result in multiple definitions. These | 623 // above, and if not, compilation will result in multiple definitions. These |
| 611 // are therefore declared as specializations here and defined in | 624 // are therefore declared as specializations here and defined in |
| 612 // message_lite.cc. | 625 // message_lite.cc. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 | 679 |
| 667 template <> | 680 template <> |
| 668 inline const Message& GenericTypeHandler<Message>::default_instance() { | 681 inline const Message& GenericTypeHandler<Message>::default_instance() { |
| 669 // Yes, the behavior of the code is undefined, but this function is only | 682 // Yes, the behavior of the code is undefined, but this function is only |
| 670 // called when we're already deep into the world of undefined, because the | 683 // called when we're already deep into the world of undefined, because the |
| 671 // caller called Get(index) out of bounds. | 684 // caller called Get(index) out of bounds. |
| 672 Message* null = NULL; | 685 Message* null = NULL; |
| 673 return *null; | 686 return *null; |
| 674 } | 687 } |
| 675 | 688 |
| 676 | 689 class LIBPROTOBUF_EXPORT StringTypeHandler { |
| 677 // HACK: If a class is declared as DLL-exported in MSVC, it insists on | |
| 678 // generating copies of all its methods -- even inline ones -- to include | |
| 679 // in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which | |
| 680 // isn't in the lite library, therefore the lite library cannot link if | |
| 681 // StringTypeHandler is exported. So, we factor out StringTypeHandlerBase, | |
| 682 // export that, then make StringTypeHandler be a subclass which is NOT | |
| 683 // exported. | |
| 684 // TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite | |
| 685 // library, this can be cleaned up. | |
| 686 class LIBPROTOBUF_EXPORT StringTypeHandlerBase { | |
| 687 public: | 690 public: |
| 688 typedef string Type; | 691 typedef string Type; |
| 689 | 692 |
| 690 static inline string* New(Arena* arena) { | 693 static inline string* New(Arena* arena) { |
| 691 return Arena::Create<string>(arena); | 694 return Arena::Create<string>(arena); |
| 692 } | 695 } |
| 693 static inline string* NewFromPrototype(const string*, | 696 static inline string* NewFromPrototype(const string*, |
| 694 ::google::protobuf::Arena* arena) { | 697 ::google::protobuf::Arena* arena) { |
| 695 return New(arena); | 698 return New(arena); |
| 696 } | 699 } |
| 697 static inline ::google::protobuf::Arena* GetArena(string*) { | 700 static inline ::google::protobuf::Arena* GetArena(string*) { |
| 698 return NULL; | 701 return NULL; |
| 699 } | 702 } |
| 700 static inline void* GetMaybeArenaPointer(string* /* value */) { | 703 static inline void* GetMaybeArenaPointer(string* /* value */) { |
| 701 return NULL; | 704 return NULL; |
| 702 } | 705 } |
| 703 static inline void Delete(string* value, Arena* arena) { | 706 static inline void Delete(string* value, Arena* arena) { |
| 704 if (arena == NULL) { | 707 if (arena == NULL) { |
| 705 delete value; | 708 delete value; |
| 706 } | 709 } |
| 707 } | 710 } |
| 708 static inline void Clear(string* value) { value->clear(); } | 711 static inline void Clear(string* value) { value->clear(); } |
| 709 static inline void Merge(const string& from, string* to) { *to = from; } | 712 static inline void Merge(const string& from, string* to) { *to = from; } |
| 710 static inline const Type& default_instance() { | 713 static inline const Type& default_instance() { |
| 711 return ::google::protobuf::internal::GetEmptyString(); | 714 return ::google::protobuf::internal::GetEmptyString(); |
| 712 } | 715 } |
| 713 }; | |
| 714 | |
| 715 class StringTypeHandler : public StringTypeHandlerBase { | |
| 716 public: | |
| 717 static int SpaceUsed(const string& value) { | 716 static int SpaceUsed(const string& value) { |
| 718 return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value)
; | 717 return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value)
; |
| 719 } | 718 } |
| 720 }; | 719 }; |
| 721 | 720 |
| 722 | 721 |
| 723 } // namespace internal | 722 } // namespace internal |
| 724 | 723 |
| 725 // RepeatedPtrField is like RepeatedField, but used for repeated strings or | 724 // RepeatedPtrField is like RepeatedField, but used for repeated strings or |
| 726 // Messages. | 725 // Messages. |
| 727 template <typename Element> | 726 template <typename Element> |
| 728 class RepeatedPtrField : public internal::RepeatedPtrFieldBase { | 727 class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { |
| 729 public: | 728 public: |
| 730 RepeatedPtrField(); | 729 RepeatedPtrField(); |
| 731 explicit RepeatedPtrField(::google::protobuf::Arena* arena); | 730 explicit RepeatedPtrField(::google::protobuf::Arena* arena); |
| 732 | 731 |
| 733 RepeatedPtrField(const RepeatedPtrField& other); | 732 RepeatedPtrField(const RepeatedPtrField& other); |
| 734 template <typename Iter> | 733 template <typename Iter> |
| 735 RepeatedPtrField(Iter begin, const Iter& end); | 734 RepeatedPtrField(Iter begin, const Iter& end); |
| 736 ~RepeatedPtrField(); | 735 ~RepeatedPtrField(); |
| 737 | 736 |
| 738 RepeatedPtrField& operator=(const RepeatedPtrField& other); | 737 RepeatedPtrField& operator=(const RepeatedPtrField& other); |
| 739 | 738 |
| 740 bool empty() const; | 739 bool empty() const; |
| 741 int size() const; | 740 int size() const; |
| 742 | 741 |
| 743 const Element& Get(int index) const; | 742 const Element& Get(int index) const; |
| 744 Element* Mutable(int index); | 743 Element* Mutable(int index); |
| 745 Element* Add(); | 744 Element* Add(); |
| 746 | 745 |
| 746 const Element& operator[](int index) const { return Get(index); } |
| 747 Element& operator[](int index) { return *Mutable(index); } |
| 748 |
| 747 // Remove the last element in the array. | 749 // Remove the last element in the array. |
| 748 // Ownership of the element is retained by the array. | 750 // Ownership of the element is retained by the array. |
| 749 void RemoveLast(); | 751 void RemoveLast(); |
| 750 | 752 |
| 751 // Delete elements with indices in the range [start .. start+num-1]. | 753 // Delete elements with indices in the range [start .. start+num-1]. |
| 752 // Caution: implementation moves all elements with indices [start+num .. ]. | 754 // Caution: implementation moves all elements with indices [start+num .. ]. |
| 753 // Calling this routine inside a loop can cause quadratic behavior. | 755 // Calling this routine inside a loop can cause quadratic behavior. |
| 754 void DeleteSubrange(int start, int num); | 756 void DeleteSubrange(int start, int num); |
| 755 | 757 |
| 756 void Clear(); | 758 void Clear(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 // If this RepeatedPtrField is on an arena, an object copy is required to pass | 856 // If this RepeatedPtrField is on an arena, an object copy is required to pass |
| 855 // ownership back to the user (for compatible semantics). Use | 857 // ownership back to the user (for compatible semantics). Use |
| 856 // UnsafeArenaReleaseLast() if this behavior is undesired. | 858 // UnsafeArenaReleaseLast() if this behavior is undesired. |
| 857 Element* ReleaseLast(); | 859 Element* ReleaseLast(); |
| 858 | 860 |
| 859 // Add an already-allocated object, skipping arena-ownership checks. The user | 861 // Add an already-allocated object, skipping arena-ownership checks. The user |
| 860 // must guarantee that the given object is in the same arena as this | 862 // must guarantee that the given object is in the same arena as this |
| 861 // RepeatedPtrField. | 863 // RepeatedPtrField. |
| 862 // It is also useful in legacy code that uses temporary ownership to avoid | 864 // It is also useful in legacy code that uses temporary ownership to avoid |
| 863 // copies. Example: | 865 // copies. Example: |
| 864 // RepeatedPtrField<T> temp_field; | 866 // RepeatedPtrField<T> temp_field; |
| 865 // temp_field.AddAllocated(new T); | 867 // temp_field.AddAllocated(new T); |
| 866 // ... // Do something with temp_field | 868 // ... // Do something with temp_field |
| 867 // temp_field.ExtractSubrange(0, temp_field.size(), NULL); | 869 // temp_field.ExtractSubrange(0, temp_field.size(), NULL); |
| 868 // If you put temp_field on the arena this fails, because the ownership | 870 // If you put temp_field on the arena this fails, because the ownership |
| 869 // transfers to the arena at the "AddAllocated" call and is not released | 871 // transfers to the arena at the "AddAllocated" call and is not released |
| 870 // anymore causing a double delete. UnsafeArenaAddAllocated prevents this. | 872 // anymore causing a double delete. UnsafeArenaAddAllocated prevents this. |
| 871 void UnsafeArenaAddAllocated(Element* value); | 873 void UnsafeArenaAddAllocated(Element* value); |
| 872 | 874 |
| 873 // Remove the last element and return it. Works only when operating on an | 875 // Remove the last element and return it. Works only when operating on an |
| 874 // arena. The returned pointer is to the original object in the arena, hence | 876 // arena. The returned pointer is to the original object in the arena, hence |
| 875 // has the arena's lifetime. | 877 // has the arena's lifetime. |
| 876 // Requires: current_size_ > 0 | 878 // Requires: current_size_ > 0 |
| 877 Element* UnsafeArenaReleaseLast(); | 879 Element* UnsafeArenaReleaseLast(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 // Returns an iterator to the element immediately following the removed range. | 941 // Returns an iterator to the element immediately following the removed range. |
| 940 // | 942 // |
| 941 // Invalidates all iterators at or after the removed range, including end(). | 943 // Invalidates all iterators at or after the removed range, including end(). |
| 942 iterator erase(const_iterator first, const_iterator last); | 944 iterator erase(const_iterator first, const_iterator last); |
| 943 | 945 |
| 944 // Gets the arena on which this RepeatedPtrField stores its elements. | 946 // Gets the arena on which this RepeatedPtrField stores its elements. |
| 945 ::google::protobuf::Arena* GetArena() const { | 947 ::google::protobuf::Arena* GetArena() const { |
| 946 return GetArenaNoVirtual(); | 948 return GetArenaNoVirtual(); |
| 947 } | 949 } |
| 948 | 950 |
| 949 protected: | 951 private: |
| 950 // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only | 952 // Note: RepeatedPtrField SHOULD NOT be subclassed by users. |
| 951 // subclass it in one place as a hack for compatibility with proto1. The | |
| 952 // subclass needs to know about TypeHandler in order to call protected | |
| 953 // methods on RepeatedPtrFieldBase. | |
| 954 class TypeHandler; | 953 class TypeHandler; |
| 955 | 954 |
| 956 // Internal arena accessor expected by helpers in Arena. | 955 // Internal arena accessor expected by helpers in Arena. |
| 957 inline Arena* GetArenaNoVirtual() const; | 956 inline Arena* GetArenaNoVirtual() const; |
| 958 | 957 |
| 959 private: | |
| 960 // Implementations for ExtractSubrange(). The copying behavior must be | 958 // Implementations for ExtractSubrange(). The copying behavior must be |
| 961 // included only if the type supports the necessary operations (e.g., | 959 // included only if the type supports the necessary operations (e.g., |
| 962 // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() | 960 // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() |
| 963 // uses SFINAE to choose one of the below implementations. | 961 // uses SFINAE to choose one of the below implementations. |
| 964 void ExtractSubrangeInternal(int start, int num, Element** elements, | 962 void ExtractSubrangeInternal(int start, int num, Element** elements, |
| 965 google::protobuf::internal::true_type); | 963 google::protobuf::internal::true_type); |
| 966 void ExtractSubrangeInternal(int start, int num, Element** elements, | 964 void ExtractSubrangeInternal(int start, int num, Element** elements, |
| 967 google::protobuf::internal::false_type); | 965 google::protobuf::internal::false_type); |
| 968 | 966 |
| 969 friend class Arena; | 967 friend class Arena; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 992 ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize)); | 990 ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize)); |
| 993 rep_->arena = arena; | 991 rep_->arena = arena; |
| 994 } | 992 } |
| 995 } | 993 } |
| 996 | 994 |
| 997 template <typename Element> | 995 template <typename Element> |
| 998 inline RepeatedField<Element>::RepeatedField(const RepeatedField& other) | 996 inline RepeatedField<Element>::RepeatedField(const RepeatedField& other) |
| 999 : current_size_(0), | 997 : current_size_(0), |
| 1000 total_size_(0), | 998 total_size_(0), |
| 1001 rep_(NULL) { | 999 rep_(NULL) { |
| 1002 CopyFrom(other); | 1000 if (other.current_size_ != 0) { |
| 1001 Reserve(other.current_size_); |
| 1002 CopyArray(rep_->elements, |
| 1003 other.rep_->elements, other.current_size_); |
| 1004 current_size_ = other.current_size_; |
| 1005 } |
| 1003 } | 1006 } |
| 1004 | 1007 |
| 1005 template <typename Element> | 1008 template <typename Element> |
| 1006 template <typename Iter> | 1009 template <typename Iter> |
| 1007 RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end) | 1010 RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end) |
| 1008 : current_size_(0), | 1011 : current_size_(0), |
| 1009 total_size_(0), | 1012 total_size_(0), |
| 1010 rep_(NULL) { | 1013 rep_(NULL) { |
| 1011 int reserve = internal::CalculateReserve(begin, end); | 1014 int reserve = internal::CalculateReserve(begin, end); |
| 1012 if (reserve != -1) { | 1015 if (reserve != -1) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 } | 1137 } |
| 1135 } | 1138 } |
| 1136 | 1139 |
| 1137 template <typename Element> | 1140 template <typename Element> |
| 1138 inline void RepeatedField<Element>::Clear() { | 1141 inline void RepeatedField<Element>::Clear() { |
| 1139 current_size_ = 0; | 1142 current_size_ = 0; |
| 1140 } | 1143 } |
| 1141 | 1144 |
| 1142 template <typename Element> | 1145 template <typename Element> |
| 1143 inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { | 1146 inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { |
| 1144 GOOGLE_CHECK_NE(&other, this); | 1147 GOOGLE_DCHECK_NE(&other, this); |
| 1145 if (other.current_size_ != 0) { | 1148 if (other.current_size_ != 0) { |
| 1146 Reserve(current_size_ + other.current_size_); | 1149 Reserve(current_size_ + other.current_size_); |
| 1147 CopyArray(rep_->elements + current_size_, | 1150 CopyArray(rep_->elements + current_size_, |
| 1148 other.rep_->elements, other.current_size_); | 1151 other.rep_->elements, other.current_size_); |
| 1149 current_size_ += other.current_size_; | 1152 current_size_ += other.current_size_; |
| 1150 } | 1153 } |
| 1151 } | 1154 } |
| 1152 | 1155 |
| 1153 template <typename Element> | 1156 template <typename Element> |
| 1154 inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) { | 1157 inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 void RepeatedField<Element>::Reserve(int new_size) { | 1263 void RepeatedField<Element>::Reserve(int new_size) { |
| 1261 if (total_size_ >= new_size) return; | 1264 if (total_size_ >= new_size) return; |
| 1262 Rep* old_rep = rep_; | 1265 Rep* old_rep = rep_; |
| 1263 Arena* arena = GetArenaNoVirtual(); | 1266 Arena* arena = GetArenaNoVirtual(); |
| 1264 new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSiz
e, | 1267 new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSiz
e, |
| 1265 std::max(total_size_ * 2, new_size)); | 1268 std::max(total_size_ * 2, new_size)); |
| 1266 GOOGLE_CHECK_LE(static_cast<size_t>(new_size), | 1269 GOOGLE_CHECK_LE(static_cast<size_t>(new_size), |
| 1267 (std::numeric_limits<size_t>::max() - kRepHeaderSize) / | 1270 (std::numeric_limits<size_t>::max() - kRepHeaderSize) / |
| 1268 sizeof(Element)) | 1271 sizeof(Element)) |
| 1269 << "Requested size is too large to fit into size_t."; | 1272 << "Requested size is too large to fit into size_t."; |
| 1273 size_t bytes = kRepHeaderSize + sizeof(Element) * new_size; |
| 1270 if (arena == NULL) { | 1274 if (arena == NULL) { |
| 1271 rep_ = reinterpret_cast<Rep*>( | 1275 rep_ = static_cast<Rep*>(::operator new(bytes)); |
| 1272 new char[kRepHeaderSize + sizeof(Element) * new_size]); | |
| 1273 } else { | 1276 } else { |
| 1274 rep_ = reinterpret_cast<Rep*>( | 1277 rep_ = reinterpret_cast<Rep*>( |
| 1275 ::google::protobuf::Arena::CreateArray<char>(arena, | 1278 ::google::protobuf::Arena::CreateArray<char>(arena, bytes)); |
| 1276 kRepHeaderSize + sizeof(Element) * new_size)); | |
| 1277 } | 1279 } |
| 1278 rep_->arena = arena; | 1280 rep_->arena = arena; |
| 1279 int old_total_size = total_size_; | 1281 int old_total_size = total_size_; |
| 1280 total_size_ = new_size; | 1282 total_size_ = new_size; |
| 1281 // Invoke placement-new on newly allocated elements. We shouldn't have to do | 1283 // Invoke placement-new on newly allocated elements. We shouldn't have to do |
| 1282 // this, since Element is supposed to be POD, but a previous version of this | 1284 // this, since Element is supposed to be POD, but a previous version of this |
| 1283 // code allocated storage with "new Element[size]" and some code uses | 1285 // code allocated storage with "new Element[size]" and some code uses |
| 1284 // RepeatedField with non-POD types, relying on constructor invocation. If | 1286 // RepeatedField with non-POD types, relying on constructor invocation. If |
| 1285 // Element has a trivial constructor (e.g., int32), gcc (tested with -O2) | 1287 // Element has a trivial constructor (e.g., int32), gcc (tested with -O2) |
| 1286 // completely removes this loop because the loop body is empty, so this has no | 1288 // completely removes this loop because the loop body is empty, so this has no |
| 1287 // effect unless its side-effects are required for correctness. | 1289 // effect unless its side-effects are required for correctness. |
| 1288 // Note that we do this before MoveArray() below because Element's copy | 1290 // Note that we do this before MoveArray() below because Element's copy |
| 1289 // assignment implementation will want an initialized instance first. | 1291 // assignment implementation will want an initialized instance first. |
| 1290 Element* e = &rep_->elements[0]; | 1292 Element* e = &rep_->elements[0]; |
| 1291 Element* limit = &rep_->elements[total_size_]; | 1293 Element* limit = &rep_->elements[total_size_]; |
| 1292 for (; e < limit; e++) { | 1294 for (; e < limit; e++) { |
| 1293 new (e) Element(); | 1295 new (e) Element; |
| 1294 } | 1296 } |
| 1295 if (current_size_ > 0) { | 1297 if (current_size_ > 0) { |
| 1296 MoveArray(rep_->elements, old_rep->elements, current_size_); | 1298 MoveArray(rep_->elements, old_rep->elements, current_size_); |
| 1297 } | 1299 } |
| 1298 | 1300 |
| 1299 // Likewise, we need to invoke destructors on the old array. | 1301 // Likewise, we need to invoke destructors on the old array. |
| 1300 InternalDeallocate(old_rep, old_total_size); | 1302 InternalDeallocate(old_rep, old_total_size); |
| 1301 | 1303 |
| 1302 } | 1304 } |
| 1303 | 1305 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 | 1354 |
| 1353 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* are
na) | 1355 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* are
na) |
| 1354 : arena_(arena), | 1356 : arena_(arena), |
| 1355 current_size_(0), | 1357 current_size_(0), |
| 1356 total_size_(0), | 1358 total_size_(0), |
| 1357 rep_(NULL) { | 1359 rep_(NULL) { |
| 1358 } | 1360 } |
| 1359 | 1361 |
| 1360 template <typename TypeHandler> | 1362 template <typename TypeHandler> |
| 1361 void RepeatedPtrFieldBase::Destroy() { | 1363 void RepeatedPtrFieldBase::Destroy() { |
| 1362 if (rep_ != NULL) { | 1364 if (rep_ != NULL && arena_ == NULL) { |
| 1363 for (int i = 0; i < rep_->allocated_size; i++) { | 1365 int n = rep_->allocated_size; |
| 1364 TypeHandler::Delete(cast<TypeHandler>(rep_->elements[i]), arena_); | 1366 void* const* elements = rep_->elements; |
| 1367 for (int i = 0; i < n; i++) { |
| 1368 TypeHandler::Delete(cast<TypeHandler>(elements[i]), NULL); |
| 1365 } | 1369 } |
| 1366 if (arena_ == NULL) { | 1370 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) |
| 1367 delete [] reinterpret_cast<char*>(rep_); | 1371 const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize; |
| 1368 } | 1372 ::operator delete(static_cast<void*>(rep_), size); |
| 1373 #else |
| 1374 ::operator delete(static_cast<void*>(rep_)); |
| 1375 #endif |
| 1369 } | 1376 } |
| 1370 rep_ = NULL; | 1377 rep_ = NULL; |
| 1371 } | 1378 } |
| 1372 | 1379 |
| 1373 template <typename TypeHandler> | 1380 template <typename TypeHandler> |
| 1374 inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { | 1381 inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { |
| 1375 if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) { | 1382 if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) { |
| 1376 InternalSwap(other); | 1383 InternalSwap(other); |
| 1377 } else { | 1384 } else { |
| 1378 SwapFallback<TypeHandler>(other); | 1385 SwapFallback<TypeHandler>(other); |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1778 : RepeatedPtrFieldBase() {} | 1785 : RepeatedPtrFieldBase() {} |
| 1779 | 1786 |
| 1780 template <typename Element> | 1787 template <typename Element> |
| 1781 inline RepeatedPtrField<Element>::RepeatedPtrField(::google::protobuf::Arena* ar
ena) : | 1788 inline RepeatedPtrField<Element>::RepeatedPtrField(::google::protobuf::Arena* ar
ena) : |
| 1782 RepeatedPtrFieldBase(arena) {} | 1789 RepeatedPtrFieldBase(arena) {} |
| 1783 | 1790 |
| 1784 template <typename Element> | 1791 template <typename Element> |
| 1785 inline RepeatedPtrField<Element>::RepeatedPtrField( | 1792 inline RepeatedPtrField<Element>::RepeatedPtrField( |
| 1786 const RepeatedPtrField& other) | 1793 const RepeatedPtrField& other) |
| 1787 : RepeatedPtrFieldBase() { | 1794 : RepeatedPtrFieldBase() { |
| 1788 CopyFrom(other); | 1795 MergeFrom(other); |
| 1789 } | 1796 } |
| 1790 | 1797 |
| 1791 template <typename Element> | 1798 template <typename Element> |
| 1792 template <typename Iter> | 1799 template <typename Iter> |
| 1793 inline RepeatedPtrField<Element>::RepeatedPtrField( | 1800 inline RepeatedPtrField<Element>::RepeatedPtrField( |
| 1794 Iter begin, const Iter& end) { | 1801 Iter begin, const Iter& end) { |
| 1795 int reserve = internal::CalculateReserve(begin, end); | 1802 int reserve = internal::CalculateReserve(begin, end); |
| 1796 if (reserve != -1) { | 1803 if (reserve != -1) { |
| 1797 Reserve(reserve); | 1804 Reserve(reserve); |
| 1798 } | 1805 } |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2358 return *this; | 2365 return *this; |
| 2359 } | 2366 } |
| 2360 RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) { | 2367 RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) { |
| 2361 return *this; | 2368 return *this; |
| 2362 } | 2369 } |
| 2363 | 2370 |
| 2364 private: | 2371 private: |
| 2365 RepeatedPtrField<T>* field_; | 2372 RepeatedPtrField<T>* field_; |
| 2366 }; | 2373 }; |
| 2367 | 2374 |
| 2368 // A back inserter for RepeatedPtrFields that inserts by transfering ownership | 2375 // A back inserter for RepeatedPtrFields that inserts by transferring ownership |
| 2369 // of a pointer. | 2376 // of a pointer. |
| 2370 template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator | 2377 template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator |
| 2371 : public std::iterator<std::output_iterator_tag, T> { | 2378 : public std::iterator<std::output_iterator_tag, T> { |
| 2372 public: | 2379 public: |
| 2373 explicit AllocatedRepeatedPtrFieldBackInsertIterator( | 2380 explicit AllocatedRepeatedPtrFieldBackInsertIterator( |
| 2374 RepeatedPtrField<T>* const mutable_field) | 2381 RepeatedPtrField<T>* const mutable_field) |
| 2375 : field_(mutable_field) { | 2382 : field_(mutable_field) { |
| 2376 } | 2383 } |
| 2377 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=( | 2384 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=( |
| 2378 T* const ptr_to_value) { | 2385 T* const ptr_to_value) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2455 AllocatedRepeatedPtrFieldBackInserter( | 2462 AllocatedRepeatedPtrFieldBackInserter( |
| 2456 RepeatedPtrField<T>* const mutable_field) { | 2463 RepeatedPtrField<T>* const mutable_field) { |
| 2457 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>( | 2464 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>( |
| 2458 mutable_field); | 2465 mutable_field); |
| 2459 } | 2466 } |
| 2460 | 2467 |
| 2461 // Similar to AllocatedRepeatedPtrFieldBackInserter, using | 2468 // Similar to AllocatedRepeatedPtrFieldBackInserter, using |
| 2462 // UnsafeArenaAddAllocated instead of AddAllocated. | 2469 // UnsafeArenaAddAllocated instead of AddAllocated. |
| 2463 // This is slightly faster if that matters. It is also useful in legacy code | 2470 // This is slightly faster if that matters. It is also useful in legacy code |
| 2464 // that uses temporary ownership to avoid copies. Example: | 2471 // that uses temporary ownership to avoid copies. Example: |
| 2465 // RepeatedPtrField<T> temp_field; | 2472 // RepeatedPtrField<T> temp_field; |
| 2466 // temp_field.AddAllocated(new T); | 2473 // temp_field.AddAllocated(new T); |
| 2467 // ... // Do something with temp_field | 2474 // ... // Do something with temp_field |
| 2468 // temp_field.ExtractSubrange(0, temp_field.size(), NULL); | 2475 // temp_field.ExtractSubrange(0, temp_field.size(), NULL); |
| 2469 // If you put temp_field on the arena this fails, because the ownership | 2476 // If you put temp_field on the arena this fails, because the ownership |
| 2470 // transfers to the arena at the "AddAllocated" call and is not released anymore | 2477 // transfers to the arena at the "AddAllocated" call and is not released anymore |
| 2471 // causing a double delete. Using UnsafeArenaAddAllocated prevents this. | 2478 // causing a double delete. Using UnsafeArenaAddAllocated prevents this. |
| 2472 template<typename T> | 2479 template<typename T> |
| 2473 internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T> | 2480 internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T> |
| 2474 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( | 2481 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( |
| 2475 ::google::protobuf::RepeatedPtrField<T>* const mutable_field) { | 2482 ::google::protobuf::RepeatedPtrField<T>* const mutable_field) { |
| 2476 return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>( | 2483 return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>( |
| 2477 mutable_field); | 2484 mutable_field); |
| 2478 } | 2485 } |
| 2479 | 2486 |
| 2480 } // namespace protobuf | 2487 } // namespace protobuf |
| 2481 | 2488 |
| 2482 } // namespace google | 2489 } // namespace google |
| 2483 #endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ | 2490 #endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ |
| OLD | NEW |