// 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 #include #include #ifdef SWIG #error "You cannot SWIG proto headers" #endif #include namespace google { namespace protobuf { namespace internal { template struct RefTypeTraits; } // namespace internal template RepeatedFieldRef Reflection::GetRepeatedFieldRef( const Message& message, const FieldDescriptor* field) const { return RepeatedFieldRef(message, field); } template MutableRepeatedFieldRef Reflection::GetMutableRepeatedFieldRef( Message* message, const FieldDescriptor* field) const { return MutableRepeatedFieldRef(message, field); } // RepeatedFieldRef definition for non-message types. template class RepeatedFieldRef< T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::iterator IteratorType; typedef typename internal::RefTypeTraits::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(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), field, internal::RefTypeTraits::cpp_type, nullptr); accessor_ = reflection->RepeatedFieldAccessor(field); } const void* data_; const AccessorType* accessor_; }; // MutableRepeatedFieldRef definition for non-message types. template class MutableRepeatedFieldRef< T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::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(data_, index); } void Set(int index, const T& value) const { accessor_->template Set(data_, index, value); } void Add(const T& value) const { accessor_->template 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 void MergeFrom(const Container& container) const { typedef typename Container::const_iterator Iterator; for (Iterator it = container.begin(); it != container.end(); ++it) { Add(*it); } } template 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::cpp_type, nullptr); accessor_ = reflection->RepeatedFieldAccessor(field); } void* data_; const AccessorType* accessor_; }; // RepeatedFieldRef definition for message types. template class RepeatedFieldRef< T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::iterator IteratorType; typedef typename internal::RefTypeTraits::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 h = ... // unique_ptr 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(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(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), field, internal::RefTypeTraits::cpp_type, internal::RefTypeTraits::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 class MutableRepeatedFieldRef< T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::AccessorType AccessorType; public: bool empty() const { return accessor_->IsEmpty(data_); } int size() const { return accessor_->Size(data_); } // See comments for RepeatedFieldRef::Get() const T& Get(int index, T* scratch_space) const { return *static_cast(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(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 void MergeFrom(const Container& container) const { typedef typename Container::const_iterator Iterator; for (Iterator it = container.begin(); it != container.end(); ++it) { Add(*it); } } template 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::cpp_type, internal::RefTypeTraits::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::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 T Get(const Field* data, int index) const { typedef typename RefTypeTraits::AccessorValueType ActualType; ActualType scratch_space; return static_cast(*reinterpret_cast( Get(data, index, static_cast(&scratch_space)))); } template void Set(Field* data, int index, const ValueType& value) const { typedef typename RefTypeTraits::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(value); Set(data, index, static_cast(&tmp)); } template void Add(Field* data, const ValueType& value) const { typedef typename RefTypeTraits::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(value); Add(data, static_cast(&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 class RepeatedFieldRefIterator { typedef typename RefTypeTraits::AccessorValueType AccessorValueType; typedef typename RefTypeTraits::IteratorValueType IteratorValueType; typedef typename RefTypeTraits::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( *static_cast(accessor_->GetIteratorValue( data_, iterator_, scratch_space_.get()))); } IteratorPointerType operator->() const { return static_cast( 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 scratch_space_; }; // TypeTraits that maps the type parameter T of RepeatedFieldRef or // MutableRepeatedFieldRef to corresponding iterator type, // RepeatedFieldAccessor type, etc. template struct PrimitiveTraits { static constexpr bool is_primitive = false; }; #define DEFINE_PRIMITIVE(TYPE, type) \ template <> \ struct PrimitiveTraits { \ 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 struct RefTypeTraits< T, typename std::enable_if::is_primitive>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; typedef T AccessorValueType; typedef T IteratorValueType; typedef T* IteratorPointerType; static constexpr FieldDescriptor::CppType cpp_type = PrimitiveTraits::cpp_type; static const Descriptor* GetMessageFieldDescriptor() { return nullptr; } }; template struct RefTypeTraits< T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator 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 nullptr; } }; template struct RefTypeTraits< T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator 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 nullptr; } }; template struct MessageDescriptorGetter { static const Descriptor* get() { return T::default_instance().GetDescriptor(); } }; template <> struct MessageDescriptorGetter { static const Descriptor* get() { return nullptr; } }; template struct RefTypeTraits< T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator 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::get(); } }; } // namespace internal } // namespace protobuf } // namespace google #include #endif // GOOGLE_PROTOBUF_REFLECTION_H__