569 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			569 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Protocol Buffers - Google's data interchange format
 | 
						|
// Copyright 2008 Google Inc.  All rights reserved.
 | 
						|
// https://developers.google.com/protocol-buffers/
 | 
						|
//
 | 
						|
// Redistribution and use in source and binary forms, with or without
 | 
						|
// modification, are permitted provided that the following conditions are
 | 
						|
// met:
 | 
						|
//
 | 
						|
//     * Redistributions of source code must retain the above copyright
 | 
						|
// notice, this list of conditions and the following disclaimer.
 | 
						|
//     * Redistributions in binary form must reproduce the above
 | 
						|
// copyright notice, this list of conditions and the following disclaimer
 | 
						|
// in the documentation and/or other materials provided with the
 | 
						|
// distribution.
 | 
						|
//     * Neither the name of Google Inc. nor the names of its
 | 
						|
// contributors may be used to endorse or promote products derived from
 | 
						|
// this software without specific prior written permission.
 | 
						|
//
 | 
						|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
						|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
						|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
						|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
						|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
						|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
						|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
						|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
 | 
						|
// This header defines the RepeatedFieldRef class template used to access
 | 
						|
// repeated fields with protobuf reflection API.
 | 
						|
#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
 | 
						|
#define GOOGLE_PROTOBUF_REFLECTION_H__
 | 
						|
 | 
						|
#include <memory>
 | 
						|
 | 
						|
#include <google/protobuf/message.h>
 | 
						|
#include <google/protobuf/generated_enum_util.h>
 | 
						|
 | 
						|
#ifdef SWIG
 | 
						|
#error "You cannot SWIG proto headers"
 | 
						|
#endif
 | 
						|
 | 
						|
#include <google/protobuf/port_def.inc>
 | 
						|
 | 
						|
namespace google {
 | 
						|
namespace protobuf {
 | 
						|
namespace internal {
 | 
						|
template <typename T, typename Enable = void>
 | 
						|
struct RefTypeTraits;
 | 
						|
}  // namespace internal
 | 
						|
 | 
						|
template <typename T>
 | 
						|
RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
 | 
						|
    const Message& message, const FieldDescriptor* field) const {
 | 
						|
  return RepeatedFieldRef<T>(message, field);
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
 | 
						|
    Message* message, const FieldDescriptor* field) const {
 | 
						|
  return MutableRepeatedFieldRef<T>(message, field);
 | 
						|
}
 | 
						|
 | 
						|
// RepeatedFieldRef definition for non-message types.
 | 
						|
template <typename T>
 | 
						|
class RepeatedFieldRef<
 | 
						|
    T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
 | 
						|
  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
 | 
						|
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
 | 
						|
 | 
						|
 public:
 | 
						|
  bool empty() const { return accessor_->IsEmpty(data_); }
 | 
						|
  int size() const { return accessor_->Size(data_); }
 | 
						|
  T Get(int index) const { return accessor_->template Get<T>(data_, index); }
 | 
						|
 | 
						|
  typedef IteratorType iterator;
 | 
						|
  typedef IteratorType const_iterator;
 | 
						|
  typedef T value_type;
 | 
						|
  typedef T& reference;
 | 
						|
  typedef const T& const_reference;
 | 
						|
  typedef int size_type;
 | 
						|
  typedef ptrdiff_t difference_type;
 | 
						|
 | 
						|
  iterator begin() const { return iterator(data_, accessor_, true); }
 | 
						|
  iterator end() const { return iterator(data_, accessor_, false); }
 | 
						|
 | 
						|
 private:
 | 
						|
  friend class Reflection;
 | 
						|
  RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
 | 
						|
    const Reflection* reflection = message.GetReflection();
 | 
						|
    data_ = reflection->RepeatedFieldData(const_cast<Message*>(&message), field,
 | 
						|
                                          internal::RefTypeTraits<T>::cpp_type,
 | 
						|
                                          NULL);
 | 
						|
    accessor_ = reflection->RepeatedFieldAccessor(field);
 | 
						|
  }
 | 
						|
 | 
						|
  const void* data_;
 | 
						|
  const AccessorType* accessor_;
 | 
						|
};
 | 
						|
 | 
						|
// MutableRepeatedFieldRef definition for non-message types.
 | 
						|
template <typename T>
 | 
						|
class MutableRepeatedFieldRef<
 | 
						|
    T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
 | 
						|
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
 | 
						|
 | 
						|
 public:
 | 
						|
  bool empty() const { return accessor_->IsEmpty(data_); }
 | 
						|
  int size() const { return accessor_->Size(data_); }
 | 
						|
  T Get(int index) const { return accessor_->template Get<T>(data_, index); }
 | 
						|
 | 
						|
  void Set(int index, const T& value) const {
 | 
						|
    accessor_->template Set<T>(data_, index, value);
 | 
						|
  }
 | 
						|
  void Add(const T& value) const { accessor_->template Add<T>(data_, value); }
 | 
						|
  void RemoveLast() const { accessor_->RemoveLast(data_); }
 | 
						|
  void SwapElements(int index1, int index2) const {
 | 
						|
    accessor_->SwapElements(data_, index1, index2);
 | 
						|
  }
 | 
						|
  void Clear() const { accessor_->Clear(data_); }
 | 
						|
 | 
						|
  void Swap(const MutableRepeatedFieldRef& other) const {
 | 
						|
    accessor_->Swap(data_, other.accessor_, other.data_);
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename Container>
 | 
						|
  void MergeFrom(const Container& container) const {
 | 
						|
    typedef typename Container::const_iterator Iterator;
 | 
						|
    for (Iterator it = container.begin(); it != container.end(); ++it) {
 | 
						|
      Add(*it);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  template <typename Container>
 | 
						|
  void CopyFrom(const Container& container) const {
 | 
						|
    Clear();
 | 
						|
    MergeFrom(container);
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  friend class Reflection;
 | 
						|
  MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
 | 
						|
    const Reflection* reflection = message->GetReflection();
 | 
						|
    data_ = reflection->RepeatedFieldData(
 | 
						|
        message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
 | 
						|
    accessor_ = reflection->RepeatedFieldAccessor(field);
 | 
						|
  }
 | 
						|
 | 
						|
  void* data_;
 | 
						|
  const AccessorType* accessor_;
 | 
						|
};
 | 
						|
 | 
						|
// RepeatedFieldRef definition for message types.
 | 
						|
template <typename T>
 | 
						|
class RepeatedFieldRef<
 | 
						|
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
 | 
						|
  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
 | 
						|
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
 | 
						|
 | 
						|
 public:
 | 
						|
  bool empty() const { return accessor_->IsEmpty(data_); }
 | 
						|
  int size() const { return accessor_->Size(data_); }
 | 
						|
  // This method returns a reference to the underlying message object if it
 | 
						|
  // exists. If a message object doesn't exist (e.g., data stored in serialized
 | 
						|
  // form), scratch_space will be filled with the data and a reference to it
 | 
						|
  // will be returned.
 | 
						|
  //
 | 
						|
  // Example:
 | 
						|
  //   RepeatedFieldRef<Message> h = ...
 | 
						|
  //   unique_ptr<Message> scratch_space(h.NewMessage());
 | 
						|
  //   const Message& item = h.Get(index, scratch_space.get());
 | 
						|
  const T& Get(int index, T* scratch_space) const {
 | 
						|
    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
 | 
						|
  }
 | 
						|
  // Create a new message of the same type as the messages stored in this
 | 
						|
  // repeated field. Caller takes ownership of the returned object.
 | 
						|
  T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
 | 
						|
 | 
						|
  typedef IteratorType iterator;
 | 
						|
  typedef IteratorType const_iterator;
 | 
						|
  typedef T value_type;
 | 
						|
  typedef T& reference;
 | 
						|
  typedef const T& const_reference;
 | 
						|
  typedef int size_type;
 | 
						|
  typedef ptrdiff_t difference_type;
 | 
						|
 | 
						|
  iterator begin() const {
 | 
						|
    return iterator(data_, accessor_, true, NewMessage());
 | 
						|
  }
 | 
						|
  iterator end() const {
 | 
						|
    // The end iterator must not be dereferenced, no need for scratch space.
 | 
						|
    return iterator(data_, accessor_, false, nullptr);
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  friend class Reflection;
 | 
						|
  RepeatedFieldRef(const Message& message, const FieldDescriptor* field) {
 | 
						|
    const Reflection* reflection = message.GetReflection();
 | 
						|
    data_ = reflection->RepeatedFieldData(
 | 
						|
        const_cast<Message*>(&message), field,
 | 
						|
        internal::RefTypeTraits<T>::cpp_type,
 | 
						|
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
 | 
						|
    accessor_ = reflection->RepeatedFieldAccessor(field);
 | 
						|
    default_instance_ =
 | 
						|
        reflection->GetMessageFactory()->GetPrototype(field->message_type());
 | 
						|
  }
 | 
						|
 | 
						|
  const void* data_;
 | 
						|
  const AccessorType* accessor_;
 | 
						|
  const Message* default_instance_;
 | 
						|
};
 | 
						|
 | 
						|
// MutableRepeatedFieldRef definition for message types.
 | 
						|
template <typename T>
 | 
						|
class MutableRepeatedFieldRef<
 | 
						|
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
 | 
						|
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
 | 
						|
 | 
						|
 public:
 | 
						|
  bool empty() const { return accessor_->IsEmpty(data_); }
 | 
						|
  int size() const { return accessor_->Size(data_); }
 | 
						|
  // See comments for RepeatedFieldRef<Message>::Get()
 | 
						|
  const T& Get(int index, T* scratch_space) const {
 | 
						|
    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
 | 
						|
  }
 | 
						|
  // Create a new message of the same type as the messages stored in this
 | 
						|
  // repeated field. Caller takes ownership of the returned object.
 | 
						|
  T* NewMessage() const { return static_cast<T*>(default_instance_->New()); }
 | 
						|
 | 
						|
  void Set(int index, const T& value) const {
 | 
						|
    accessor_->Set(data_, index, &value);
 | 
						|
  }
 | 
						|
  void Add(const T& value) const { accessor_->Add(data_, &value); }
 | 
						|
  void RemoveLast() const { accessor_->RemoveLast(data_); }
 | 
						|
  void SwapElements(int index1, int index2) const {
 | 
						|
    accessor_->SwapElements(data_, index1, index2);
 | 
						|
  }
 | 
						|
  void Clear() const { accessor_->Clear(data_); }
 | 
						|
 | 
						|
  void Swap(const MutableRepeatedFieldRef& other) const {
 | 
						|
    accessor_->Swap(data_, other.accessor_, other.data_);
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename Container>
 | 
						|
  void MergeFrom(const Container& container) const {
 | 
						|
    typedef typename Container::const_iterator Iterator;
 | 
						|
    for (Iterator it = container.begin(); it != container.end(); ++it) {
 | 
						|
      Add(*it);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  template <typename Container>
 | 
						|
  void CopyFrom(const Container& container) const {
 | 
						|
    Clear();
 | 
						|
    MergeFrom(container);
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  friend class Reflection;
 | 
						|
  MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) {
 | 
						|
    const Reflection* reflection = message->GetReflection();
 | 
						|
    data_ = reflection->RepeatedFieldData(
 | 
						|
        message, field, internal::RefTypeTraits<T>::cpp_type,
 | 
						|
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
 | 
						|
    accessor_ = reflection->RepeatedFieldAccessor(field);
 | 
						|
    default_instance_ =
 | 
						|
        reflection->GetMessageFactory()->GetPrototype(field->message_type());
 | 
						|
  }
 | 
						|
 | 
						|
  void* data_;
 | 
						|
  const AccessorType* accessor_;
 | 
						|
  const Message* default_instance_;
 | 
						|
};
 | 
						|
 | 
						|
namespace internal {
 | 
						|
// Interfaces used to implement reflection RepeatedFieldRef API.
 | 
						|
// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
 | 
						|
// object that implements the below interface.
 | 
						|
//
 | 
						|
// This interface passes/returns values using void pointers. The actual type
 | 
						|
// of the value depends on the field's cpp_type. Following is a mapping from
 | 
						|
// cpp_type to the type that should be used in this interface:
 | 
						|
//
 | 
						|
//   field->cpp_type()      T                Actual type of void*
 | 
						|
//   CPPTYPE_INT32        int32_t                 int32_t
 | 
						|
//   CPPTYPE_UINT32       uint32_t                uint32_t
 | 
						|
//   CPPTYPE_INT64        int64_t                 int64_t
 | 
						|
//   CPPTYPE_UINT64       uint64_t                uint64_t
 | 
						|
//   CPPTYPE_DOUBLE       double                  double
 | 
						|
//   CPPTYPE_FLOAT        float                   float
 | 
						|
//   CPPTYPE_BOOL         bool                    bool
 | 
						|
//   CPPTYPE_ENUM         generated enum type     int32_t
 | 
						|
//   CPPTYPE_STRING       string                  std::string
 | 
						|
//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
 | 
						|
//                        or google::protobuf::Message
 | 
						|
//
 | 
						|
// Note that for enums we use int32_t in the interface.
 | 
						|
//
 | 
						|
// You can map from T to the actual type using RefTypeTraits:
 | 
						|
//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
 | 
						|
class PROTOBUF_EXPORT RepeatedFieldAccessor {
 | 
						|
 public:
 | 
						|
  // Typedefs for clarity.
 | 
						|
  typedef void Field;
 | 
						|
  typedef void Value;
 | 
						|
  typedef void Iterator;
 | 
						|
 | 
						|
  virtual bool IsEmpty(const Field* data) const = 0;
 | 
						|
  virtual int Size(const Field* data) const = 0;
 | 
						|
  // Depends on the underlying representation of the repeated field, this
 | 
						|
  // method can return a pointer to the underlying object if such an object
 | 
						|
  // exists, or fill the data into scratch_space and return scratch_space.
 | 
						|
  // Callers of this method must ensure scratch_space is a valid pointer
 | 
						|
  // to a mutable object of the correct type.
 | 
						|
  virtual const Value* Get(const Field* data, int index,
 | 
						|
                           Value* scratch_space) const = 0;
 | 
						|
 | 
						|
  virtual void Clear(Field* data) const = 0;
 | 
						|
  virtual void Set(Field* data, int index, const Value* value) const = 0;
 | 
						|
  virtual void Add(Field* data, const Value* value) const = 0;
 | 
						|
  virtual void RemoveLast(Field* data) const = 0;
 | 
						|
  virtual void SwapElements(Field* data, int index1, int index2) const = 0;
 | 
						|
  virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
 | 
						|
                    Field* other_data) const = 0;
 | 
						|
 | 
						|
  // Create an iterator that points at the beginning of the repeated field.
 | 
						|
  virtual Iterator* BeginIterator(const Field* data) const = 0;
 | 
						|
  // Create an iterator that points at the end of the repeated field.
 | 
						|
  virtual Iterator* EndIterator(const Field* data) const = 0;
 | 
						|
  // Make a copy of an iterator and return the new copy.
 | 
						|
  virtual Iterator* CopyIterator(const Field* data,
 | 
						|
                                 const Iterator* iterator) const = 0;
 | 
						|
  // Move an iterator to point to the next element.
 | 
						|
  virtual Iterator* AdvanceIterator(const Field* data,
 | 
						|
                                    Iterator* iterator) const = 0;
 | 
						|
  // Compare whether two iterators point to the same element.
 | 
						|
  virtual bool EqualsIterator(const Field* data, const Iterator* a,
 | 
						|
                              const Iterator* b) const = 0;
 | 
						|
  // Delete an iterator created by BeginIterator(), EndIterator() and
 | 
						|
  // CopyIterator().
 | 
						|
  virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
 | 
						|
  // Like Get() but for iterators.
 | 
						|
  virtual const Value* GetIteratorValue(const Field* data,
 | 
						|
                                        const Iterator* iterator,
 | 
						|
                                        Value* scratch_space) const = 0;
 | 
						|
 | 
						|
  // Templated methods that make using this interface easier for non-message
 | 
						|
  // types.
 | 
						|
  template <typename T>
 | 
						|
  T Get(const Field* data, int index) const {
 | 
						|
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
 | 
						|
    ActualType scratch_space;
 | 
						|
    return static_cast<T>(*reinterpret_cast<const ActualType*>(
 | 
						|
        Get(data, index, static_cast<Value*>(&scratch_space))));
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename T, typename ValueType>
 | 
						|
  void Set(Field* data, int index, const ValueType& value) const {
 | 
						|
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
 | 
						|
    // In this RepeatedFieldAccessor interface we pass/return data using
 | 
						|
    // raw pointers. Type of the data these raw pointers point to should
 | 
						|
    // be ActualType. Here we have a ValueType object and want a ActualType
 | 
						|
    // pointer. We can't cast a ValueType pointer to an ActualType pointer
 | 
						|
    // directly because their type might be different (for enums ValueType
 | 
						|
    // may be a generated enum type while ActualType is int32_t). To be safe
 | 
						|
    // we make a copy to get a temporary ActualType object and use it.
 | 
						|
    ActualType tmp = static_cast<ActualType>(value);
 | 
						|
    Set(data, index, static_cast<const Value*>(&tmp));
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename T, typename ValueType>
 | 
						|
  void Add(Field* data, const ValueType& value) const {
 | 
						|
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
 | 
						|
    // In this RepeatedFieldAccessor interface we pass/return data using
 | 
						|
    // raw pointers. Type of the data these raw pointers point to should
 | 
						|
    // be ActualType. Here we have a ValueType object and want a ActualType
 | 
						|
    // pointer. We can't cast a ValueType pointer to an ActualType pointer
 | 
						|
    // directly because their type might be different (for enums ValueType
 | 
						|
    // may be a generated enum type while ActualType is int32_t). To be safe
 | 
						|
    // we make a copy to get a temporary ActualType object and use it.
 | 
						|
    ActualType tmp = static_cast<ActualType>(value);
 | 
						|
    Add(data, static_cast<const Value*>(&tmp));
 | 
						|
  }
 | 
						|
 | 
						|
 protected:
 | 
						|
  // We want the destructor to be completely trivial as to allow it to be
 | 
						|
  // a function local static. Hence we make it non-virtual and protected,
 | 
						|
  // this class only live as part of a global singleton and should not be
 | 
						|
  // deleted.
 | 
						|
  ~RepeatedFieldAccessor() = default;
 | 
						|
};
 | 
						|
 | 
						|
// Implement (Mutable)RepeatedFieldRef::iterator
 | 
						|
template <typename T>
 | 
						|
class RepeatedFieldRefIterator {
 | 
						|
  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
 | 
						|
  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
 | 
						|
  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
 | 
						|
 | 
						|
 public:
 | 
						|
  using iterator_category = std::forward_iterator_tag;
 | 
						|
  using value_type = T;
 | 
						|
  using pointer = T*;
 | 
						|
  using reference = T&;
 | 
						|
  using difference_type = std::ptrdiff_t;
 | 
						|
 | 
						|
  // Constructor for non-message fields.
 | 
						|
  RepeatedFieldRefIterator(const void* data,
 | 
						|
                           const RepeatedFieldAccessor* accessor, bool begin)
 | 
						|
      : data_(data),
 | 
						|
        accessor_(accessor),
 | 
						|
        iterator_(begin ? accessor->BeginIterator(data)
 | 
						|
                        : accessor->EndIterator(data)),
 | 
						|
        // The end iterator must not be dereferenced, no need for scratch space.
 | 
						|
        scratch_space_(begin ? new AccessorValueType : nullptr) {}
 | 
						|
  // Constructor for message fields.
 | 
						|
  RepeatedFieldRefIterator(const void* data,
 | 
						|
                           const RepeatedFieldAccessor* accessor, bool begin,
 | 
						|
                           AccessorValueType* scratch_space)
 | 
						|
      : data_(data),
 | 
						|
        accessor_(accessor),
 | 
						|
        iterator_(begin ? accessor->BeginIterator(data)
 | 
						|
                        : accessor->EndIterator(data)),
 | 
						|
        scratch_space_(scratch_space) {}
 | 
						|
  ~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); }
 | 
						|
  RepeatedFieldRefIterator operator++(int) {
 | 
						|
    RepeatedFieldRefIterator tmp(*this);
 | 
						|
    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
 | 
						|
    return tmp;
 | 
						|
  }
 | 
						|
  RepeatedFieldRefIterator& operator++() {
 | 
						|
    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
  IteratorValueType operator*() const {
 | 
						|
    return static_cast<IteratorValueType>(
 | 
						|
        *static_cast<const AccessorValueType*>(accessor_->GetIteratorValue(
 | 
						|
            data_, iterator_, scratch_space_.get())));
 | 
						|
  }
 | 
						|
  IteratorPointerType operator->() const {
 | 
						|
    return static_cast<IteratorPointerType>(
 | 
						|
        accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get()));
 | 
						|
  }
 | 
						|
  bool operator!=(const RepeatedFieldRefIterator& other) const {
 | 
						|
    assert(data_ == other.data_);
 | 
						|
    assert(accessor_ == other.accessor_);
 | 
						|
    return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
 | 
						|
  }
 | 
						|
  bool operator==(const RepeatedFieldRefIterator& other) const {
 | 
						|
    return !this->operator!=(other);
 | 
						|
  }
 | 
						|
 | 
						|
  RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
 | 
						|
      : data_(other.data_),
 | 
						|
        accessor_(other.accessor_),
 | 
						|
        iterator_(accessor_->CopyIterator(data_, other.iterator_)) {}
 | 
						|
  RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
 | 
						|
    if (this != &other) {
 | 
						|
      accessor_->DeleteIterator(data_, iterator_);
 | 
						|
      data_ = other.data_;
 | 
						|
      accessor_ = other.accessor_;
 | 
						|
      iterator_ = accessor_->CopyIterator(data_, other.iterator_);
 | 
						|
    }
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
 protected:
 | 
						|
  const void* data_;
 | 
						|
  const RepeatedFieldAccessor* accessor_;
 | 
						|
  void* iterator_;
 | 
						|
  std::unique_ptr<AccessorValueType> scratch_space_;
 | 
						|
};
 | 
						|
 | 
						|
// TypeTraits that maps the type parameter T of RepeatedFieldRef or
 | 
						|
// MutableRepeatedFieldRef to corresponding iterator type,
 | 
						|
// RepeatedFieldAccessor type, etc.
 | 
						|
template <typename T>
 | 
						|
struct PrimitiveTraits {
 | 
						|
  static constexpr bool is_primitive = false;
 | 
						|
};
 | 
						|
#define DEFINE_PRIMITIVE(TYPE, type)                 \
 | 
						|
  template <>                                        \
 | 
						|
  struct PrimitiveTraits<type> {                     \
 | 
						|
    static const bool is_primitive = true;           \
 | 
						|
    static const FieldDescriptor::CppType cpp_type = \
 | 
						|
        FieldDescriptor::CPPTYPE_##TYPE;             \
 | 
						|
  };
 | 
						|
DEFINE_PRIMITIVE(INT32, int32_t)
 | 
						|
DEFINE_PRIMITIVE(UINT32, uint32_t)
 | 
						|
DEFINE_PRIMITIVE(INT64, int64_t)
 | 
						|
DEFINE_PRIMITIVE(UINT64, uint64_t)
 | 
						|
DEFINE_PRIMITIVE(FLOAT, float)
 | 
						|
DEFINE_PRIMITIVE(DOUBLE, double)
 | 
						|
DEFINE_PRIMITIVE(BOOL, bool)
 | 
						|
#undef DEFINE_PRIMITIVE
 | 
						|
 | 
						|
template <typename T>
 | 
						|
struct RefTypeTraits<
 | 
						|
    T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
 | 
						|
  typedef RepeatedFieldRefIterator<T> iterator;
 | 
						|
  typedef RepeatedFieldAccessor AccessorType;
 | 
						|
  typedef T AccessorValueType;
 | 
						|
  typedef T IteratorValueType;
 | 
						|
  typedef T* IteratorPointerType;
 | 
						|
  static constexpr FieldDescriptor::CppType cpp_type =
 | 
						|
      PrimitiveTraits<T>::cpp_type;
 | 
						|
  static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 | 
						|
};
 | 
						|
 | 
						|
template <typename T>
 | 
						|
struct RefTypeTraits<
 | 
						|
    T, typename std::enable_if<is_proto_enum<T>::value>::type> {
 | 
						|
  typedef RepeatedFieldRefIterator<T> iterator;
 | 
						|
  typedef RepeatedFieldAccessor AccessorType;
 | 
						|
  // We use int32_t for repeated enums in RepeatedFieldAccessor.
 | 
						|
  typedef int32_t AccessorValueType;
 | 
						|
  typedef T IteratorValueType;
 | 
						|
  typedef int32_t* IteratorPointerType;
 | 
						|
  static constexpr FieldDescriptor::CppType cpp_type =
 | 
						|
      FieldDescriptor::CPPTYPE_ENUM;
 | 
						|
  static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 | 
						|
};
 | 
						|
 | 
						|
template <typename T>
 | 
						|
struct RefTypeTraits<
 | 
						|
    T, typename std::enable_if<std::is_same<std::string, T>::value>::type> {
 | 
						|
  typedef RepeatedFieldRefIterator<T> iterator;
 | 
						|
  typedef RepeatedFieldAccessor AccessorType;
 | 
						|
  typedef std::string AccessorValueType;
 | 
						|
  typedef const std::string IteratorValueType;
 | 
						|
  typedef const std::string* IteratorPointerType;
 | 
						|
  static constexpr FieldDescriptor::CppType cpp_type =
 | 
						|
      FieldDescriptor::CPPTYPE_STRING;
 | 
						|
  static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 | 
						|
};
 | 
						|
 | 
						|
template <typename T>
 | 
						|
struct MessageDescriptorGetter {
 | 
						|
  static const Descriptor* get() {
 | 
						|
    return T::default_instance().GetDescriptor();
 | 
						|
  }
 | 
						|
};
 | 
						|
template <>
 | 
						|
struct MessageDescriptorGetter<Message> {
 | 
						|
  static const Descriptor* get() { return NULL; }
 | 
						|
};
 | 
						|
 | 
						|
template <typename T>
 | 
						|
struct RefTypeTraits<
 | 
						|
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
 | 
						|
  typedef RepeatedFieldRefIterator<T> iterator;
 | 
						|
  typedef RepeatedFieldAccessor AccessorType;
 | 
						|
  typedef Message AccessorValueType;
 | 
						|
  typedef const T& IteratorValueType;
 | 
						|
  typedef const T* IteratorPointerType;
 | 
						|
  static constexpr FieldDescriptor::CppType cpp_type =
 | 
						|
      FieldDescriptor::CPPTYPE_MESSAGE;
 | 
						|
  static const Descriptor* GetMessageFieldDescriptor() {
 | 
						|
    return MessageDescriptorGetter<T>::get();
 | 
						|
  }
 | 
						|
};
 | 
						|
}  // namespace internal
 | 
						|
}  // namespace protobuf
 | 
						|
}  // namespace google
 | 
						|
 | 
						|
#include <google/protobuf/port_undef.inc>
 | 
						|
 | 
						|
#endif  // GOOGLE_PROTOBUF_REFLECTION_H__
 |