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 |