blob: fcb424715c39e123f2ce3200cbe592797134875d [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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
38namespace google {
39namespace protobuf {
40namespace 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.
44class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor {
45 public:
46 virtual ~RandomAccessRepeatedFieldAccessor() {}
47
48 virtual Iterator* BeginIterator(const Field* data) const {
49 return PositionToIterator(0);
50 }
51 virtual Iterator* EndIterator(const Field* data) const {
52 return PositionToIterator(this->Size(data));
53 }
54 virtual Iterator* CopyIterator(const Field* data,
55 const Iterator* iterator) const {
56 return const_cast<Iterator*>(iterator);
57 }
58 virtual Iterator* AdvanceIterator(const Field* data,
59 Iterator* iterator) const {
60 return PositionToIterator(IteratorToPosition(iterator) + 1);
61 }
62 virtual bool EqualsIterator(const Field* data,
63 const Iterator* a,
64 const Iterator* b) const {
65 return a == b;
66 }
67 virtual void DeleteIterator(const Field* data, Iterator* iterator) const {
68 }
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:
77 static intptr_t IteratorToPosition(const Iterator* iterator) {
78 return reinterpret_cast<intptr_t>(iterator);
79 }
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>.
87template<typename T>
88class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor {
89 public:
90 RepeatedFieldWrapper() {}
91 virtual ~RepeatedFieldWrapper() {}
92 virtual bool IsEmpty(const Field* data) const {
93 return GetRepeatedField(data)->empty();
94 }
95 virtual int Size(const Field* data) const {
96 return GetRepeatedField(data)->size();
97 }
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 }
102 virtual void Clear(Field* data) const {
103 MutableRepeatedField(data)->Clear();
104 }
105 virtual void Set(Field* data, int index, const Value* value) const {
106 MutableRepeatedField(data)->Set(index, ConvertToT(value));
107 }
108 virtual void Add(Field* data, const Value* value) const {
109 MutableRepeatedField(data)->Add(ConvertToT(value));
110 }
111 virtual void RemoveLast(Field* data) const {
112 MutableRepeatedField(data)->RemoveLast();
113 }
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;
120 static const RepeatedFieldType* GetRepeatedField(const Field* data) {
121 return reinterpret_cast<const RepeatedFieldType*>(data);
122 }
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>.
142template<typename T>
143class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
144 public:
145 RepeatedPtrFieldWrapper() {}
146 virtual ~RepeatedPtrFieldWrapper() {}
147 virtual bool IsEmpty(const Field* data) const {
148 return GetRepeatedField(data)->empty();
149 }
150 virtual int Size(const Field* data) const {
151 return GetRepeatedField(data)->size();
152 }
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 }
157 virtual void Clear(Field* data) const {
158 MutableRepeatedField(data)->Clear();
159 }
160 virtual void Set(Field* data, int index, const Value* value) const {
161 ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
162 }
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 }
168 virtual void RemoveLast(Field* data) const {
169 MutableRepeatedField(data)->RemoveLast();
170 }
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;
177 static const RepeatedFieldType* GetRepeatedField(const Field* data) {
178 return reinterpret_cast<const RepeatedFieldType*>(data);
179 }
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.
205class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor {
206 public:
207 MapFieldAccessor() {}
208 virtual ~MapFieldAccessor() {}
209 virtual bool IsEmpty(const Field* data) const {
210 return GetRepeatedField(data)->empty();
211 }
212 virtual int Size(const Field* data) const {
213 return GetRepeatedField(data)->size();
214 }
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 }
219 virtual void Clear(Field* data) const {
220 MutableRepeatedField(data)->Clear();
221 }
222 virtual void Set(Field* data, int index, const Value* value) const {
223 ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
224 }
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 }
230 virtual void RemoveLast(Field* data) const {
231 MutableRepeatedField(data)->RemoveLast();
232 }
233 virtual void SwapElements(Field* data, int index1, int index2) const {
234 MutableRepeatedField(data)->SwapElements(index1, index2);
235 }
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;
246 static const RepeatedFieldType* GetRepeatedField(const Field* data) {
247 return reinterpret_cast<const RepeatedFieldType*>(
248 (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
249 }
250 static RepeatedFieldType* MutableRepeatedField(Field* data) {
251 return reinterpret_cast<RepeatedFieldType*>(
252 reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
253 }
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.
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.
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.
271template<typename T>
272class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
273 typedef void Field;
274 typedef void Value;
275 using RepeatedFieldWrapper<T>::MutableRepeatedField;
276
277 public:
278 RepeatedFieldPrimitiveAccessor() {}
279 virtual ~RepeatedFieldPrimitiveAccessor() {}
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:
292 virtual T ConvertToT(const Value* value) const {
293 return *static_cast<const T*>(value);
294 }
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.
303class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> {
304 typedef void Field;
305 typedef void Value;
306 using RepeatedFieldAccessor::Add;
307
308 public:
309 RepeatedPtrFieldStringAccessor() {}
310 virtual ~RepeatedPtrFieldStringAccessor() {}
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:
333 virtual string* New(const Value*) const {
334 return new string();
335 }
336 virtual void ConvertToT(const Value* value, string* result) const {
337 *result = *static_cast<const string*>(value);
338 }
339 virtual const Value* ConvertFromT(const string& value,
340 Value* scratch_space) const {
341 return static_cast<const Value*>(&value);
342 }
343};
344
345
346class RepeatedPtrFieldMessageAccessor
347 : public RepeatedPtrFieldWrapper<Message> {
348 typedef void Field;
349 typedef void Value;
350
351 public:
352 RepeatedPtrFieldMessageAccessor() {}
353 virtual ~RepeatedPtrFieldMessageAccessor() {}
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:
363 virtual Message* New(const Value* value) const {
364 return static_cast<const Message*>(value)->New();
365 }
366 virtual void ConvertToT(const Value* value, Message* result) const {
367 result->CopyFrom(*static_cast<const Message*>(value));
368 }
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__