OLD | NEW |
| (Empty) |
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> | |
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> | |
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> | |
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. | |
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. | |
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 } | |
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 | |
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>::ty
pe> { | |
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__ | |
OLD | NEW |