// 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. #ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ #include #include #include namespace google { namespace protobuf { namespace internal { // A base class for RepeatedFieldAccessor implementations that can support // random-access efficiently. All iterator methods delegates the work to // corresponding random-access methods. class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { public: Iterator* BeginIterator(const Field* data) const override { return PositionToIterator(0); } Iterator* EndIterator(const Field* data) const override { return PositionToIterator(this->Size(data)); } Iterator* CopyIterator(const Field* data, const Iterator* iterator) const override { return const_cast(iterator); } Iterator* AdvanceIterator(const Field* data, Iterator* iterator) const override { return PositionToIterator(IteratorToPosition(iterator) + 1); } bool EqualsIterator(const Field* data, const Iterator* a, const Iterator* b) const override { return a == b; } void DeleteIterator(const Field* data, Iterator* iterator) const override {} const Value* GetIteratorValue(const Field* data, const Iterator* iterator, Value* scratch_space) const override { return Get(data, static_cast(IteratorToPosition(iterator)), scratch_space); } protected: ~RandomAccessRepeatedFieldAccessor() = default; private: static intptr_t IteratorToPosition(const Iterator* iterator) { return reinterpret_cast(iterator); } static Iterator* PositionToIterator(intptr_t position) { return reinterpret_cast(position); } }; // Base class for RepeatedFieldAccessor implementations that manipulates // RepeatedField. template class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { public: RepeatedFieldWrapper() {} bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } const Value* Get(const Field* data, int index, Value* scratch_space) const override { return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); } void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } void Set(Field* data, int index, const Value* value) const override { MutableRepeatedField(data)->Set(index, ConvertToT(value)); } void Add(Field* data, const Value* value) const override { MutableRepeatedField(data)->Add(ConvertToT(value)); } void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } protected: ~RepeatedFieldWrapper() = default; typedef RepeatedField RepeatedFieldType; static const RepeatedFieldType* GetRepeatedField(const Field* data) { return reinterpret_cast(data); } static RepeatedFieldType* MutableRepeatedField(Field* data) { return reinterpret_cast(data); } // Convert an object recevied by this accessor to an object to be stored in // the underlying RepeatedField. virtual T ConvertToT(const Value* value) const = 0; // Convert an object stored in RepeatedPtrField to an object that will be // returned by this accessor. If the two objects have the same type (true for // string fields with ctype=STRING), a pointer to the source object can be // returned directly. Otherwise, data should be copied from value to // scratch_space and scratch_space should be returned. virtual const Value* ConvertFromT(const T& value, Value* scratch_space) const = 0; }; // Base class for RepeatedFieldAccessor implementations that manipulates // RepeatedPtrField. template class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { public: bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } const Value* Get(const Field* data, int index, Value* scratch_space) const override { return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); } void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } void Set(Field* data, int index, const Value* value) const override { ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); } void Add(Field* data, const Value* value) const override { T* allocated = New(value); ConvertToT(value, allocated); MutableRepeatedField(data)->AddAllocated(allocated); } void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } protected: ~RepeatedPtrFieldWrapper() = default; typedef RepeatedPtrField RepeatedFieldType; static const RepeatedFieldType* GetRepeatedField(const Field* data) { return reinterpret_cast(data); } static RepeatedFieldType* MutableRepeatedField(Field* data) { return reinterpret_cast(data); } // Create a new T instance. For repeated message fields, T can be specified // as google::protobuf::Message so we can't use "new T()" directly. In that case, value // should be a message of the same type (it's ensured by the caller) and a // new message object will be created using it. virtual T* New(const Value* value) const = 0; // Convert an object received by this accessor to an object that will be // stored in the underlying RepeatedPtrField. virtual void ConvertToT(const Value* value, T* result) const = 0; // Convert an object stored in RepeatedPtrField to an object that will be // returned by this accessor. If the two objects have the same type (true for // string fields with ctype=STRING), a pointer to the source object can be // returned directly. Otherwise, data should be copied from value to // scratch_space and scratch_space should be returned. virtual const Value* ConvertFromT(const T& value, Value* scratch_space) const = 0; }; // An implementation of RandomAccessRepeatedFieldAccessor that manipulates // MapFieldBase. class MapFieldAccessor final : public RandomAccessRepeatedFieldAccessor { public: MapFieldAccessor() {} virtual ~MapFieldAccessor() {} bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } const Value* Get(const Field* data, int index, Value* scratch_space) const override { return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); } void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } void Set(Field* data, int index, const Value* value) const override { ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); } void Add(Field* data, const Value* value) const override { Message* allocated = New(value); ConvertToEntry(value, allocated); MutableRepeatedField(data)->AddAllocated(allocated); } void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, Field* other_data) const override { GOOGLE_CHECK(this == other_mutator); MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } protected: typedef RepeatedPtrField RepeatedFieldType; static const RepeatedFieldType* GetRepeatedField(const Field* data) { return reinterpret_cast( (&reinterpret_cast(data)->GetRepeatedField())); } static RepeatedFieldType* MutableRepeatedField(Field* data) { return reinterpret_cast( reinterpret_cast(data)->MutableRepeatedField()); } virtual Message* New(const Value* value) const { return static_cast(value)->New(); } // Convert an object received by this accessor to an MapEntry message to be // stored in the underlying MapFieldBase. virtual void ConvertToEntry(const Value* value, Message* result) const { result->CopyFrom(*static_cast(value)); } // Convert a MapEntry message stored in the underlying MapFieldBase to an // object that will be returned by this accessor. virtual const Value* ConvertFromEntry(const Message& value, Value* scratch_space) const { return static_cast(&value); } }; // Default implementations of RepeatedFieldAccessor for primitive types. template class RepeatedFieldPrimitiveAccessor final : public RepeatedFieldWrapper { typedef void Field; typedef void Value; using RepeatedFieldWrapper::MutableRepeatedField; public: RepeatedFieldPrimitiveAccessor() {} void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, Field* other_data) const override { // Currently RepeatedFieldPrimitiveAccessor is the only implementation of // RepeatedFieldAccessor for primitive types. As we are using singletons // for these accessors, here "other_mutator" must be "this". GOOGLE_CHECK(this == other_mutator); MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } protected: T ConvertToT(const Value* value) const override { return *static_cast(value); } const Value* ConvertFromT(const T& value, Value* scratch_space) const override { return static_cast(&value); } }; // Default implementation of RepeatedFieldAccessor for string fields with // ctype=STRING. class RepeatedPtrFieldStringAccessor final : public RepeatedPtrFieldWrapper { typedef void Field; typedef void Value; using RepeatedFieldAccessor::Add; public: RepeatedPtrFieldStringAccessor() {} void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, Field* other_data) const override { if (this == other_mutator) { MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } else { RepeatedPtrField tmp; tmp.Swap(MutableRepeatedField(data)); int other_size = other_mutator->Size(other_data); for (int i = 0; i < other_size; ++i) { Add(data, other_mutator->Get(other_data, i)); } int size = Size(data); other_mutator->Clear(other_data); for (int i = 0; i < size; ++i) { other_mutator->Add(other_data, tmp.Get(i)); } } } protected: std::string* New(const Value*) const override { return new std::string(); } void ConvertToT(const Value* value, std::string* result) const override { *result = *static_cast(value); } const Value* ConvertFromT(const std::string& value, Value* scratch_space) const override { return static_cast(&value); } }; class RepeatedPtrFieldMessageAccessor final : public RepeatedPtrFieldWrapper { typedef void Field; typedef void Value; public: RepeatedPtrFieldMessageAccessor() {} void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, Field* other_data) const override { GOOGLE_CHECK(this == other_mutator); MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } protected: Message* New(const Value* value) const override { return static_cast(value)->New(); } void ConvertToT(const Value* value, Message* result) const override { result->CopyFrom(*static_cast(value)); } const Value* ConvertFromT(const Message& value, Value* scratch_space) const override { return static_cast(&value); } }; } // namespace internal } // namespace protobuf } // namespace google #endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__