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