• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // This header file is protobuf internal. Users should not include this
32 // file directly.
33 #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
34 #define GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
35 
36 #include <memory>
37 #ifndef _SHARED_PTR_H
38 #include <google/protobuf/stubs/shared_ptr.h>
39 #endif
40 
41 #include <google/protobuf/generated_enum_reflection.h>
42 
43 namespace google {
44 namespace protobuf {
45 namespace internal {
46 // Interfaces used to implement reflection RepeatedFieldRef API.
47 // Reflection::GetRepeatedAccessor() should return a pointer to an singleton
48 // object that implements the below interface.
49 //
50 // This interface passes/returns values using void pointers. The actual type
51 // of the value depends on the field's cpp_type. Following is a mapping from
52 // cpp_type to the type that should be used in this interface:
53 //
54 //   field->cpp_type()      T                Actual type of void*
55 //   CPPTYPE_INT32        int32                   int32
56 //   CPPTYPE_UINT32       uint32                  uint32
57 //   CPPTYPE_INT64        int64                   int64
58 //   CPPTYPE_UINT64       uint64                  uint64
59 //   CPPTYPE_DOUBLE       double                  double
60 //   CPPTYPE_FLOAT        float                   float
61 //   CPPTYPE_BOOL         bool                    bool
62 //   CPPTYPE_ENUM         generated enum type     int32
63 //   CPPTYPE_STRING       string                  string
64 //   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
65 //                        or google::protobuf::Message
66 //
67 // Note that for enums we use int32 in the interface.
68 //
69 // You can map from T to the actual type using RefTypeTraits:
70 //   typedef RefTypeTraits<T>::AccessorValueType ActualType;
71 class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
72  public:
73   // Typedefs for clarity.
74   typedef void Field;
75   typedef void Value;
76   typedef void Iterator;
77 
78   virtual ~RepeatedFieldAccessor();
79   virtual bool IsEmpty(const Field* data) const = 0;
80   virtual int Size(const Field* data) const = 0;
81   // Depends on the underlying representation of the repeated field, this
82   // method can return a pointer to the underlying object if such an object
83   // exists, or fill the data into scratch_space and return scratch_space.
84   // Callers of this method must ensure scratch_space is a valid pointer
85   // to a mutable object of the correct type.
86   virtual const Value* Get(
87       const Field* data, int index, Value* scratch_space) const = 0;
88 
89   virtual void Clear(Field* data) const = 0;
90   virtual void Set(Field* data, int index, const Value* value) const = 0;
91   virtual void Add(Field* data, const Value* value) const = 0;
92   virtual void RemoveLast(Field* data) const = 0;
93   virtual void SwapElements(Field* data, int index1, int index2) const = 0;
94   virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
95                     Field* other_data) const = 0;
96 
97   // Create an iterator that points at the begining of the repeated field.
98   virtual Iterator* BeginIterator(const Field* data) const = 0;
99   // Create an iterator that points at the end of the repeated field.
100   virtual Iterator* EndIterator(const Field* data) const = 0;
101   // Make a copy of an iterator and return the new copy.
102   virtual Iterator* CopyIterator(const Field* data,
103                                  const Iterator* iterator) const = 0;
104   // Move an iterator to point to the next element.
105   virtual Iterator* AdvanceIterator(const Field* data,
106                                     Iterator* iterator) const = 0;
107   // Compare whether two iterators point to the same element.
108   virtual bool EqualsIterator(const Field* data, const Iterator* a,
109                               const Iterator* b) const = 0;
110   // Delete an iterator created by BeginIterator(), EndIterator() and
111   // CopyIterator().
112   virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
113   // Like Get() but for iterators.
114   virtual const Value* GetIteratorValue(const Field* data,
115                                         const Iterator* iterator,
116                                         Value* scratch_space) const = 0;
117 
118   // Templated methods that make using this interface easier for non-message
119   // types.
120   template<typename T>
Get(const Field * data,int index)121   T Get(const Field* data, int index) const {
122     typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
123     ActualType scratch_space;
124     return static_cast<T>(
125         *reinterpret_cast<const ActualType*>(
126             Get(data, index, static_cast<Value*>(&scratch_space))));
127   }
128 
129   template<typename T, typename ValueType>
Set(Field * data,int index,const ValueType & value)130   void Set(Field* data, int index, const ValueType& value) const {
131     typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
132     // In this RepeatedFieldAccessor interface we pass/return data using
133     // raw pointers. Type of the data these raw pointers point to should
134     // be ActualType. Here we have a ValueType object and want a ActualType
135     // pointer. We can't cast a ValueType pointer to an ActualType pointer
136     // directly because their type might be different (for enums ValueType
137     // may be a generated enum type while ActualType is int32). To be safe
138     // we make a copy to get a temporary ActualType object and use it.
139     ActualType tmp = static_cast<ActualType>(value);
140     Set(data, index, static_cast<const Value*>(&tmp));
141   }
142 
143   template<typename T, typename ValueType>
Add(Field * data,const ValueType & value)144   void Add(Field* data, const ValueType& value) const {
145     typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
146     // In this RepeatedFieldAccessor interface we pass/return data using
147     // raw pointers. Type of the data these raw pointers point to should
148     // be ActualType. Here we have a ValueType object and want a ActualType
149     // pointer. We can't cast a ValueType pointer to an ActualType pointer
150     // directly because their type might be different (for enums ValueType
151     // may be a generated enum type while ActualType is int32). To be safe
152     // we make a copy to get a temporary ActualType object and use it.
153     ActualType tmp = static_cast<ActualType>(value);
154     Add(data, static_cast<const Value*>(&tmp));
155   }
156 };
157 
158 // Implement (Mutable)RepeatedFieldRef::iterator
159 template<typename T>
160 class RepeatedFieldRefIterator
161     : public std::iterator<std::forward_iterator_tag, T> {
162   typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
163   typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
164   typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
165 
166  public:
167   // Constructor for non-message fields.
RepeatedFieldRefIterator(const void * data,const RepeatedFieldAccessor * accessor,bool begin)168   RepeatedFieldRefIterator(const void* data,
169                            const RepeatedFieldAccessor* accessor,
170                            bool begin)
171       : data_(data), accessor_(accessor),
172         iterator_(begin ? accessor->BeginIterator(data) :
173                           accessor->EndIterator(data)),
174         scratch_space_(new AccessorValueType) {
175   }
176   // Constructor for message fields.
RepeatedFieldRefIterator(const void * data,const RepeatedFieldAccessor * accessor,bool begin,AccessorValueType * scratch_space)177   RepeatedFieldRefIterator(const void* data,
178                            const RepeatedFieldAccessor* accessor,
179                            bool begin,
180                            AccessorValueType* scratch_space)
181       : data_(data), accessor_(accessor),
182         iterator_(begin ? accessor->BeginIterator(data) :
183                           accessor->EndIterator(data)),
184         scratch_space_(scratch_space) {
185   }
~RepeatedFieldRefIterator()186   ~RepeatedFieldRefIterator() {
187     accessor_->DeleteIterator(data_, iterator_);
188   }
189   RepeatedFieldRefIterator operator++(int) {
190     RepeatedFieldRefIterator tmp(*this);
191     iterator_ = accessor_->AdvanceIterator(data_, iterator_);
192     return tmp;
193   }
194   RepeatedFieldRefIterator& operator++() {
195     iterator_ = accessor_->AdvanceIterator(data_, iterator_);
196     return *this;
197   }
198   IteratorValueType operator*() const {
199     return static_cast<IteratorValueType>(
200         *static_cast<const AccessorValueType*>(
201             accessor_->GetIteratorValue(
202                 data_, iterator_, scratch_space_.get())));
203   }
204   IteratorPointerType operator->() const {
205     return static_cast<IteratorPointerType>(
206         accessor_->GetIteratorValue(
207             data_, iterator_, scratch_space_.get()));
208   }
209   bool operator!=(const RepeatedFieldRefIterator& other) const {
210     assert(data_ == other.data_);
211     assert(accessor_ == other.accessor_);
212     return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
213   }
214   bool operator==(const RepeatedFieldRefIterator& other) const {
215     return !this->operator!=(other);
216   }
217 
RepeatedFieldRefIterator(const RepeatedFieldRefIterator & other)218   RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
219       : data_(other.data_), accessor_(other.accessor_),
220         iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
221   }
222   RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
223     if (this != &other) {
224       accessor_->DeleteIterator(data_, iterator_);
225       data_ = other.data_;
226       accessor_ = other.accessor_;
227       iterator_ = accessor_->CopyIterator(data_, other.iterator_);
228     }
229     return *this;
230   }
231 
232  protected:
233   const void* data_;
234   const RepeatedFieldAccessor* accessor_;
235   void* iterator_;
236   google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
237 };
238 
239 // TypeTraits that maps the type parameter T of RepeatedFieldRef or
240 // MutableRepeatedFieldRef to corresponding iterator type,
241 // RepeatedFieldAccessor type, etc.
242 template<typename T>
243 struct PrimitiveTraits {
244   static const bool is_primitive = false;
245 };
246 #define DEFINE_PRIMITIVE(TYPE, type) \
247     template<> struct PrimitiveTraits<type> { \
248       static const bool is_primitive = true; \
249       static const FieldDescriptor::CppType cpp_type = \
250           FieldDescriptor::CPPTYPE_ ## TYPE; \
251     };
252 DEFINE_PRIMITIVE(INT32, int32)
253 DEFINE_PRIMITIVE(UINT32, uint32)
254 DEFINE_PRIMITIVE(INT64, int64)
255 DEFINE_PRIMITIVE(UINT64, uint64)
256 DEFINE_PRIMITIVE(FLOAT, float)
257 DEFINE_PRIMITIVE(DOUBLE, double)
258 DEFINE_PRIMITIVE(BOOL, bool)
259 #undef DEFINE_PRIMITIVE
260 
261 template<typename T>
262 struct RefTypeTraits<
263     T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
264   typedef RepeatedFieldRefIterator<T> iterator;
265   typedef RepeatedFieldAccessor AccessorType;
266   typedef T AccessorValueType;
267   typedef T IteratorValueType;
268   typedef T* IteratorPointerType;
269   static const FieldDescriptor::CppType cpp_type =
270       PrimitiveTraits<T>::cpp_type;
271   static const Descriptor* GetMessageFieldDescriptor() {
272     return NULL;
273   }
274 };
275 
276 template<typename T>
277 struct RefTypeTraits<
278     T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
279   typedef RepeatedFieldRefIterator<T> iterator;
280   typedef RepeatedFieldAccessor AccessorType;
281   // We use int32 for repeated enums in RepeatedFieldAccessor.
282   typedef int32 AccessorValueType;
283   typedef T IteratorValueType;
284   typedef int32* IteratorPointerType;
285   static const FieldDescriptor::CppType cpp_type =
286       FieldDescriptor::CPPTYPE_ENUM;
287   static const Descriptor* GetMessageFieldDescriptor() {
288     return NULL;
289   }
290 };
291 
292 template<typename T>
293 struct RefTypeTraits<
294     T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
295   typedef RepeatedFieldRefIterator<T> iterator;
296   typedef RepeatedFieldAccessor AccessorType;
297   typedef string AccessorValueType;
298   typedef string IteratorValueType;
299   typedef string* IteratorPointerType;
300   static const FieldDescriptor::CppType cpp_type =
301       FieldDescriptor::CPPTYPE_STRING;
302   static const Descriptor* GetMessageFieldDescriptor() {
303     return NULL;
304   }
305 };
306 
307 template<typename T>
308 struct MessageDescriptorGetter {
309   static const Descriptor* get() {
310     return T::default_instance().GetDescriptor();
311   }
312 };
313 template<>
314 struct MessageDescriptorGetter<Message> {
315   static const Descriptor* get() {
316     return NULL;
317   }
318 };
319 
320 template<typename T>
321 struct RefTypeTraits<
322     T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
323   typedef RepeatedFieldRefIterator<T> iterator;
324   typedef RepeatedFieldAccessor AccessorType;
325   typedef Message AccessorValueType;
326   typedef const T& IteratorValueType;
327   typedef const T* IteratorPointerType;
328   static const FieldDescriptor::CppType cpp_type =
329       FieldDescriptor::CPPTYPE_MESSAGE;
330   static const Descriptor* GetMessageFieldDescriptor() {
331     return MessageDescriptorGetter<T>::get();
332   }
333 };
334 }  // namespace internal
335 }  // namespace protobuf
336 }  // namespace google
337 #endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
338