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 | // Author: kenton@google.com (Kenton Varda) |
32 | // Based on original Protocol Buffers design by |
33 | // Sanjay Ghemawat, Jeff Dean, and others. |
34 | #include <google/protobuf/reflection_ops.h> |
35 | |
36 | #include <string> |
37 | #include <vector> |
38 | |
39 | #include <google/protobuf/stubs/logging.h> |
40 | #include <google/protobuf/stubs/common.h> |
41 | #include <google/protobuf/descriptor.h> |
42 | #include <google/protobuf/descriptor.pb.h> |
43 | #include <google/protobuf/map_field.h> |
44 | #include <google/protobuf/map_field_inl.h> |
45 | #include <google/protobuf/unknown_field_set.h> |
46 | |
47 | // Must be included last. |
48 | #include <google/protobuf/port_def.inc> |
49 | |
50 | namespace google { |
51 | namespace protobuf { |
52 | namespace internal { |
53 | |
54 | static const Reflection* GetReflectionOrDie(const Message& m) { |
55 | const Reflection* r = m.GetReflection(); |
56 | if (r == nullptr) { |
57 | const Descriptor* d = m.GetDescriptor(); |
58 | const std::string& mtype = d ? d->name() : "unknown" ; |
59 | // RawMessage is one known type for which GetReflection() returns nullptr. |
60 | GOOGLE_LOG(FATAL) << "Message does not support reflection (type " << mtype << ")." ; |
61 | } |
62 | return r; |
63 | } |
64 | |
65 | void ReflectionOps::Copy(const Message& from, Message* to) { |
66 | if (&from == to) return; |
67 | Clear(message: to); |
68 | Merge(from, to); |
69 | } |
70 | |
71 | void ReflectionOps::Merge(const Message& from, Message* to) { |
72 | GOOGLE_CHECK_NE(&from, to); |
73 | |
74 | const Descriptor* descriptor = from.GetDescriptor(); |
75 | GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) |
76 | << "Tried to merge messages of different types " |
77 | << "(merge " << descriptor->full_name() << " to " |
78 | << to->GetDescriptor()->full_name() << ")" ; |
79 | |
80 | const Reflection* from_reflection = GetReflectionOrDie(m: from); |
81 | const Reflection* to_reflection = GetReflectionOrDie(m: *to); |
82 | bool is_from_generated = (from_reflection->GetMessageFactory() == |
83 | google::protobuf::MessageFactory::generated_factory()); |
84 | bool is_to_generated = (to_reflection->GetMessageFactory() == |
85 | google::protobuf::MessageFactory::generated_factory()); |
86 | |
87 | std::vector<const FieldDescriptor*> fields; |
88 | from_reflection->ListFieldsOmitStripped(message: from, output: &fields); |
89 | for (const FieldDescriptor* field : fields) { |
90 | if (field->is_repeated()) { |
91 | // Use map reflection if both are in map status and have the |
92 | // same map type to avoid sync with repeated field. |
93 | // Note: As from and to messages have the same descriptor, the |
94 | // map field types are the same if they are both generated |
95 | // messages or both dynamic messages. |
96 | if (is_from_generated == is_to_generated && field->is_map()) { |
97 | const MapFieldBase* from_field = |
98 | from_reflection->GetMapData(message: from, field); |
99 | MapFieldBase* to_field = to_reflection->MutableMapData(message: to, field); |
100 | if (to_field->IsMapValid() && from_field->IsMapValid()) { |
101 | to_field->MergeFrom(other: *from_field); |
102 | continue; |
103 | } |
104 | } |
105 | int count = from_reflection->FieldSize(message: from, field); |
106 | for (int j = 0; j < count; j++) { |
107 | switch (field->cpp_type()) { |
108 | #define HANDLE_TYPE(CPPTYPE, METHOD) \ |
109 | case FieldDescriptor::CPPTYPE_##CPPTYPE: \ |
110 | to_reflection->Add##METHOD( \ |
111 | to, field, from_reflection->GetRepeated##METHOD(from, field, j)); \ |
112 | break; |
113 | |
114 | HANDLE_TYPE(INT32, Int32); |
115 | HANDLE_TYPE(INT64, Int64); |
116 | HANDLE_TYPE(UINT32, UInt32); |
117 | HANDLE_TYPE(UINT64, UInt64); |
118 | HANDLE_TYPE(FLOAT, Float); |
119 | HANDLE_TYPE(DOUBLE, Double); |
120 | HANDLE_TYPE(BOOL, Bool); |
121 | HANDLE_TYPE(STRING, String); |
122 | HANDLE_TYPE(ENUM, Enum); |
123 | #undef HANDLE_TYPE |
124 | |
125 | case FieldDescriptor::CPPTYPE_MESSAGE: |
126 | const Message& from_child = |
127 | from_reflection->GetRepeatedMessage(message: from, field, index: j); |
128 | if (from_reflection == to_reflection) { |
129 | to_reflection |
130 | ->AddMessage(message: to, field, |
131 | factory: from_child.GetReflection()->GetMessageFactory()) |
132 | ->MergeFrom(from: from_child); |
133 | } else { |
134 | to_reflection->AddMessage(message: to, field)->MergeFrom(from: from_child); |
135 | } |
136 | break; |
137 | } |
138 | } |
139 | } else { |
140 | switch (field->cpp_type()) { |
141 | #define HANDLE_TYPE(CPPTYPE, METHOD) \ |
142 | case FieldDescriptor::CPPTYPE_##CPPTYPE: \ |
143 | to_reflection->Set##METHOD(to, field, \ |
144 | from_reflection->Get##METHOD(from, field)); \ |
145 | break; |
146 | |
147 | HANDLE_TYPE(INT32, Int32); |
148 | HANDLE_TYPE(INT64, Int64); |
149 | HANDLE_TYPE(UINT32, UInt32); |
150 | HANDLE_TYPE(UINT64, UInt64); |
151 | HANDLE_TYPE(FLOAT, Float); |
152 | HANDLE_TYPE(DOUBLE, Double); |
153 | HANDLE_TYPE(BOOL, Bool); |
154 | HANDLE_TYPE(STRING, String); |
155 | HANDLE_TYPE(ENUM, Enum); |
156 | #undef HANDLE_TYPE |
157 | |
158 | case FieldDescriptor::CPPTYPE_MESSAGE: |
159 | const Message& from_child = from_reflection->GetMessage(message: from, field); |
160 | if (from_reflection == to_reflection) { |
161 | to_reflection |
162 | ->MutableMessage( |
163 | message: to, field, factory: from_child.GetReflection()->GetMessageFactory()) |
164 | ->MergeFrom(from: from_child); |
165 | } else { |
166 | to_reflection->MutableMessage(message: to, field)->MergeFrom(from: from_child); |
167 | } |
168 | break; |
169 | } |
170 | } |
171 | } |
172 | |
173 | if (!from_reflection->GetUnknownFields(message: from).empty()) { |
174 | to_reflection->MutableUnknownFields(message: to)->MergeFrom( |
175 | other: from_reflection->GetUnknownFields(message: from)); |
176 | } |
177 | } |
178 | |
179 | void ReflectionOps::Clear(Message* message) { |
180 | const Reflection* reflection = GetReflectionOrDie(m: *message); |
181 | |
182 | std::vector<const FieldDescriptor*> fields; |
183 | reflection->ListFieldsOmitStripped(message: *message, output: &fields); |
184 | for (const FieldDescriptor* field : fields) { |
185 | reflection->ClearField(message, field); |
186 | } |
187 | |
188 | if (reflection->GetInternalMetadata(message: *message).have_unknown_fields()) { |
189 | reflection->MutableUnknownFields(message)->Clear(); |
190 | } |
191 | } |
192 | |
193 | bool ReflectionOps::IsInitialized(const Message& message, bool check_fields, |
194 | bool check_descendants) { |
195 | const Descriptor* descriptor = message.GetDescriptor(); |
196 | const Reflection* reflection = GetReflectionOrDie(m: message); |
197 | if (const int field_count = descriptor->field_count()) { |
198 | const FieldDescriptor* begin = descriptor->field(index: 0); |
199 | const FieldDescriptor* end = begin + field_count; |
200 | GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1); |
201 | |
202 | if (check_fields) { |
203 | // Check required fields of this message. |
204 | for (const FieldDescriptor* field = begin; field != end; ++field) { |
205 | if (field->is_required() && !reflection->HasField(message, field)) { |
206 | return false; |
207 | } |
208 | } |
209 | } |
210 | |
211 | if (check_descendants) { |
212 | for (const FieldDescriptor* field = begin; field != end; ++field) { |
213 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
214 | const Descriptor* message_type = field->message_type(); |
215 | if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) { |
216 | if (message_type->field(index: 1)->cpp_type() == |
217 | FieldDescriptor::CPPTYPE_MESSAGE) { |
218 | const MapFieldBase* map_field = |
219 | reflection->GetMapData(message, field); |
220 | if (map_field->IsMapValid()) { |
221 | MapIterator it(const_cast<Message*>(&message), field); |
222 | MapIterator end_map(const_cast<Message*>(&message), field); |
223 | for (map_field->MapBegin(map_iter: &it), map_field->MapEnd(map_iter: &end_map); |
224 | it != end_map; ++it) { |
225 | if (!it.GetValueRef().GetMessageValue().IsInitialized()) { |
226 | return false; |
227 | } |
228 | } |
229 | } |
230 | } |
231 | } else if (field->is_repeated()) { |
232 | const int size = reflection->FieldSize(message, field); |
233 | for (int j = 0; j < size; j++) { |
234 | if (!reflection->GetRepeatedMessage(message, field, index: j) |
235 | .IsInitialized()) { |
236 | return false; |
237 | } |
238 | } |
239 | } else if (reflection->HasField(message, field)) { |
240 | if (!reflection->GetMessage(message, field).IsInitialized()) { |
241 | return false; |
242 | } |
243 | } |
244 | } |
245 | } |
246 | } |
247 | } |
248 | if (check_descendants && reflection->HasExtensionSet(message) && |
249 | !reflection->GetExtensionSet(message).IsInitialized()) { |
250 | return false; |
251 | } |
252 | return true; |
253 | } |
254 | |
255 | bool ReflectionOps::IsInitialized(const Message& message) { |
256 | const Descriptor* descriptor = message.GetDescriptor(); |
257 | const Reflection* reflection = GetReflectionOrDie(m: message); |
258 | |
259 | // Check required fields of this message. |
260 | { |
261 | const int field_count = descriptor->field_count(); |
262 | for (int i = 0; i < field_count; i++) { |
263 | if (descriptor->field(index: i)->is_required()) { |
264 | if (!reflection->HasField(message, field: descriptor->field(index: i))) { |
265 | return false; |
266 | } |
267 | } |
268 | } |
269 | } |
270 | |
271 | // Check that sub-messages are initialized. |
272 | std::vector<const FieldDescriptor*> fields; |
273 | // Should be safe to skip stripped fields because required fields are not |
274 | // stripped. |
275 | reflection->ListFieldsOmitStripped(message, output: &fields); |
276 | for (const FieldDescriptor* field : fields) { |
277 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
278 | |
279 | if (field->is_map()) { |
280 | const FieldDescriptor* value_field = field->message_type()->field(index: 1); |
281 | if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
282 | const MapFieldBase* map_field = |
283 | reflection->GetMapData(message, field); |
284 | if (map_field->IsMapValid()) { |
285 | MapIterator iter(const_cast<Message*>(&message), field); |
286 | MapIterator end(const_cast<Message*>(&message), field); |
287 | for (map_field->MapBegin(map_iter: &iter), map_field->MapEnd(map_iter: &end); |
288 | iter != end; ++iter) { |
289 | if (!iter.GetValueRef().GetMessageValue().IsInitialized()) { |
290 | return false; |
291 | } |
292 | } |
293 | continue; |
294 | } |
295 | } else { |
296 | continue; |
297 | } |
298 | } |
299 | |
300 | if (field->is_repeated()) { |
301 | int size = reflection->FieldSize(message, field); |
302 | |
303 | for (int j = 0; j < size; j++) { |
304 | if (!reflection->GetRepeatedMessage(message, field, index: j) |
305 | .IsInitialized()) { |
306 | return false; |
307 | } |
308 | } |
309 | } else { |
310 | if (!reflection->GetMessage(message, field).IsInitialized()) { |
311 | return false; |
312 | } |
313 | } |
314 | } |
315 | } |
316 | |
317 | return true; |
318 | } |
319 | |
320 | static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) { |
321 | return map_field->message_type()->field(index: 1)->cpp_type() == |
322 | FieldDescriptor::CPPTYPE_MESSAGE; |
323 | } |
324 | |
325 | void ReflectionOps::DiscardUnknownFields(Message* message) { |
326 | const Reflection* reflection = GetReflectionOrDie(m: *message); |
327 | |
328 | reflection->MutableUnknownFields(message)->Clear(); |
329 | |
330 | // Walk through the fields of this message and DiscardUnknownFields on any |
331 | // messages present. |
332 | std::vector<const FieldDescriptor*> fields; |
333 | reflection->ListFields(message: *message, output: &fields); |
334 | for (const FieldDescriptor* field : fields) { |
335 | // Skip over non-message fields. |
336 | if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
337 | continue; |
338 | } |
339 | // Discard the unknown fields in maps that contain message values. |
340 | if (field->is_map() && IsMapValueMessageTyped(map_field: field)) { |
341 | const MapFieldBase* map_field = |
342 | reflection->MutableMapData(message, field); |
343 | if (map_field->IsMapValid()) { |
344 | MapIterator iter(message, field); |
345 | MapIterator end(message, field); |
346 | for (map_field->MapBegin(map_iter: &iter), map_field->MapEnd(map_iter: &end); iter != end; |
347 | ++iter) { |
348 | iter.MutableValueRef()->MutableMessageValue()->DiscardUnknownFields(); |
349 | } |
350 | } |
351 | // Discard every unknown field inside messages in a repeated field. |
352 | } else if (field->is_repeated()) { |
353 | int size = reflection->FieldSize(message: *message, field); |
354 | for (int j = 0; j < size; j++) { |
355 | reflection->MutableRepeatedMessage(message, field, index: j) |
356 | ->DiscardUnknownFields(); |
357 | } |
358 | // Discard the unknown fields inside an optional message. |
359 | } else { |
360 | reflection->MutableMessage(message, field)->DiscardUnknownFields(); |
361 | } |
362 | } |
363 | } |
364 | |
365 | static std::string SubMessagePrefix(const std::string& prefix, |
366 | const FieldDescriptor* field, int index) { |
367 | std::string result(prefix); |
368 | if (field->is_extension()) { |
369 | result.append(s: "(" ); |
370 | result.append(str: field->full_name()); |
371 | result.append(s: ")" ); |
372 | } else { |
373 | result.append(str: field->name()); |
374 | } |
375 | if (index != -1) { |
376 | result.append(s: "[" ); |
377 | result.append(str: StrCat(a: index)); |
378 | result.append(s: "]" ); |
379 | } |
380 | result.append(s: "." ); |
381 | return result; |
382 | } |
383 | |
384 | void ReflectionOps::FindInitializationErrors(const Message& message, |
385 | const std::string& prefix, |
386 | std::vector<std::string>* errors) { |
387 | const Descriptor* descriptor = message.GetDescriptor(); |
388 | const Reflection* reflection = GetReflectionOrDie(m: message); |
389 | |
390 | // Check required fields of this message. |
391 | { |
392 | const int field_count = descriptor->field_count(); |
393 | for (int i = 0; i < field_count; i++) { |
394 | if (descriptor->field(index: i)->is_required()) { |
395 | if (!reflection->HasField(message, field: descriptor->field(index: i))) { |
396 | errors->push_back(x: prefix + descriptor->field(index: i)->name()); |
397 | } |
398 | } |
399 | } |
400 | } |
401 | |
402 | // Check sub-messages. |
403 | std::vector<const FieldDescriptor*> fields; |
404 | reflection->ListFieldsOmitStripped(message, output: &fields); |
405 | for (const FieldDescriptor* field : fields) { |
406 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
407 | |
408 | if (field->is_repeated()) { |
409 | int size = reflection->FieldSize(message, field); |
410 | |
411 | for (int j = 0; j < size; j++) { |
412 | const Message& sub_message = |
413 | reflection->GetRepeatedMessage(message, field, index: j); |
414 | FindInitializationErrors(message: sub_message, |
415 | prefix: SubMessagePrefix(prefix, field, index: j), errors); |
416 | } |
417 | } else { |
418 | const Message& sub_message = reflection->GetMessage(message, field); |
419 | FindInitializationErrors(message: sub_message, |
420 | prefix: SubMessagePrefix(prefix, field, index: -1), errors); |
421 | } |
422 | } |
423 | } |
424 | } |
425 | |
426 | void GenericSwap(Message* lhs, Message* rhs) { |
427 | #ifndef PROTOBUF_FORCE_COPY_IN_SWAP |
428 | GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != |
429 | Arena::InternalGetOwningArena(rhs)); |
430 | GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != nullptr || |
431 | Arena::InternalGetOwningArena(rhs) != nullptr); |
432 | #endif // !PROTOBUF_FORCE_COPY_IN_SWAP |
433 | // At least one of these must have an arena, so make `rhs` point to it. |
434 | Arena* arena = Arena::InternalGetOwningArena(p: rhs); |
435 | if (arena == nullptr) { |
436 | std::swap(a&: lhs, b&: rhs); |
437 | arena = Arena::InternalGetOwningArena(p: rhs); |
438 | } |
439 | |
440 | // Improve efficiency by placing the temporary on an arena so that messages |
441 | // are copied twice rather than three times. |
442 | Message* tmp = rhs->New(arena); |
443 | tmp->CheckTypeAndMergeFrom(other: *lhs); |
444 | lhs->Clear(); |
445 | lhs->CheckTypeAndMergeFrom(other: *rhs); |
446 | #ifdef PROTOBUF_FORCE_COPY_IN_SWAP |
447 | rhs->Clear(); |
448 | rhs->CheckTypeAndMergeFrom(*tmp); |
449 | if (arena == nullptr) delete tmp; |
450 | #else // PROTOBUF_FORCE_COPY_IN_SWAP |
451 | rhs->GetReflection()->Swap(message1: tmp, message2: rhs); |
452 | #endif // !PROTOBUF_FORCE_COPY_IN_SWAP |
453 | } |
454 | |
455 | } // namespace internal |
456 | } // namespace protobuf |
457 | } // namespace google |
458 | |
459 | #include <google/protobuf/port_undef.inc> |
460 | |