|  | // 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 <google/protobuf/map_field.h> | 
|  | #include <google/protobuf/reflection.h> | 
|  | #include <google/protobuf/repeated_field.h> | 
|  |  | 
|  | 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: | 
|  | virtual ~RandomAccessRepeatedFieldAccessor() {} | 
|  |  | 
|  | virtual Iterator* BeginIterator(const Field* data) const { | 
|  | return PositionToIterator(0); | 
|  | } | 
|  | virtual Iterator* EndIterator(const Field* data) const { | 
|  | return PositionToIterator(this->Size(data)); | 
|  | } | 
|  | virtual Iterator* CopyIterator(const Field* data, | 
|  | const Iterator* iterator) const { | 
|  | return const_cast<Iterator*>(iterator); | 
|  | } | 
|  | virtual Iterator* AdvanceIterator(const Field* data, | 
|  | Iterator* iterator) const { | 
|  | return PositionToIterator(IteratorToPosition(iterator) + 1); | 
|  | } | 
|  | virtual bool EqualsIterator(const Field* data, | 
|  | const Iterator* a, | 
|  | const Iterator* b) const { | 
|  | return a == b; | 
|  | } | 
|  | virtual void DeleteIterator(const Field* data, Iterator* iterator) const { | 
|  | } | 
|  | virtual const Value* GetIteratorValue(const Field* data, | 
|  | const Iterator* iterator, | 
|  | Value* scratch_space) const { | 
|  | return Get(data, static_cast<int>(IteratorToPosition(iterator)), | 
|  | scratch_space); | 
|  | } | 
|  |  | 
|  | private: | 
|  | static intptr_t IteratorToPosition(const Iterator* iterator) { | 
|  | return reinterpret_cast<intptr_t>(iterator); | 
|  | } | 
|  | static Iterator* PositionToIterator(intptr_t position) { | 
|  | return reinterpret_cast<Iterator*>(position); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Base class for RepeatedFieldAccessor implementations that manipulates | 
|  | // RepeatedField<T>. | 
|  | template<typename T> | 
|  | class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { | 
|  | public: | 
|  | RepeatedFieldWrapper() {} | 
|  | virtual ~RepeatedFieldWrapper() {} | 
|  | virtual bool IsEmpty(const Field* data) const { | 
|  | return GetRepeatedField(data)->empty(); | 
|  | } | 
|  | virtual int Size(const Field* data) const { | 
|  | return GetRepeatedField(data)->size(); | 
|  | } | 
|  | virtual const Value* Get(const Field* data, int index, | 
|  | Value* scratch_space) const { | 
|  | return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); | 
|  | } | 
|  | virtual void Clear(Field* data) const { | 
|  | MutableRepeatedField(data)->Clear(); | 
|  | } | 
|  | virtual void Set(Field* data, int index, const Value* value) const { | 
|  | MutableRepeatedField(data)->Set(index, ConvertToT(value)); | 
|  | } | 
|  | virtual void Add(Field* data, const Value* value) const { | 
|  | MutableRepeatedField(data)->Add(ConvertToT(value)); | 
|  | } | 
|  | virtual void RemoveLast(Field* data) const { | 
|  | MutableRepeatedField(data)->RemoveLast(); | 
|  | } | 
|  | virtual void SwapElements(Field* data, int index1, int index2) const { | 
|  | MutableRepeatedField(data)->SwapElements(index1, index2); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | typedef RepeatedField<T> RepeatedFieldType; | 
|  | static const RepeatedFieldType* GetRepeatedField(const Field* data) { | 
|  | return reinterpret_cast<const RepeatedFieldType*>(data); | 
|  | } | 
|  | static RepeatedFieldType* MutableRepeatedField(Field* data) { | 
|  | return reinterpret_cast<RepeatedFieldType*>(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<T>. | 
|  | template<typename T> | 
|  | class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { | 
|  | public: | 
|  | RepeatedPtrFieldWrapper() {} | 
|  | virtual ~RepeatedPtrFieldWrapper() {} | 
|  | virtual bool IsEmpty(const Field* data) const { | 
|  | return GetRepeatedField(data)->empty(); | 
|  | } | 
|  | virtual int Size(const Field* data) const { | 
|  | return GetRepeatedField(data)->size(); | 
|  | } | 
|  | virtual const Value* Get(const Field* data, int index, | 
|  | Value* scratch_space) const { | 
|  | return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); | 
|  | } | 
|  | virtual void Clear(Field* data) const { | 
|  | MutableRepeatedField(data)->Clear(); | 
|  | } | 
|  | virtual void Set(Field* data, int index, const Value* value) const { | 
|  | ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); | 
|  | } | 
|  | virtual void Add(Field* data, const Value* value) const { | 
|  | T* allocated = New(value); | 
|  | ConvertToT(value, allocated); | 
|  | MutableRepeatedField(data)->AddAllocated(allocated); | 
|  | } | 
|  | virtual void RemoveLast(Field* data) const { | 
|  | MutableRepeatedField(data)->RemoveLast(); | 
|  | } | 
|  | virtual void SwapElements(Field* data, int index1, int index2) const { | 
|  | MutableRepeatedField(data)->SwapElements(index1, index2); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | typedef RepeatedPtrField<T> RepeatedFieldType; | 
|  | static const RepeatedFieldType* GetRepeatedField(const Field* data) { | 
|  | return reinterpret_cast<const RepeatedFieldType*>(data); | 
|  | } | 
|  | static RepeatedFieldType* MutableRepeatedField(Field* data) { | 
|  | return reinterpret_cast<RepeatedFieldType*>(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 : public RandomAccessRepeatedFieldAccessor { | 
|  | public: | 
|  | MapFieldAccessor() {} | 
|  | virtual ~MapFieldAccessor() {} | 
|  | virtual bool IsEmpty(const Field* data) const { | 
|  | return GetRepeatedField(data)->empty(); | 
|  | } | 
|  | virtual int Size(const Field* data) const { | 
|  | return GetRepeatedField(data)->size(); | 
|  | } | 
|  | virtual const Value* Get(const Field* data, int index, | 
|  | Value* scratch_space) const { | 
|  | return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); | 
|  | } | 
|  | virtual void Clear(Field* data) const { | 
|  | MutableRepeatedField(data)->Clear(); | 
|  | } | 
|  | virtual void Set(Field* data, int index, const Value* value) const { | 
|  | ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); | 
|  | } | 
|  | virtual void Add(Field* data, const Value* value) const { | 
|  | Message* allocated = New(value); | 
|  | ConvertToEntry(value, allocated); | 
|  | MutableRepeatedField(data)->AddAllocated(allocated); | 
|  | } | 
|  | virtual void RemoveLast(Field* data) const { | 
|  | MutableRepeatedField(data)->RemoveLast(); | 
|  | } | 
|  | virtual void SwapElements(Field* data, int index1, int index2) const { | 
|  | MutableRepeatedField(data)->SwapElements(index1, index2); | 
|  | } | 
|  | virtual void Swap( | 
|  | Field* data, | 
|  | const internal::RepeatedFieldAccessor* other_mutator, | 
|  | Field* other_data) const { | 
|  | GOOGLE_CHECK(this == other_mutator); | 
|  | MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | typedef RepeatedPtrField<Message> RepeatedFieldType; | 
|  | static const RepeatedFieldType* GetRepeatedField(const Field* data) { | 
|  | return reinterpret_cast<const RepeatedFieldType*>( | 
|  | (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField())); | 
|  | } | 
|  | static RepeatedFieldType* MutableRepeatedField(Field* data) { | 
|  | return reinterpret_cast<RepeatedFieldType*>( | 
|  | reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField()); | 
|  | } | 
|  | virtual Message* New(const Value* value) const { | 
|  | return static_cast<const Message*>(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<const Message*>(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<const Value*>(&value); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Default implementations of RepeatedFieldAccessor for primitive types. | 
|  | template<typename T> | 
|  | class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> { | 
|  | typedef void Field; | 
|  | typedef void Value; | 
|  | using RepeatedFieldWrapper<T>::MutableRepeatedField; | 
|  |  | 
|  | public: | 
|  | RepeatedFieldPrimitiveAccessor() {} | 
|  | virtual ~RepeatedFieldPrimitiveAccessor() {} | 
|  | virtual void Swap( | 
|  | Field* data, | 
|  | const internal::RepeatedFieldAccessor* other_mutator, | 
|  | Field* other_data) const { | 
|  | // 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: | 
|  | virtual T ConvertToT(const Value* value) const { | 
|  | return *static_cast<const T*>(value); | 
|  | } | 
|  | virtual const Value* ConvertFromT(const T& value, | 
|  | Value* scratch_space) const { | 
|  | return static_cast<const Value*>(&value); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Default implementation of RepeatedFieldAccessor for string fields with | 
|  | // ctype=STRING. | 
|  | class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> { | 
|  | typedef void Field; | 
|  | typedef void Value; | 
|  | using RepeatedFieldAccessor::Add; | 
|  |  | 
|  | public: | 
|  | RepeatedPtrFieldStringAccessor() {} | 
|  | virtual ~RepeatedPtrFieldStringAccessor() {} | 
|  | virtual void Swap( | 
|  | Field* data, | 
|  | const internal::RepeatedFieldAccessor* other_mutator, | 
|  | Field* other_data) const { | 
|  | if (this == other_mutator) { | 
|  | MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); | 
|  | } else { | 
|  | RepeatedPtrField<string> tmp; | 
|  | tmp.Swap(MutableRepeatedField(data)); | 
|  | int other_size = other_mutator->Size(other_data); | 
|  | for (int i = 0; i < other_size; ++i) { | 
|  | Add<string>(data, other_mutator->Get<string>(other_data, i)); | 
|  | } | 
|  | int size = Size(data); | 
|  | other_mutator->Clear(other_data); | 
|  | for (int i = 0; i < size; ++i) { | 
|  | other_mutator->Add<string>(other_data, tmp.Get(i)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | protected: | 
|  | virtual string* New(const Value*) const { | 
|  | return new string(); | 
|  | } | 
|  | virtual void ConvertToT(const Value* value, string* result) const { | 
|  | *result = *static_cast<const string*>(value); | 
|  | } | 
|  | virtual const Value* ConvertFromT(const string& value, | 
|  | Value* scratch_space) const { | 
|  | return static_cast<const Value*>(&value); | 
|  | } | 
|  | }; | 
|  |  | 
|  |  | 
|  | class RepeatedPtrFieldMessageAccessor | 
|  | : public RepeatedPtrFieldWrapper<Message> { | 
|  | typedef void Field; | 
|  | typedef void Value; | 
|  |  | 
|  | public: | 
|  | RepeatedPtrFieldMessageAccessor() {} | 
|  | virtual ~RepeatedPtrFieldMessageAccessor() {} | 
|  | virtual void Swap( | 
|  | Field* data, | 
|  | const internal::RepeatedFieldAccessor* other_mutator, | 
|  | Field* other_data) const { | 
|  | GOOGLE_CHECK(this == other_mutator); | 
|  | MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | virtual Message* New(const Value* value) const { | 
|  | return static_cast<const Message*>(value)->New(); | 
|  | } | 
|  | virtual void ConvertToT(const Value* value, Message* result) const { | 
|  | result->CopyFrom(*static_cast<const Message*>(value)); | 
|  | } | 
|  | virtual const Value* ConvertFromT(const Message& value, | 
|  | Value* scratch_space) const { | 
|  | return static_cast<const Value*>(&value); | 
|  | } | 
|  | }; | 
|  | }  // namespace internal | 
|  | }  // namespace protobuf | 
|  |  | 
|  | }  // namespace google | 
|  | #endif  // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ |