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 |