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
50namespace google {
51namespace protobuf {
52namespace internal {
53
54static 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
65void ReflectionOps::Copy(const Message& from, Message* to) {
66 if (&from == to) return;
67 Clear(message: to);
68 Merge(from, to);
69}
70
71void 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
179void 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
193bool 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
255bool 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
320static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) {
321 return map_field->message_type()->field(index: 1)->cpp_type() ==
322 FieldDescriptor::CPPTYPE_MESSAGE;
323}
324
325void 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
365static 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
384void 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
426void 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