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: |
46 | Iterator* BeginIterator(const Field* /*data*/) const override { |
47 | return PositionToIterator(position: 0); |
48 | } |
49 | Iterator* EndIterator(const Field* data) const override { |
50 | return PositionToIterator(position: this->Size(data)); |
51 | } |
52 | Iterator* CopyIterator(const Field* /*data*/, |
53 | const Iterator* iterator) const override { |
54 | return const_cast<Iterator*>(iterator); |
55 | } |
56 | Iterator* AdvanceIterator(const Field* /*data*/, |
57 | Iterator* iterator) const override { |
58 | return PositionToIterator(position: IteratorToPosition(iterator) + 1); |
59 | } |
60 | bool EqualsIterator(const Field* /*data*/, const Iterator* a, |
61 | const Iterator* b) const override { |
62 | return a == b; |
63 | } |
64 | void DeleteIterator(const Field* /*data*/, |
65 | Iterator* /*iterator*/) const override {} |
66 | const Value* GetIteratorValue(const Field* data, const Iterator* iterator, |
67 | Value* scratch_space) const override { |
68 | return Get(data, index: static_cast<int>(IteratorToPosition(iterator)), |
69 | scratch_space); |
70 | } |
71 | |
72 | protected: |
73 | ~RandomAccessRepeatedFieldAccessor() = default; |
74 | |
75 | private: |
76 | static intptr_t IteratorToPosition(const Iterator* iterator) { |
77 | return reinterpret_cast<intptr_t>(iterator); |
78 | } |
79 | static Iterator* PositionToIterator(intptr_t position) { |
80 | return reinterpret_cast<Iterator*>(position); |
81 | } |
82 | }; |
83 | |
84 | // Base class for RepeatedFieldAccessor implementations that manipulates |
85 | // RepeatedField<T>. |
86 | template <typename T> |
87 | class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { |
88 | public: |
89 | RepeatedFieldWrapper() {} |
90 | bool IsEmpty(const Field* data) const override { |
91 | return GetRepeatedField(data)->empty(); |
92 | } |
93 | int Size(const Field* data) const override { |
94 | return GetRepeatedField(data)->size(); |
95 | } |
96 | const Value* Get(const Field* data, int index, |
97 | Value* scratch_space) const override { |
98 | return ConvertFromT(value: GetRepeatedField(data)->Get(index), scratch_space); |
99 | } |
100 | void Clear(Field* data) const override { |
101 | MutableRepeatedField(data)->Clear(); |
102 | } |
103 | void Set(Field* data, int index, const Value* value) const override { |
104 | MutableRepeatedField(data)->Set(index, ConvertToT(value)); |
105 | } |
106 | void Add(Field* data, const Value* value) const override { |
107 | MutableRepeatedField(data)->Add(ConvertToT(value)); |
108 | } |
109 | void RemoveLast(Field* data) const override { |
110 | MutableRepeatedField(data)->RemoveLast(); |
111 | } |
112 | void SwapElements(Field* data, int index1, int index2) const override { |
113 | MutableRepeatedField(data)->SwapElements(index1, index2); |
114 | } |
115 | |
116 | protected: |
117 | ~RepeatedFieldWrapper() = default; |
118 | typedef RepeatedField<T> RepeatedFieldType; |
119 | static const RepeatedFieldType* GetRepeatedField(const Field* data) { |
120 | return reinterpret_cast<const RepeatedFieldType*>(data); |
121 | } |
122 | static RepeatedFieldType* MutableRepeatedField(Field* data) { |
123 | return reinterpret_cast<RepeatedFieldType*>(data); |
124 | } |
125 | |
126 | // Convert an object received by this accessor to an object to be stored in |
127 | // the underlying RepeatedField. |
128 | virtual T ConvertToT(const Value* value) const = 0; |
129 | |
130 | // Convert an object stored in RepeatedPtrField to an object that will be |
131 | // returned by this accessor. If the two objects have the same type (true for |
132 | // string fields with ctype=STRING), a pointer to the source object can be |
133 | // returned directly. Otherwise, data should be copied from value to |
134 | // scratch_space and scratch_space should be returned. |
135 | virtual const Value* ConvertFromT(const T& value, |
136 | Value* scratch_space) const = 0; |
137 | }; |
138 | |
139 | // Base class for RepeatedFieldAccessor implementations that manipulates |
140 | // RepeatedPtrField<T>. |
141 | template <typename T> |
142 | class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { |
143 | public: |
144 | bool IsEmpty(const Field* data) const override { |
145 | return GetRepeatedField(data)->empty(); |
146 | } |
147 | int Size(const Field* data) const override { |
148 | return GetRepeatedField(data)->size(); |
149 | } |
150 | const Value* Get(const Field* data, int index, |
151 | Value* scratch_space) const override { |
152 | return ConvertFromT(value: GetRepeatedField(data)->Get(index), scratch_space); |
153 | } |
154 | void Clear(Field* data) const override { |
155 | MutableRepeatedField(data)->Clear(); |
156 | } |
157 | void Set(Field* data, int index, const Value* value) const override { |
158 | ConvertToT(value, result: MutableRepeatedField(data)->Mutable(index)); |
159 | } |
160 | void Add(Field* data, const Value* value) const override { |
161 | T* allocated = New(value); |
162 | ConvertToT(value, result: allocated); |
163 | MutableRepeatedField(data)->AddAllocated(allocated); |
164 | } |
165 | void RemoveLast(Field* data) const override { |
166 | MutableRepeatedField(data)->RemoveLast(); |
167 | } |
168 | void SwapElements(Field* data, int index1, int index2) const override { |
169 | MutableRepeatedField(data)->SwapElements(index1, index2); |
170 | } |
171 | |
172 | protected: |
173 | ~RepeatedPtrFieldWrapper() = default; |
174 | typedef RepeatedPtrField<T> RepeatedFieldType; |
175 | static const RepeatedFieldType* GetRepeatedField(const Field* data) { |
176 | return reinterpret_cast<const RepeatedFieldType*>(data); |
177 | } |
178 | static RepeatedFieldType* MutableRepeatedField(Field* data) { |
179 | return reinterpret_cast<RepeatedFieldType*>(data); |
180 | } |
181 | |
182 | // Create a new T instance. For repeated message fields, T can be specified |
183 | // as google::protobuf::Message so we can't use "new T()" directly. In that case, value |
184 | // should be a message of the same type (it's ensured by the caller) and a |
185 | // new message object will be created using it. |
186 | virtual T* New(const Value* value) const = 0; |
187 | |
188 | // Convert an object received by this accessor to an object that will be |
189 | // stored in the underlying RepeatedPtrField. |
190 | virtual void ConvertToT(const Value* value, T* result) const = 0; |
191 | |
192 | // Convert an object stored in RepeatedPtrField to an object that will be |
193 | // returned by this accessor. If the two objects have the same type (true for |
194 | // string fields with ctype=STRING), a pointer to the source object can be |
195 | // returned directly. Otherwise, data should be copied from value to |
196 | // scratch_space and scratch_space should be returned. |
197 | virtual const Value* ConvertFromT(const T& value, |
198 | Value* scratch_space) const = 0; |
199 | }; |
200 | |
201 | // An implementation of RandomAccessRepeatedFieldAccessor that manipulates |
202 | // MapFieldBase. |
203 | class MapFieldAccessor final : public RandomAccessRepeatedFieldAccessor { |
204 | public: |
205 | MapFieldAccessor() {} |
206 | virtual ~MapFieldAccessor() {} |
207 | bool IsEmpty(const Field* data) const override { |
208 | return GetRepeatedField(data)->empty(); |
209 | } |
210 | int Size(const Field* data) const override { |
211 | return GetRepeatedField(data)->size(); |
212 | } |
213 | const Value* Get(const Field* data, int index, |
214 | Value* scratch_space) const override { |
215 | return ConvertFromEntry(value: GetRepeatedField(data)->Get(index), scratch_space); |
216 | } |
217 | void Clear(Field* data) const override { |
218 | MutableRepeatedField(data)->Clear(); |
219 | } |
220 | void Set(Field* data, int index, const Value* value) const override { |
221 | ConvertToEntry(value, result: MutableRepeatedField(data)->Mutable(index)); |
222 | } |
223 | void Add(Field* data, const Value* value) const override { |
224 | Message* allocated = New(value); |
225 | ConvertToEntry(value, result: allocated); |
226 | MutableRepeatedField(data)->AddAllocated(value: allocated); |
227 | } |
228 | void RemoveLast(Field* data) const override { |
229 | MutableRepeatedField(data)->RemoveLast(); |
230 | } |
231 | void SwapElements(Field* data, int index1, int index2) const override { |
232 | MutableRepeatedField(data)->SwapElements(index1, index2); |
233 | } |
234 | void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, |
235 | Field* other_data) const override { |
236 | GOOGLE_CHECK(this == other_mutator); |
237 | MutableRepeatedField(data)->Swap(other: MutableRepeatedField(data: other_data)); |
238 | } |
239 | |
240 | protected: |
241 | typedef RepeatedPtrField<Message> RepeatedFieldType; |
242 | static const RepeatedFieldType* GetRepeatedField(const Field* data) { |
243 | return reinterpret_cast<const RepeatedFieldType*>( |
244 | (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField())); |
245 | } |
246 | static RepeatedFieldType* MutableRepeatedField(Field* data) { |
247 | return reinterpret_cast<RepeatedFieldType*>( |
248 | reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField()); |
249 | } |
250 | virtual Message* New(const Value* value) const { |
251 | return static_cast<const Message*>(value)->New(); |
252 | } |
253 | // Convert an object received by this accessor to an MapEntry message to be |
254 | // stored in the underlying MapFieldBase. |
255 | virtual void ConvertToEntry(const Value* value, Message* result) const { |
256 | result->CopyFrom(from: *static_cast<const Message*>(value)); |
257 | } |
258 | // Convert a MapEntry message stored in the underlying MapFieldBase to an |
259 | // object that will be returned by this accessor. |
260 | virtual const Value* ConvertFromEntry(const Message& value, |
261 | Value* /*scratch_space*/) const { |
262 | return static_cast<const Value*>(&value); |
263 | } |
264 | }; |
265 | |
266 | // Default implementations of RepeatedFieldAccessor for primitive types. |
267 | template <typename T> |
268 | class RepeatedFieldPrimitiveAccessor final : public RepeatedFieldWrapper<T> { |
269 | typedef void Field; |
270 | typedef void Value; |
271 | using RepeatedFieldWrapper<T>::MutableRepeatedField; |
272 | |
273 | public: |
274 | RepeatedFieldPrimitiveAccessor() {} |
275 | void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, |
276 | Field* other_data) const override { |
277 | // Currently RepeatedFieldPrimitiveAccessor is the only implementation of |
278 | // RepeatedFieldAccessor for primitive types. As we are using singletons |
279 | // for these accessors, here "other_mutator" must be "this". |
280 | GOOGLE_CHECK(this == other_mutator); |
281 | MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); |
282 | } |
283 | |
284 | protected: |
285 | T ConvertToT(const Value* value) const override { |
286 | return *static_cast<const T*>(value); |
287 | } |
288 | const Value* ConvertFromT(const T& value, |
289 | Value* /*scratch_space*/) const override { |
290 | return static_cast<const Value*>(&value); |
291 | } |
292 | }; |
293 | |
294 | // Default implementation of RepeatedFieldAccessor for string fields with |
295 | // ctype=STRING. |
296 | class RepeatedPtrFieldStringAccessor final |
297 | : public RepeatedPtrFieldWrapper<std::string> { |
298 | typedef void Field; |
299 | typedef void Value; |
300 | using RepeatedFieldAccessor::Add; |
301 | |
302 | public: |
303 | RepeatedPtrFieldStringAccessor() {} |
304 | void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, |
305 | Field* other_data) const override { |
306 | if (this == other_mutator) { |
307 | MutableRepeatedField(data)->Swap(other: MutableRepeatedField(data: other_data)); |
308 | } else { |
309 | RepeatedPtrField<std::string> tmp; |
310 | tmp.Swap(other: MutableRepeatedField(data)); |
311 | int other_size = other_mutator->Size(data: other_data); |
312 | for (int i = 0; i < other_size; ++i) { |
313 | Add<std::string>(data, value: other_mutator->Get<std::string>(data: other_data, index: i)); |
314 | } |
315 | int size = Size(data); |
316 | other_mutator->Clear(data: other_data); |
317 | for (int i = 0; i < size; ++i) { |
318 | other_mutator->Add<std::string>(data: other_data, value: tmp.Get(index: i)); |
319 | } |
320 | } |
321 | } |
322 | |
323 | protected: |
324 | std::string* New(const Value*) const override { return new std::string(); } |
325 | void ConvertToT(const Value* value, std::string* result) const override { |
326 | *result = *static_cast<const std::string*>(value); |
327 | } |
328 | const Value* ConvertFromT(const std::string& value, |
329 | Value* /*scratch_space*/) const override { |
330 | return static_cast<const Value*>(&value); |
331 | } |
332 | }; |
333 | |
334 | |
335 | class RepeatedPtrFieldMessageAccessor final |
336 | : public RepeatedPtrFieldWrapper<Message> { |
337 | typedef void Field; |
338 | typedef void Value; |
339 | |
340 | public: |
341 | RepeatedPtrFieldMessageAccessor() {} |
342 | void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, |
343 | Field* other_data) const override { |
344 | GOOGLE_CHECK(this == other_mutator); |
345 | MutableRepeatedField(data)->Swap(other: MutableRepeatedField(data: other_data)); |
346 | } |
347 | |
348 | protected: |
349 | Message* New(const Value* value) const override { |
350 | return static_cast<const Message*>(value)->New(); |
351 | } |
352 | void ConvertToT(const Value* value, Message* result) const override { |
353 | result->CopyFrom(from: *static_cast<const Message*>(value)); |
354 | } |
355 | const Value* ConvertFromT(const Message& value, |
356 | Value* /*scratch_space*/) const override { |
357 | return static_cast<const Value*>(&value); |
358 | } |
359 | }; |
360 | } // namespace internal |
361 | } // namespace protobuf |
362 | } // namespace google |
363 | |
364 | #endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ |
365 | |