blob: 8f8b1ab6a5a7a58c73fefe5c88fd302fba70c8cd [file] [log] [blame]
Feng Xiao6ef984a2014-11-10 17:34:54 -08001// 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 defines the RepeatedFieldRef class template used to access
32// repeated fields with protobuf reflection API.
33#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
34#define GOOGLE_PROTOBUF_REFLECTION_H__
35
Jisi Liu885b6122015-02-28 14:51:22 -080036#include <memory>
37#ifndef _SHARED_PTR_H
38#include <google/protobuf/stubs/shared_ptr.h>
39#endif
40
Feng Xiao6ef984a2014-11-10 17:34:54 -080041#include <google/protobuf/message.h>
42
43namespace google {
44namespace protobuf {
45namespace internal {
46template<typename T, typename Enable = void>
47struct RefTypeTraits;
48} // namespace internal
49
50template<typename T>
51RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
52 const Message& message, const FieldDescriptor* field) const {
53 return RepeatedFieldRef<T>(message, field);
54}
55
56template<typename T>
57MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
58 Message* message, const FieldDescriptor* field) const {
59 return MutableRepeatedFieldRef<T>(message, field);
60}
61
62// RepeatedFieldRef definition for non-message types.
63template<typename T>
64class RepeatedFieldRef<
65 T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
66 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
67 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
68
69 public:
70 bool empty() const {
71 return accessor_->IsEmpty(data_);
72 }
73 int size() const {
74 return accessor_->Size(data_);
75 }
76 T Get(int index) const {
77 return accessor_->template Get<T>(data_, index);
78 }
79
80 typedef IteratorType iterator;
81 typedef IteratorType const_iterator;
82 iterator begin() const {
83 return iterator(data_, accessor_, true);
84 }
85 iterator end() const {
86 return iterator(data_, accessor_, false);
87 }
88
89 private:
90 friend class Reflection;
91 RepeatedFieldRef(
92 const Message& message,
93 const FieldDescriptor* field) {
94 const Reflection* reflection = message.GetReflection();
95 data_ = reflection->RepeatedFieldData(
96 const_cast<Message*>(&message), field,
97 internal::RefTypeTraits<T>::cpp_type, NULL);
98 accessor_ = reflection->RepeatedFieldAccessor(field);
99 }
100
101 const void* data_;
102 const AccessorType* accessor_;
103};
104
105// MutableRepeatedFieldRef definition for non-message types.
106template<typename T>
107class MutableRepeatedFieldRef<
108 T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
109 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
110
111 public:
112 bool empty() const {
113 return accessor_->IsEmpty(data_);
114 }
115 int size() const {
116 return accessor_->Size(data_);
117 }
118 T Get(int index) const {
119 return accessor_->template Get<T>(data_, index);
120 }
121
122 void Set(int index, const T& value) const {
123 accessor_->template Set<T>(data_, index, value);
124 }
125 void Add(const T& value) const {
126 accessor_->template Add<T>(data_, value);
127 }
128 void RemoveLast() const {
129 accessor_->RemoveLast(data_);
130 }
131 void SwapElements(int index1, int index2) const {
132 accessor_->SwapElements(data_, index1, index2);
133 }
134 void Clear() const {
135 accessor_->Clear(data_);
136 }
137
138 void Swap(const MutableRepeatedFieldRef& other) const {
139 accessor_->Swap(data_, other.accessor_, other.data_);
140 }
141
142 template<typename Container>
143 void MergeFrom(const Container& container) const {
144 typedef typename Container::const_iterator Iterator;
145 for (Iterator it = container.begin(); it != container.end(); ++it) {
146 Add(*it);
147 }
148 }
149 template<typename Container>
150 void CopyFrom(const Container& container) const {
151 Clear();
152 MergeFrom(container);
153 }
154
155 private:
156 friend class Reflection;
157 MutableRepeatedFieldRef(
158 Message* message,
159 const FieldDescriptor* field) {
160 const Reflection* reflection = message->GetReflection();
161 data_ = reflection->RepeatedFieldData(
162 message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
163 accessor_ = reflection->RepeatedFieldAccessor(field);
164 }
165
166 void* data_;
167 const AccessorType* accessor_;
168};
169
170// RepeatedFieldRef definition for message types.
171template<typename T>
172class RepeatedFieldRef<
173 T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
174 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
175 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
176
177 public:
178 bool empty() const {
179 return accessor_->IsEmpty(data_);
180 }
181 int size() const {
182 return accessor_->Size(data_);
183 }
184 // This method returns a reference to the underlying message object if it
185 // exists. If a message object doesn't exist (e.g., data stored in serialized
186 // form), scratch_space will be filled with the data and a reference to it
187 // will be returned.
188 //
189 // Example:
190 // RepeatedFieldRef<Message> h = ...
191 // unique_ptr<Message> scratch_space(h.NewMessage());
192 // const Message& item = h.Get(index, scratch_space.get());
193 const T& Get(int index, T* scratch_space) const {
194 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
195 }
196 // Create a new message of the same type as the messages stored in this
197 // repeated field. Caller takes ownership of the returned object.
198 T* NewMessage() const {
199 return static_cast<T*>(default_instance_->New());
200 }
201
202 typedef IteratorType iterator;
203 typedef IteratorType const_iterator;
204 iterator begin() const {
205 return iterator(data_, accessor_, true, NewMessage());
206 }
207 iterator end() const {
208 return iterator(data_, accessor_, false, NewMessage());
209 }
210
211 private:
212 friend class Reflection;
213 RepeatedFieldRef(
214 const Message& message,
215 const FieldDescriptor* field) {
216 const Reflection* reflection = message.GetReflection();
217 data_ = reflection->RepeatedFieldData(
218 const_cast<Message*>(&message), field,
219 internal::RefTypeTraits<T>::cpp_type,
220 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
221 accessor_ = reflection->RepeatedFieldAccessor(field);
222 default_instance_ =
223 reflection->GetMessageFactory()->GetPrototype(field->message_type());
224 }
225
226 const void* data_;
227 const AccessorType* accessor_;
228 const Message* default_instance_;
229};
230
Jisi Liu885b6122015-02-28 14:51:22 -0800231// MutableRepeatedFieldRef definition for message types.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800232template<typename T>
233class MutableRepeatedFieldRef<
234 T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
235 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
236
237 public:
238 bool empty() const {
239 return accessor_->IsEmpty(data_);
240 }
241 int size() const {
242 return accessor_->Size(data_);
243 }
244 // See comments for RepeatedFieldRef<Message>::Get()
245 const T& Get(int index, T* scratch_space) const {
246 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
247 }
248 // Create a new message of the same type as the messages stored in this
249 // repeated field. Caller takes ownership of the returned object.
250 T* NewMessage() const {
251 return static_cast<T*>(default_instance_->New());
252 }
253
254 void Set(int index, const T& value) const {
255 accessor_->Set(data_, index, &value);
256 }
257 void Add(const T& value) const {
258 accessor_->Add(data_, &value);
259 }
260 void RemoveLast() const {
261 accessor_->RemoveLast(data_);
262 }
263 void SwapElements(int index1, int index2) const {
264 accessor_->SwapElements(data_, index1, index2);
265 }
266 void Clear() const {
267 accessor_->Clear(data_);
268 }
269
270 void Swap(const MutableRepeatedFieldRef& other) const {
271 accessor_->Swap(data_, other.accessor_, other.data_);
272 }
273
274 template<typename Container>
275 void MergeFrom(const Container& container) const {
276 typedef typename Container::const_iterator Iterator;
277 for (Iterator it = container.begin(); it != container.end(); ++it) {
278 Add(*it);
279 }
280 }
281 template<typename Container>
282 void CopyFrom(const Container& container) const {
283 Clear();
284 MergeFrom(container);
285 }
286
287 private:
288 friend class Reflection;
289 MutableRepeatedFieldRef(
290 Message* message,
291 const FieldDescriptor* field) {
292 const Reflection* reflection = message->GetReflection();
293 data_ = reflection->RepeatedFieldData(
294 message, field, internal::RefTypeTraits<T>::cpp_type,
295 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
296 accessor_ = reflection->RepeatedFieldAccessor(field);
297 default_instance_ =
298 reflection->GetMessageFactory()->GetPrototype(field->message_type());
299 }
300
301 void* data_;
302 const AccessorType* accessor_;
303 const Message* default_instance_;
304};
Jisi Liu885b6122015-02-28 14:51:22 -0800305
306namespace internal {
307// Interfaces used to implement reflection RepeatedFieldRef API.
308// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
309// object that implements the below interface.
310//
311// This interface passes/returns values using void pointers. The actual type
312// of the value depends on the field's cpp_type. Following is a mapping from
313// cpp_type to the type that should be used in this interface:
314//
315// field->cpp_type() T Actual type of void*
316// CPPTYPE_INT32 int32 int32
317// CPPTYPE_UINT32 uint32 uint32
318// CPPTYPE_INT64 int64 int64
319// CPPTYPE_UINT64 uint64 uint64
320// CPPTYPE_DOUBLE double double
321// CPPTYPE_FLOAT float float
322// CPPTYPE_BOOL bool bool
323// CPPTYPE_ENUM generated enum type int32
324// CPPTYPE_STRING string string
325// CPPTYPE_MESSAGE generated message type google::protobuf::Message
326// or google::protobuf::Message
327//
328// Note that for enums we use int32 in the interface.
329//
330// You can map from T to the actual type using RefTypeTraits:
331// typedef RefTypeTraits<T>::AccessorValueType ActualType;
332class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
333 public:
334 // Typedefs for clarity.
335 typedef void Field;
336 typedef void Value;
337 typedef void Iterator;
338
339 virtual ~RepeatedFieldAccessor();
340 virtual bool IsEmpty(const Field* data) const = 0;
341 virtual int Size(const Field* data) const = 0;
342 // Depends on the underlying representation of the repeated field, this
343 // method can return a pointer to the underlying object if such an object
344 // exists, or fill the data into scratch_space and return scratch_space.
345 // Callers of this method must ensure scratch_space is a valid pointer
346 // to a mutable object of the correct type.
347 virtual const Value* Get(
348 const Field* data, int index, Value* scratch_space) const = 0;
349
350 virtual void Clear(Field* data) const = 0;
351 virtual void Set(Field* data, int index, const Value* value) const = 0;
352 virtual void Add(Field* data, const Value* value) const = 0;
353 virtual void RemoveLast(Field* data) const = 0;
354 virtual void SwapElements(Field* data, int index1, int index2) const = 0;
355 virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
356 Field* other_data) const = 0;
357
358 // Create an iterator that points at the begining of the repeated field.
359 virtual Iterator* BeginIterator(const Field* data) const = 0;
360 // Create an iterator that points at the end of the repeated field.
361 virtual Iterator* EndIterator(const Field* data) const = 0;
362 // Make a copy of an iterator and return the new copy.
363 virtual Iterator* CopyIterator(const Field* data,
364 const Iterator* iterator) const = 0;
365 // Move an iterator to point to the next element.
366 virtual Iterator* AdvanceIterator(const Field* data,
367 Iterator* iterator) const = 0;
368 // Compare whether two iterators point to the same element.
369 virtual bool EqualsIterator(const Field* data, const Iterator* a,
370 const Iterator* b) const = 0;
371 // Delete an iterator created by BeginIterator(), EndIterator() and
372 // CopyIterator().
373 virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
374 // Like Get() but for iterators.
375 virtual const Value* GetIteratorValue(const Field* data,
376 const Iterator* iterator,
377 Value* scratch_space) const = 0;
378
379 // Templated methods that make using this interface easier for non-message
380 // types.
381 template<typename T>
382 T Get(const Field* data, int index) const {
383 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
384 ActualType scratch_space;
385 return static_cast<T>(
386 *reinterpret_cast<const ActualType*>(
387 Get(data, index, static_cast<Value*>(&scratch_space))));
388 }
389
390 template<typename T, typename ValueType>
391 void Set(Field* data, int index, const ValueType& value) const {
392 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
393 // In this RepeatedFieldAccessor interface we pass/return data using
394 // raw pointers. Type of the data these raw pointers point to should
395 // be ActualType. Here we have a ValueType object and want a ActualType
396 // pointer. We can't cast a ValueType pointer to an ActualType pointer
397 // directly because their type might be different (for enums ValueType
398 // may be a generated enum type while ActualType is int32). To be safe
399 // we make a copy to get a temporary ActualType object and use it.
400 ActualType tmp = static_cast<ActualType>(value);
401 Set(data, index, static_cast<const Value*>(&tmp));
402 }
403
404 template<typename T, typename ValueType>
405 void Add(Field* data, const ValueType& value) const {
406 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
407 // In this RepeatedFieldAccessor interface we pass/return data using
408 // raw pointers. Type of the data these raw pointers point to should
409 // be ActualType. Here we have a ValueType object and want a ActualType
410 // pointer. We can't cast a ValueType pointer to an ActualType pointer
411 // directly because their type might be different (for enums ValueType
412 // may be a generated enum type while ActualType is int32). To be safe
413 // we make a copy to get a temporary ActualType object and use it.
414 ActualType tmp = static_cast<ActualType>(value);
415 Add(data, static_cast<const Value*>(&tmp));
416 }
417};
418
419// Implement (Mutable)RepeatedFieldRef::iterator
420template<typename T>
421class RepeatedFieldRefIterator
422 : public std::iterator<std::forward_iterator_tag, T> {
423 typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
424 typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
425 typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
426
427 public:
428 // Constructor for non-message fields.
429 RepeatedFieldRefIterator(const void* data,
430 const RepeatedFieldAccessor* accessor,
431 bool begin)
432 : data_(data), accessor_(accessor),
433 iterator_(begin ? accessor->BeginIterator(data) :
434 accessor->EndIterator(data)),
435 scratch_space_(new AccessorValueType) {
436 }
437 // Constructor for message fields.
438 RepeatedFieldRefIterator(const void* data,
439 const RepeatedFieldAccessor* accessor,
440 bool begin,
441 AccessorValueType* scratch_space)
442 : data_(data), accessor_(accessor),
443 iterator_(begin ? accessor->BeginIterator(data) :
444 accessor->EndIterator(data)),
445 scratch_space_(scratch_space) {
446 }
447 ~RepeatedFieldRefIterator() {
448 accessor_->DeleteIterator(data_, iterator_);
449 }
450 RepeatedFieldRefIterator operator++(int) {
451 RepeatedFieldRefIterator tmp(*this);
452 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
453 return tmp;
454 }
455 RepeatedFieldRefIterator& operator++() {
456 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
457 return *this;
458 }
459 IteratorValueType operator*() const {
460 return static_cast<IteratorValueType>(
461 *static_cast<const AccessorValueType*>(
462 accessor_->GetIteratorValue(
463 data_, iterator_, scratch_space_.get())));
464 }
465 IteratorPointerType operator->() const {
466 return static_cast<IteratorPointerType>(
467 accessor_->GetIteratorValue(
468 data_, iterator_, scratch_space_.get()));
469 }
470 bool operator!=(const RepeatedFieldRefIterator& other) const {
471 assert(data_ == other.data_);
472 assert(accessor_ == other.accessor_);
473 return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
474 }
475 bool operator==(const RepeatedFieldRefIterator& other) const {
476 return !this->operator!=(other);
477 }
478
479 RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
480 : data_(other.data_), accessor_(other.accessor_),
481 iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
482 }
483 RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
484 if (this != &other) {
485 accessor_->DeleteIterator(data_, iterator_);
486 data_ = other.data_;
487 accessor_ = other.accessor_;
488 iterator_ = accessor_->CopyIterator(data_, other.iterator_);
489 }
490 return *this;
491 }
492
493 protected:
494 const void* data_;
495 const RepeatedFieldAccessor* accessor_;
496 void* iterator_;
497 google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
498};
499
500// TypeTraits that maps the type parameter T of RepeatedFieldRef or
501// MutableRepeatedFieldRef to corresponding iterator type,
502// RepeatedFieldAccessor type, etc.
503template<typename T>
504struct PrimitiveTraits {
505 static const bool is_primitive = false;
506};
507#define DEFINE_PRIMITIVE(TYPE, type) \
508 template<> struct PrimitiveTraits<type> { \
509 static const bool is_primitive = true; \
510 static const FieldDescriptor::CppType cpp_type = \
511 FieldDescriptor::CPPTYPE_ ## TYPE; \
512 };
513DEFINE_PRIMITIVE(INT32, int32)
514DEFINE_PRIMITIVE(UINT32, uint32)
515DEFINE_PRIMITIVE(INT64, int64)
516DEFINE_PRIMITIVE(UINT64, uint64)
517DEFINE_PRIMITIVE(FLOAT, float)
518DEFINE_PRIMITIVE(DOUBLE, double)
519DEFINE_PRIMITIVE(BOOL, bool)
520#undef DEFINE_PRIMITIVE
521
522template<typename T>
523struct RefTypeTraits<
524 T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
525 typedef RepeatedFieldRefIterator<T> iterator;
526 typedef RepeatedFieldAccessor AccessorType;
527 typedef T AccessorValueType;
528 typedef T IteratorValueType;
529 typedef T* IteratorPointerType;
530 static const FieldDescriptor::CppType cpp_type =
531 PrimitiveTraits<T>::cpp_type;
532 static const Descriptor* GetMessageFieldDescriptor() {
533 return NULL;
534 }
535};
536
537template<typename T>
538struct RefTypeTraits<
539 T, typename internal::enable_if<internal::is_enum<T>::value>::type> {
540 typedef RepeatedFieldRefIterator<T> iterator;
541 typedef RepeatedFieldAccessor AccessorType;
542 // We use int32 for repeated enums in RepeatedFieldAccessor.
543 typedef int32 AccessorValueType;
544 typedef T IteratorValueType;
545 typedef int32* IteratorPointerType;
546 static const FieldDescriptor::CppType cpp_type =
547 FieldDescriptor::CPPTYPE_ENUM;
548 static const Descriptor* GetMessageFieldDescriptor() {
549 return NULL;
550 }
551};
552
553template<typename T>
554struct RefTypeTraits<
555 T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
556 typedef RepeatedFieldRefIterator<T> iterator;
557 typedef RepeatedFieldAccessor AccessorType;
558 typedef string AccessorValueType;
559 typedef string IteratorValueType;
560 typedef string* IteratorPointerType;
561 static const FieldDescriptor::CppType cpp_type =
562 FieldDescriptor::CPPTYPE_STRING;
563 static const Descriptor* GetMessageFieldDescriptor() {
564 return NULL;
565 }
566};
567
568template<typename T>
569struct MessageDescriptorGetter {
570 static const Descriptor* get() {
571 return T::default_instance().GetDescriptor();
572 }
573};
574template<>
575struct MessageDescriptorGetter<Message> {
576 static const Descriptor* get() {
577 return NULL;
578 }
579};
580
581template<typename T>
582struct RefTypeTraits<
583 T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
584 typedef RepeatedFieldRefIterator<T> iterator;
585 typedef RepeatedFieldAccessor AccessorType;
586 typedef Message AccessorValueType;
587 typedef const T& IteratorValueType;
588 typedef const T* IteratorPointerType;
589 static const FieldDescriptor::CppType cpp_type =
590 FieldDescriptor::CPPTYPE_MESSAGE;
591 static const Descriptor* GetMessageFieldDescriptor() {
592 return MessageDescriptorGetter<T>::get();
593 }
594};
595} // namespace internal
Feng Xiao6ef984a2014-11-10 17:34:54 -0800596} // namespace protobuf
597} // namespace google
598
Feng Xiao6ef984a2014-11-10 17:34:54 -0800599#endif // GOOGLE_PROTOBUF_REFLECTION_H__