Home | History | Annotate | Download | only in protobuf
      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>::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