// 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>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif

#include <google/protobuf/message.h>
#include <google/protobuf/generated_enum_util.h>

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 internal::enable_if<!internal::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;
  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 internal::enable_if<!internal::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 internal::enable_if<internal::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;
  iterator begin() const {
    return iterator(data_, accessor_, true, NewMessage());
  }
  iterator end() const {
    return iterator(data_, accessor_, false, NewMessage());
  }

 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 internal::enable_if<internal::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                   int32
//   CPPTYPE_UINT32       uint32                  uint32
//   CPPTYPE_INT64        int64                   int64
//   CPPTYPE_UINT64       uint64                  uint64
//   CPPTYPE_DOUBLE       double                  double
//   CPPTYPE_FLOAT        float                   float
//   CPPTYPE_BOOL         bool                    bool
//   CPPTYPE_ENUM         generated enum type     int32
//   CPPTYPE_STRING       string                  string
//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
//                        or google::protobuf::Message
//
// Note that for enums we use int32 in the interface.
//
// You can map from T to the actual type using RefTypeTraits:
//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
 public:
  // Typedefs for clarity.
  typedef void Field;
  typedef void Value;
  typedef void Iterator;

  virtual ~RepeatedFieldAccessor();
  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 begining 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). 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). 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));
  }
};

// Implement (Mutable)RepeatedFieldRef::iterator
template<typename T>
class RepeatedFieldRefIterator
    : public std::iterator<std::forward_iterator_tag, T> {
  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;

 public:
  // 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)),
        scratch_space_(new AccessorValueType) {
  }
  // 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_;
  google::protobuf::scoped_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 const 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)
DEFINE_PRIMITIVE(UINT32, uint32)
DEFINE_PRIMITIVE(INT64, int64)
DEFINE_PRIMITIVE(UINT64, uint64)
DEFINE_PRIMITIVE(FLOAT, float)
DEFINE_PRIMITIVE(DOUBLE, double)
DEFINE_PRIMITIVE(BOOL, bool)
#undef DEFINE_PRIMITIVE

template<typename T>
struct RefTypeTraits<
    T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  typedef T AccessorValueType;
  typedef T IteratorValueType;
  typedef T* IteratorPointerType;
  static const FieldDescriptor::CppType cpp_type =
      PrimitiveTraits<T>::cpp_type;
  static const Descriptor* GetMessageFieldDescriptor() {
    return NULL;
  }
};

template<typename T>
struct RefTypeTraits<
    T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  // We use int32 for repeated enums in RepeatedFieldAccessor.
  typedef int32 AccessorValueType;
  typedef T IteratorValueType;
  typedef int32* IteratorPointerType;
  static const FieldDescriptor::CppType cpp_type =
      FieldDescriptor::CPPTYPE_ENUM;
  static const Descriptor* GetMessageFieldDescriptor() {
    return NULL;
  }
};

template<typename T>
struct RefTypeTraits<
    T, typename internal::enable_if< ::google::protobuf::internal::is_same<string, T>::value>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  typedef string AccessorValueType;
  typedef string IteratorValueType;
  typedef string* IteratorPointerType;
  static const 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 internal::enable_if<internal::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 const FieldDescriptor::CppType cpp_type =
      FieldDescriptor::CPPTYPE_MESSAGE;
  static const Descriptor* GetMessageFieldDescriptor() {
    return MessageDescriptorGetter<T>::get();
  }
};
}  // namespace internal
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_REFLECTION_H__
