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
43namespace google {
44namespace protobuf {
45namespace 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;
71class 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
159template<typename T>
160class 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.
242template<typename T>
243struct 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    };
252DEFINE_PRIMITIVE(INT32, int32)
253DEFINE_PRIMITIVE(UINT32, uint32)
254DEFINE_PRIMITIVE(INT64, int64)
255DEFINE_PRIMITIVE(UINT64, uint64)
256DEFINE_PRIMITIVE(FLOAT, float)
257DEFINE_PRIMITIVE(DOUBLE, double)
258DEFINE_PRIMITIVE(BOOL, bool)
259#undef DEFINE_PRIMITIVE
260
261template<typename T>
262struct 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
276template<typename T>
277struct 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
292template<typename T>
293struct 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
307template<typename T>
308struct MessageDescriptorGetter {
309  static const Descriptor* get() {
310    return T::default_instance().GetDescriptor();
311  }
312};
313template<>
314struct MessageDescriptorGetter<Message> {
315  static const Descriptor* get() {
316    return NULL;
317  }
318};
319
320template<typename T>
321struct 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