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
GetReflectionOrDie(const Message & m)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
Copy(const Message & from,Message * to)65 void ReflectionOps::Copy(const Message& from, Message* to) {
66 if (&from == to) return;
67 Clear(to);
68 Merge(from, to);
69 }
70
Merge(const Message & from,Message * to)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(from);
81 const Reflection* to_reflection = GetReflectionOrDie(*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(from, &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(from, field);
99 MapFieldBase* to_field = to_reflection->MutableMapData(to, field);
100 if (to_field->IsMapValid() && from_field->IsMapValid()) {
101 to_field->MergeFrom(*from_field);
102 continue;
103 }
104 }
105 int count = from_reflection->FieldSize(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(from, field, j);
128 if (from_reflection == to_reflection) {
129 to_reflection
130 ->AddMessage(to, field,
131 from_child.GetReflection()->GetMessageFactory())
132 ->MergeFrom(from_child);
133 } else {
134 to_reflection->AddMessage(to, field)->MergeFrom(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(from, field);
160 if (from_reflection == to_reflection) {
161 to_reflection
162 ->MutableMessage(
163 to, field, from_child.GetReflection()->GetMessageFactory())
164 ->MergeFrom(from_child);
165 } else {
166 to_reflection->MutableMessage(to, field)->MergeFrom(from_child);
167 }
168 break;
169 }
170 }
171 }
172
173 to_reflection->MutableUnknownFields(to)->MergeFrom(
174 from_reflection->GetUnknownFields(from));
175 }
176
Clear(Message * message)177 void ReflectionOps::Clear(Message* message) {
178 const Reflection* reflection = GetReflectionOrDie(*message);
179
180 std::vector<const FieldDescriptor*> fields;
181 reflection->ListFieldsOmitStripped(*message, &fields);
182 for (const FieldDescriptor* field : fields) {
183 reflection->ClearField(message, field);
184 }
185
186 if (reflection->GetInternalMetadata(*message).have_unknown_fields()) {
187 reflection->MutableUnknownFields(message)->Clear();
188 }
189 }
190
IsInitialized(const Message & message,bool check_fields,bool check_descendants)191 bool ReflectionOps::IsInitialized(const Message& message, bool check_fields,
192 bool check_descendants) {
193 const Descriptor* descriptor = message.GetDescriptor();
194 const Reflection* reflection = GetReflectionOrDie(message);
195 if (const int field_count = descriptor->field_count()) {
196 const FieldDescriptor* begin = descriptor->field(0);
197 const FieldDescriptor* end = begin + field_count;
198 GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1);
199
200 if (check_fields) {
201 // Check required fields of this message.
202 for (const FieldDescriptor* field = begin; field != end; ++field) {
203 if (field->is_required() && !reflection->HasField(message, field)) {
204 return false;
205 }
206 }
207 }
208
209 if (check_descendants) {
210 for (const FieldDescriptor* field = begin; field != end; ++field) {
211 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
212 const Descriptor* message_type = field->message_type();
213 if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) {
214 if (message_type->field(1)->cpp_type() ==
215 FieldDescriptor::CPPTYPE_MESSAGE) {
216 const MapFieldBase* map_field =
217 reflection->GetMapData(message, field);
218 if (map_field->IsMapValid()) {
219 MapIterator it(const_cast<Message*>(&message), field);
220 MapIterator end_map(const_cast<Message*>(&message), field);
221 for (map_field->MapBegin(&it), map_field->MapEnd(&end_map);
222 it != end_map; ++it) {
223 if (!it.GetValueRef().GetMessageValue().IsInitialized()) {
224 return false;
225 }
226 }
227 }
228 }
229 } else if (field->is_repeated()) {
230 const int size = reflection->FieldSize(message, field);
231 for (int j = 0; j < size; j++) {
232 if (!reflection->GetRepeatedMessage(message, field, j)
233 .IsInitialized()) {
234 return false;
235 }
236 }
237 } else if (reflection->HasField(message, field)) {
238 if (!reflection->GetMessage(message, field).IsInitialized()) {
239 return false;
240 }
241 }
242 }
243 }
244 }
245 }
246 if (check_descendants && reflection->HasExtensionSet(message) &&
247 !reflection->GetExtensionSet(message).IsInitialized()) {
248 return false;
249 }
250 return true;
251 }
252
IsInitialized(const Message & message)253 bool ReflectionOps::IsInitialized(const Message& message) {
254 const Descriptor* descriptor = message.GetDescriptor();
255 const Reflection* reflection = GetReflectionOrDie(message);
256
257 // Check required fields of this message.
258 {
259 const int field_count = descriptor->field_count();
260 for (int i = 0; i < field_count; i++) {
261 if (descriptor->field(i)->is_required()) {
262 if (!reflection->HasField(message, descriptor->field(i))) {
263 return false;
264 }
265 }
266 }
267 }
268
269 // Check that sub-messages are initialized.
270 std::vector<const FieldDescriptor*> fields;
271 // Should be safe to skip stripped fields because required fields are not
272 // stripped.
273 reflection->ListFieldsOmitStripped(message, &fields);
274 for (const FieldDescriptor* field : fields) {
275 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
276
277 if (field->is_map()) {
278 const FieldDescriptor* value_field = field->message_type()->field(1);
279 if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
280 const MapFieldBase* map_field =
281 reflection->GetMapData(message, field);
282 if (map_field->IsMapValid()) {
283 MapIterator iter(const_cast<Message*>(&message), field);
284 MapIterator end(const_cast<Message*>(&message), field);
285 for (map_field->MapBegin(&iter), map_field->MapEnd(&end);
286 iter != end; ++iter) {
287 if (!iter.GetValueRef().GetMessageValue().IsInitialized()) {
288 return false;
289 }
290 }
291 continue;
292 }
293 } else {
294 continue;
295 }
296 }
297
298 if (field->is_repeated()) {
299 int size = reflection->FieldSize(message, field);
300
301 for (int j = 0; j < size; j++) {
302 if (!reflection->GetRepeatedMessage(message, field, j)
303 .IsInitialized()) {
304 return false;
305 }
306 }
307 } else {
308 if (!reflection->GetMessage(message, field).IsInitialized()) {
309 return false;
310 }
311 }
312 }
313 }
314
315 return true;
316 }
317
IsMapValueMessageTyped(const FieldDescriptor * map_field)318 static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) {
319 return map_field->message_type()->field(1)->cpp_type() ==
320 FieldDescriptor::CPPTYPE_MESSAGE;
321 }
322
DiscardUnknownFields(Message * message)323 void ReflectionOps::DiscardUnknownFields(Message* message) {
324 const Reflection* reflection = GetReflectionOrDie(*message);
325
326 reflection->MutableUnknownFields(message)->Clear();
327
328 // Walk through the fields of this message and DiscardUnknownFields on any
329 // messages present.
330 std::vector<const FieldDescriptor*> fields;
331 reflection->ListFields(*message, &fields);
332 for (const FieldDescriptor* field : fields) {
333 // Skip over non-message fields.
334 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
335 continue;
336 }
337 // Discard the unknown fields in maps that contain message values.
338 if (field->is_map() && IsMapValueMessageTyped(field)) {
339 const MapFieldBase* map_field =
340 reflection->MutableMapData(message, field);
341 if (map_field->IsMapValid()) {
342 MapIterator iter(message, field);
343 MapIterator end(message, field);
344 for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end;
345 ++iter) {
346 iter.MutableValueRef()->MutableMessageValue()->DiscardUnknownFields();
347 }
348 }
349 // Discard every unknown field inside messages in a repeated field.
350 } else if (field->is_repeated()) {
351 int size = reflection->FieldSize(*message, field);
352 for (int j = 0; j < size; j++) {
353 reflection->MutableRepeatedMessage(message, field, j)
354 ->DiscardUnknownFields();
355 }
356 // Discard the unknown fields inside an optional message.
357 } else {
358 reflection->MutableMessage(message, field)->DiscardUnknownFields();
359 }
360 }
361 }
362
SubMessagePrefix(const std::string & prefix,const FieldDescriptor * field,int index)363 static std::string SubMessagePrefix(const std::string& prefix,
364 const FieldDescriptor* field, int index) {
365 std::string result(prefix);
366 if (field->is_extension()) {
367 result.append("(");
368 result.append(field->full_name());
369 result.append(")");
370 } else {
371 result.append(field->name());
372 }
373 if (index != -1) {
374 result.append("[");
375 result.append(StrCat(index));
376 result.append("]");
377 }
378 result.append(".");
379 return result;
380 }
381
FindInitializationErrors(const Message & message,const std::string & prefix,std::vector<std::string> * errors)382 void ReflectionOps::FindInitializationErrors(const Message& message,
383 const std::string& prefix,
384 std::vector<std::string>* errors) {
385 const Descriptor* descriptor = message.GetDescriptor();
386 const Reflection* reflection = GetReflectionOrDie(message);
387
388 // Check required fields of this message.
389 {
390 const int field_count = descriptor->field_count();
391 for (int i = 0; i < field_count; i++) {
392 if (descriptor->field(i)->is_required()) {
393 if (!reflection->HasField(message, descriptor->field(i))) {
394 errors->push_back(prefix + descriptor->field(i)->name());
395 }
396 }
397 }
398 }
399
400 // Check sub-messages.
401 std::vector<const FieldDescriptor*> fields;
402 reflection->ListFieldsOmitStripped(message, &fields);
403 for (const FieldDescriptor* field : fields) {
404 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
405
406 if (field->is_repeated()) {
407 int size = reflection->FieldSize(message, field);
408
409 for (int j = 0; j < size; j++) {
410 const Message& sub_message =
411 reflection->GetRepeatedMessage(message, field, j);
412 FindInitializationErrors(sub_message,
413 SubMessagePrefix(prefix, field, j), errors);
414 }
415 } else {
416 const Message& sub_message = reflection->GetMessage(message, field);
417 FindInitializationErrors(sub_message,
418 SubMessagePrefix(prefix, field, -1), errors);
419 }
420 }
421 }
422 }
423
GenericSwap(Message * lhs,Message * rhs)424 void GenericSwap(Message* lhs, Message* rhs) {
425 #ifndef PROTOBUF_FORCE_COPY_IN_SWAP
426 GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) !=
427 Arena::InternalGetOwningArena(rhs));
428 GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != nullptr ||
429 Arena::InternalGetOwningArena(rhs) != nullptr);
430 #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
431 // At least one of these must have an arena, so make `rhs` point to it.
432 Arena* arena = Arena::InternalGetOwningArena(rhs);
433 if (arena == nullptr) {
434 std::swap(lhs, rhs);
435 arena = Arena::InternalGetOwningArena(rhs);
436 }
437
438 // Improve efficiency by placing the temporary on an arena so that messages
439 // are copied twice rather than three times.
440 Message* tmp = rhs->New(arena);
441 tmp->CheckTypeAndMergeFrom(*lhs);
442 lhs->Clear();
443 lhs->CheckTypeAndMergeFrom(*rhs);
444 #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
445 rhs->Clear();
446 rhs->CheckTypeAndMergeFrom(*tmp);
447 if (arena == nullptr) delete tmp;
448 #else // PROTOBUF_FORCE_COPY_IN_SWAP
449 rhs->GetReflection()->Swap(tmp, rhs);
450 #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
451 }
452
453 } // namespace internal
454 } // namespace protobuf
455 } // namespace google
456
457 #include <google/protobuf/port_undef.inc>
458