• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
32 #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
33 
34 #include <google/protobuf/map_field.h>
35 #include <google/protobuf/reflection.h>
36 #include <google/protobuf/repeated_field.h>
37 
38 namespace google {
39 namespace protobuf {
40 namespace internal {
41 // A base class for RepeatedFieldAccessor implementations that can support
42 // random-access efficiently. All iterator methods delegates the work to
43 // corresponding random-access methods.
44 class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor {
45  public:
~RandomAccessRepeatedFieldAccessor()46   virtual ~RandomAccessRepeatedFieldAccessor() {}
47 
BeginIterator(const Field * data)48   virtual Iterator* BeginIterator(const Field* data) const {
49     return PositionToIterator(0);
50   }
EndIterator(const Field * data)51   virtual Iterator* EndIterator(const Field* data) const {
52     return PositionToIterator(this->Size(data));
53   }
CopyIterator(const Field * data,const Iterator * iterator)54   virtual Iterator* CopyIterator(const Field* data,
55                                  const Iterator* iterator) const {
56     return const_cast<Iterator*>(iterator);
57   }
AdvanceIterator(const Field * data,Iterator * iterator)58   virtual Iterator* AdvanceIterator(const Field* data,
59                                     Iterator* iterator) const {
60     return PositionToIterator(IteratorToPosition(iterator) + 1);
61   }
EqualsIterator(const Field * data,const Iterator * a,const Iterator * b)62   virtual bool EqualsIterator(const Field* data,
63                               const Iterator* a,
64                               const Iterator* b) const {
65     return a == b;
66   }
DeleteIterator(const Field * data,Iterator * iterator)67   virtual void DeleteIterator(const Field* data, Iterator* iterator) const {
68   }
GetIteratorValue(const Field * data,const Iterator * iterator,Value * scratch_space)69   virtual const Value* GetIteratorValue(const Field* data,
70                                         const Iterator* iterator,
71                                         Value* scratch_space) const {
72     return Get(data, static_cast<int>(IteratorToPosition(iterator)),
73                scratch_space);
74   }
75 
76  private:
IteratorToPosition(const Iterator * iterator)77   static intptr_t IteratorToPosition(const Iterator* iterator) {
78     return reinterpret_cast<intptr_t>(iterator);
79   }
PositionToIterator(intptr_t position)80   static Iterator* PositionToIterator(intptr_t position) {
81     return reinterpret_cast<Iterator*>(position);
82   }
83 };
84 
85 // Base class for RepeatedFieldAccessor implementations that manipulates
86 // RepeatedField<T>.
87 template<typename T>
88 class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor {
89  public:
RepeatedFieldWrapper()90   RepeatedFieldWrapper() {}
~RepeatedFieldWrapper()91   virtual ~RepeatedFieldWrapper() {}
IsEmpty(const Field * data)92   virtual bool IsEmpty(const Field* data) const {
93     return GetRepeatedField(data)->empty();
94   }
Size(const Field * data)95   virtual int Size(const Field* data) const {
96     return GetRepeatedField(data)->size();
97   }
Get(const Field * data,int index,Value * scratch_space)98   virtual const Value* Get(const Field* data, int index,
99                           Value* scratch_space) const {
100     return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
101   }
Clear(Field * data)102   virtual void Clear(Field* data) const {
103     MutableRepeatedField(data)->Clear();
104   }
Set(Field * data,int index,const Value * value)105   virtual void Set(Field* data, int index, const Value* value) const {
106     MutableRepeatedField(data)->Set(index, ConvertToT(value));
107   }
Add(Field * data,const Value * value)108   virtual void Add(Field* data, const Value* value) const {
109     MutableRepeatedField(data)->Add(ConvertToT(value));
110   }
RemoveLast(Field * data)111   virtual void RemoveLast(Field* data) const {
112     MutableRepeatedField(data)->RemoveLast();
113   }
SwapElements(Field * data,int index1,int index2)114   virtual void SwapElements(Field* data, int index1, int index2) const {
115     MutableRepeatedField(data)->SwapElements(index1, index2);
116   }
117 
118  protected:
119   typedef RepeatedField<T> RepeatedFieldType;
GetRepeatedField(const Field * data)120   static const RepeatedFieldType* GetRepeatedField(const Field* data) {
121     return reinterpret_cast<const RepeatedFieldType*>(data);
122   }
MutableRepeatedField(Field * data)123   static RepeatedFieldType* MutableRepeatedField(Field* data) {
124     return reinterpret_cast<RepeatedFieldType*>(data);
125   }
126 
127   // Convert an object recevied by this accessor to an object to be stored in
128   // the underlying RepeatedField.
129   virtual T ConvertToT(const Value* value) const = 0;
130 
131   // Convert an object stored in RepeatedPtrField to an object that will be
132   // returned by this accessor. If the two objects have the same type (true
133   // for string fields with ctype=STRING), a pointer to the source object can
134   // be returned directly. Otherwise, data should be copied from value to
135   // scratch_space and scratch_space should be returned.
136   virtual const Value* ConvertFromT(const T& value,
137                                     Value* scratch_space) const = 0;
138 };
139 
140 // Base class for RepeatedFieldAccessor implementations that manipulates
141 // RepeatedPtrField<T>.
142 template<typename T>
143 class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
144  public:
RepeatedPtrFieldWrapper()145   RepeatedPtrFieldWrapper() {}
~RepeatedPtrFieldWrapper()146   virtual ~RepeatedPtrFieldWrapper() {}
IsEmpty(const Field * data)147   virtual bool IsEmpty(const Field* data) const {
148     return GetRepeatedField(data)->empty();
149   }
Size(const Field * data)150   virtual int Size(const Field* data) const {
151     return GetRepeatedField(data)->size();
152   }
Get(const Field * data,int index,Value * scratch_space)153   virtual const Value* Get(const Field* data, int index,
154                            Value* scratch_space) const {
155     return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
156   }
Clear(Field * data)157   virtual void Clear(Field* data) const {
158     MutableRepeatedField(data)->Clear();
159   }
Set(Field * data,int index,const Value * value)160   virtual void Set(Field* data, int index, const Value* value) const {
161     ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
162   }
Add(Field * data,const Value * value)163   virtual void Add(Field* data, const Value* value) const {
164     T* allocated = New(value);
165     ConvertToT(value, allocated);
166     MutableRepeatedField(data)->AddAllocated(allocated);
167   }
RemoveLast(Field * data)168   virtual void RemoveLast(Field* data) const {
169     MutableRepeatedField(data)->RemoveLast();
170   }
SwapElements(Field * data,int index1,int index2)171   virtual void SwapElements(Field* data, int index1, int index2) const {
172     MutableRepeatedField(data)->SwapElements(index1, index2);
173   }
174 
175  protected:
176   typedef RepeatedPtrField<T> RepeatedFieldType;
GetRepeatedField(const Field * data)177   static const RepeatedFieldType* GetRepeatedField(const Field* data) {
178     return reinterpret_cast<const RepeatedFieldType*>(data);
179   }
MutableRepeatedField(Field * data)180   static RepeatedFieldType* MutableRepeatedField(Field* data) {
181     return reinterpret_cast<RepeatedFieldType*>(data);
182   }
183 
184   // Create a new T instance. For repeated message fields, T can be specified
185   // as google::protobuf::Message so we can't use "new T()" directly. In that case, value
186   // should be a message of the same type (it's ensured by the caller) and a
187   // new message object will be created using it.
188   virtual T* New(const Value* value) const = 0;
189 
190   // Convert an object received by this accessor to an object that will be
191   // stored in the underlying RepeatedPtrField.
192   virtual void ConvertToT(const Value* value, T* result) const = 0;
193 
194   // Convert an object stored in RepeatedPtrField to an object that will be
195   // returned by this accessor. If the two objects have the same type (true
196   // for string fields with ctype=STRING), a pointer to the source object can
197   // be returned directly. Otherwise, data should be copied from value to
198   // scratch_space and scratch_space should be returned.
199   virtual const Value* ConvertFromT(const T& value,
200                                     Value* scratch_space) const = 0;
201 };
202 
203 // An implementation of RandomAccessRepeatedFieldAccessor that manipulates
204 // MapFieldBase.
205 class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor {
206  public:
MapFieldAccessor()207   MapFieldAccessor() {}
~MapFieldAccessor()208   virtual ~MapFieldAccessor() {}
IsEmpty(const Field * data)209   virtual bool IsEmpty(const Field* data) const {
210     return GetRepeatedField(data)->empty();
211   }
Size(const Field * data)212   virtual int Size(const Field* data) const {
213     return GetRepeatedField(data)->size();
214   }
Get(const Field * data,int index,Value * scratch_space)215   virtual const Value* Get(const Field* data, int index,
216                            Value* scratch_space) const {
217     return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space);
218   }
Clear(Field * data)219   virtual void Clear(Field* data) const {
220     MutableRepeatedField(data)->Clear();
221   }
Set(Field * data,int index,const Value * value)222   virtual void Set(Field* data, int index, const Value* value) const {
223     ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
224   }
Add(Field * data,const Value * value)225   virtual void Add(Field* data, const Value* value) const {
226     Message* allocated = New(value);
227     ConvertToEntry(value, allocated);
228     MutableRepeatedField(data)->AddAllocated(allocated);
229   }
RemoveLast(Field * data)230   virtual void RemoveLast(Field* data) const {
231     MutableRepeatedField(data)->RemoveLast();
232   }
SwapElements(Field * data,int index1,int index2)233   virtual void SwapElements(Field* data, int index1, int index2) const {
234     MutableRepeatedField(data)->SwapElements(index1, index2);
235   }
Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)236   virtual void Swap(
237       Field* data,
238       const internal::RepeatedFieldAccessor* other_mutator,
239       Field* other_data) const {
240     GOOGLE_CHECK(this == other_mutator);
241     MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
242   }
243 
244  protected:
245   typedef RepeatedPtrField<Message> RepeatedFieldType;
GetRepeatedField(const Field * data)246   static const RepeatedFieldType* GetRepeatedField(const Field* data) {
247     return reinterpret_cast<const RepeatedFieldType*>(
248         (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
249   }
MutableRepeatedField(Field * data)250   static RepeatedFieldType* MutableRepeatedField(Field* data) {
251     return reinterpret_cast<RepeatedFieldType*>(
252         reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
253   }
New(const Value * value)254   virtual Message* New(const Value* value) const {
255     return static_cast<const Message*>(value)->New();
256   }
257   // Convert an object received by this accessor to an MapEntry message to be
258   // stored in the underlying MapFieldBase.
ConvertToEntry(const Value * value,Message * result)259   virtual void ConvertToEntry(const Value* value, Message* result) const {
260     result->CopyFrom(*static_cast<const Message*>(value));
261   }
262   // Convert a MapEntry message stored in the underlying MapFieldBase to an
263   // object that will be returned by this accessor.
ConvertFromEntry(const Message & value,Value * scratch_space)264   virtual const Value* ConvertFromEntry(const Message& value,
265                                         Value* scratch_space) const {
266     return static_cast<const Value*>(&value);
267   }
268 };
269 
270 // Default implementations of RepeatedFieldAccessor for primitive types.
271 template<typename T>
272 class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
273   typedef void Field;
274   typedef void Value;
275   using RepeatedFieldWrapper<T>::MutableRepeatedField;
276 
277  public:
RepeatedFieldPrimitiveAccessor()278   RepeatedFieldPrimitiveAccessor() {}
~RepeatedFieldPrimitiveAccessor()279   virtual ~RepeatedFieldPrimitiveAccessor() {}
Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)280   virtual void Swap(
281       Field* data,
282       const internal::RepeatedFieldAccessor* other_mutator,
283       Field* other_data) const {
284     // Currently RepeatedFieldPrimitiveAccessor is the only implementation of
285     // RepeatedFieldAccessor for primitive types. As we are using singletons
286     // for these accessors, here "other_mutator" must be "this".
287     GOOGLE_CHECK(this == other_mutator);
288     MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
289   }
290 
291  protected:
ConvertToT(const Value * value)292   virtual T ConvertToT(const Value* value) const {
293     return *static_cast<const T*>(value);
294   }
ConvertFromT(const T & value,Value * scratch_space)295   virtual const Value* ConvertFromT(const T& value,
296                                     Value* scratch_space) const {
297     return static_cast<const Value*>(&value);
298   }
299 };
300 
301 // Default implementation of RepeatedFieldAccessor for string fields with
302 // ctype=STRING.
303 class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> {
304   typedef void Field;
305   typedef void Value;
306   using RepeatedFieldAccessor::Add;
307 
308  public:
RepeatedPtrFieldStringAccessor()309   RepeatedPtrFieldStringAccessor() {}
~RepeatedPtrFieldStringAccessor()310   virtual ~RepeatedPtrFieldStringAccessor() {}
Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)311   virtual void Swap(
312       Field* data,
313       const internal::RepeatedFieldAccessor* other_mutator,
314       Field* other_data) const {
315     if (this == other_mutator) {
316       MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
317     } else {
318       RepeatedPtrField<string> tmp;
319       tmp.Swap(MutableRepeatedField(data));
320       int other_size = other_mutator->Size(other_data);
321       for (int i = 0; i < other_size; ++i) {
322         Add<string>(data, other_mutator->Get<string>(other_data, i));
323       }
324       int size = Size(data);
325       other_mutator->Clear(other_data);
326       for (int i = 0; i < size; ++i) {
327         other_mutator->Add<string>(other_data, tmp.Get(i));
328       }
329     }
330   }
331 
332  protected:
New(const Value *)333   virtual string* New(const Value*) const {
334     return new string();
335   }
ConvertToT(const Value * value,string * result)336   virtual void ConvertToT(const Value* value, string* result) const {
337     *result = *static_cast<const string*>(value);
338   }
ConvertFromT(const string & value,Value * scratch_space)339   virtual const Value* ConvertFromT(const string& value,
340                                     Value* scratch_space) const {
341     return static_cast<const Value*>(&value);
342   }
343 };
344 
345 
346 class RepeatedPtrFieldMessageAccessor
347     : public RepeatedPtrFieldWrapper<Message> {
348   typedef void Field;
349   typedef void Value;
350 
351  public:
RepeatedPtrFieldMessageAccessor()352   RepeatedPtrFieldMessageAccessor() {}
~RepeatedPtrFieldMessageAccessor()353   virtual ~RepeatedPtrFieldMessageAccessor() {}
Swap(Field * data,const internal::RepeatedFieldAccessor * other_mutator,Field * other_data)354   virtual void Swap(
355       Field* data,
356       const internal::RepeatedFieldAccessor* other_mutator,
357       Field* other_data) const {
358     GOOGLE_CHECK(this == other_mutator);
359     MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
360   }
361 
362  protected:
New(const Value * value)363   virtual Message* New(const Value* value) const {
364     return static_cast<const Message*>(value)->New();
365   }
ConvertToT(const Value * value,Message * result)366   virtual void ConvertToT(const Value* value, Message* result) const {
367     result->CopyFrom(*static_cast<const Message*>(value));
368   }
ConvertFromT(const Message & value,Value * scratch_space)369   virtual const Value* ConvertFromT(const Message& value,
370                                     Value* scratch_space) const {
371     return static_cast<const Value*>(&value);
372   }
373 };
374 }  // namespace internal
375 }  // namespace protobuf
376 
377 }  // namespace google
378 #endif  // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
379