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