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
35#include <google/protobuf/generated_message_reflection.h>
36
37#include <algorithm>
38#include <set>
39
40#include <google/protobuf/stubs/logging.h>
41#include <google/protobuf/stubs/common.h>
42#include <google/protobuf/stubs/mutex.h>
43#include <google/protobuf/stubs/casts.h>
44#include <google/protobuf/stubs/strutil.h>
45#include <google/protobuf/descriptor.h>
46#include <google/protobuf/descriptor.pb.h>
47#include <google/protobuf/extension_set.h>
48#include <google/protobuf/generated_message_util.h>
49#include <google/protobuf/inlined_string_field.h>
50#include <google/protobuf/map_field.h>
51#include <google/protobuf/map_field_inl.h>
52#include <google/protobuf/repeated_field.h>
53#include <google/protobuf/unknown_field_set.h>
54
55
56// clang-format off
57#include <google/protobuf/port_def.inc>
58// clang-format on
59
60#define GOOGLE_PROTOBUF_HAS_ONEOF
61
62using google::protobuf::internal::ArenaStringPtr;
63using google::protobuf::internal::DescriptorTable;
64using google::protobuf::internal::ExtensionSet;
65using google::protobuf::internal::GenericTypeHandler;
66using google::protobuf::internal::GetEmptyString;
67using google::protobuf::internal::InlinedStringField;
68using google::protobuf::internal::InternalMetadata;
69using google::protobuf::internal::LazyField;
70using google::protobuf::internal::MapFieldBase;
71using google::protobuf::internal::MigrationSchema;
72using google::protobuf::internal::OnShutdownDelete;
73using google::protobuf::internal::ReflectionSchema;
74using google::protobuf::internal::RepeatedPtrFieldBase;
75using google::protobuf::internal::StringSpaceUsedExcludingSelfLong;
76using google::protobuf::internal::WrappedMutex;
77
78namespace google {
79namespace protobuf {
80
81namespace {
82bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
83
84#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
85Message* MaybeForceCopy(Arena* arena, Message* msg) {
86 if (arena != nullptr || msg == nullptr) return msg;
87
88 Message* copy = msg->New();
89 copy->MergeFrom(*msg);
90 delete msg;
91 return copy;
92}
93#endif // PROTOBUF_FORCE_COPY_IN_RELEASE
94} // anonymous namespace
95
96namespace internal {
97
98bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
99 int* value) {
100 const EnumValueDescriptor* d = descriptor->FindValueByName(name);
101 if (d == nullptr) return false;
102 *value = d->number();
103 return true;
104}
105
106const std::string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
107 const EnumValueDescriptor* d = descriptor->FindValueByNumber(number: value);
108 return (d == nullptr ? GetEmptyString() : d->name());
109}
110
111} // namespace internal
112
113// ===================================================================
114// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
115// a string field).
116
117namespace {
118
119using internal::GetConstPointerAtOffset;
120using internal::GetConstRefAtOffset;
121using internal::GetPointerAtOffset;
122
123void ReportReflectionUsageError(const Descriptor* descriptor,
124 const FieldDescriptor* field,
125 const char* method, const char* description) {
126 GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n"
127 " Method : google::protobuf::Reflection::"
128 << method
129 << "\n"
130 " Message type: "
131 << descriptor->full_name()
132 << "\n"
133 " Field : "
134 << field->full_name()
135 << "\n"
136 " Problem : "
137 << description;
138}
139
140const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
141 "INVALID_CPPTYPE", "CPPTYPE_INT32", "CPPTYPE_INT64", "CPPTYPE_UINT32",
142 "CPPTYPE_UINT64", "CPPTYPE_DOUBLE", "CPPTYPE_FLOAT", "CPPTYPE_BOOL",
143 "CPPTYPE_ENUM", "CPPTYPE_STRING", "CPPTYPE_MESSAGE"};
144
145static void ReportReflectionUsageTypeError(
146 const Descriptor* descriptor, const FieldDescriptor* field,
147 const char* method, FieldDescriptor::CppType expected_type) {
148 GOOGLE_LOG(FATAL)
149 << "Protocol Buffer reflection usage error:\n"
150 " Method : google::protobuf::Reflection::"
151 << method
152 << "\n"
153 " Message type: "
154 << descriptor->full_name()
155 << "\n"
156 " Field : "
157 << field->full_name()
158 << "\n"
159 " Problem : Field is not the right type for this message:\n"
160 " Expected : "
161 << cpptype_names_[expected_type]
162 << "\n"
163 " Field type: "
164 << cpptype_names_[field->cpp_type()];
165}
166
167static void ReportReflectionUsageEnumTypeError(
168 const Descriptor* descriptor, const FieldDescriptor* field,
169 const char* method, const EnumValueDescriptor* value) {
170 GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n"
171 " Method : google::protobuf::Reflection::"
172 << method
173 << "\n"
174 " Message type: "
175 << descriptor->full_name()
176 << "\n"
177 " Field : "
178 << field->full_name()
179 << "\n"
180 " Problem : Enum value did not match field type:\n"
181 " Expected : "
182 << field->enum_type()->full_name()
183 << "\n"
184 " Actual : "
185 << value->full_name();
186}
187
188inline void CheckInvalidAccess(const internal::ReflectionSchema& schema,
189 const FieldDescriptor* field) {
190 GOOGLE_CHECK(!schema.IsFieldStripped(field))
191 << "invalid access to a stripped field " << field->full_name();
192}
193
194#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
195 if (!(CONDITION)) \
196 ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
197#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \
198 USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
199#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \
200 USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
201
202#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \
203 if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \
204 ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \
205 FieldDescriptor::CPPTYPE_##CPPTYPE)
206
207#define USAGE_CHECK_ENUM_VALUE(METHOD) \
208 if (value->type() != field->enum_type()) \
209 ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
210
211#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \
212 USAGE_CHECK_EQ(field->containing_type(), descriptor_, METHOD, \
213 "Field does not match message type.");
214#define USAGE_CHECK_SINGULAR(METHOD) \
215 USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
216 "Field is repeated; the method requires a singular field.")
217#define USAGE_CHECK_REPEATED(METHOD) \
218 USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
219 "Field is singular; the method requires a repeated field.")
220
221#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \
222 USAGE_CHECK_MESSAGE_TYPE(METHOD); \
223 USAGE_CHECK_##LABEL(METHOD); \
224 USAGE_CHECK_TYPE(METHOD, CPPTYPE)
225
226} // namespace
227
228// ===================================================================
229
230Reflection::Reflection(const Descriptor* descriptor,
231 const internal::ReflectionSchema& schema,
232 const DescriptorPool* pool, MessageFactory* factory)
233 : descriptor_(descriptor),
234 schema_(schema),
235 descriptor_pool_(
236 (pool == nullptr) ? DescriptorPool::internal_generated_pool() : pool),
237 message_factory_(factory),
238 last_non_weak_field_index_(-1) {
239 last_non_weak_field_index_ = descriptor_->field_count() - 1;
240}
241
242const UnknownFieldSet& Reflection::GetUnknownFields(
243 const Message& message) const {
244 return GetInternalMetadata(message).unknown_fields<UnknownFieldSet>(
245 default_instance: UnknownFieldSet::default_instance);
246}
247
248UnknownFieldSet* Reflection::MutableUnknownFields(Message* message) const {
249 return MutableInternalMetadata(message)
250 ->mutable_unknown_fields<UnknownFieldSet>();
251}
252
253bool Reflection::IsLazyExtension(const Message& message,
254 const FieldDescriptor* field) const {
255 return field->is_extension() &&
256 GetExtensionSet(message).HasLazy(number: field->number());
257}
258
259bool Reflection::IsLazilyVerifiedLazyField(const FieldDescriptor* field) const {
260 if (field->options().unverified_lazy()) return true;
261
262 // Message fields with [lazy=true] will be eagerly verified
263 // (go/verified-lazy).
264 return field->options().lazy() && !IsEagerlyVerifiedLazyField(field);
265}
266
267bool Reflection::IsEagerlyVerifiedLazyField(
268 const FieldDescriptor* field) const {
269 return (field->type() == FieldDescriptor::TYPE_MESSAGE &&
270 schema_.IsEagerlyVerifiedLazyField(field));
271}
272
273bool Reflection::IsInlined(const FieldDescriptor* field) const {
274 return schema_.IsFieldInlined(field);
275}
276
277size_t Reflection::SpaceUsedLong(const Message& message) const {
278 // object_size_ already includes the in-memory representation of each field
279 // in the message, so we only need to account for additional memory used by
280 // the fields.
281 size_t total_size = schema_.GetObjectSize();
282
283 total_size += GetUnknownFields(message).SpaceUsedExcludingSelfLong();
284
285 // If this message owns an arena, add any unused space that's been allocated.
286 auto* arena = Arena::InternalGetArenaForAllocation(p: &message);
287 if (arena != nullptr && Arena::InternalGetOwningArena(p: &message) == nullptr &&
288 arena->InternalIsMessageOwnedArena()) {
289 total_size += arena->SpaceAllocated() - arena->SpaceUsed();
290 }
291
292 if (schema_.HasExtensionSet()) {
293 total_size += GetExtensionSet(message).SpaceUsedExcludingSelfLong();
294 }
295 for (int i = 0; i <= last_non_weak_field_index_; i++) {
296 const FieldDescriptor* field = descriptor_->field(index: i);
297 if (field->is_repeated()) {
298 switch (field->cpp_type()) {
299#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
300 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
301 total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field) \
302 .SpaceUsedExcludingSelfLong(); \
303 break
304
305 HANDLE_TYPE(INT32, int32_t);
306 HANDLE_TYPE(INT64, int64_t);
307 HANDLE_TYPE(UINT32, uint32_t);
308 HANDLE_TYPE(UINT64, uint64_t);
309 HANDLE_TYPE(DOUBLE, double);
310 HANDLE_TYPE(FLOAT, float);
311 HANDLE_TYPE(BOOL, bool);
312 HANDLE_TYPE(ENUM, int);
313#undef HANDLE_TYPE
314
315 case FieldDescriptor::CPPTYPE_STRING:
316 switch (field->options().ctype()) {
317 default: // TODO(kenton): Support other string reps.
318 case FieldOptions::STRING:
319 total_size +=
320 GetRaw<RepeatedPtrField<std::string> >(message, field)
321 .SpaceUsedExcludingSelfLong();
322 break;
323 }
324 break;
325
326 case FieldDescriptor::CPPTYPE_MESSAGE:
327 if (IsMapFieldInApi(field)) {
328 total_size += GetRaw<internal::MapFieldBase>(message, field)
329 .SpaceUsedExcludingSelfLong();
330 } else {
331 // We don't know which subclass of RepeatedPtrFieldBase the type is,
332 // so we use RepeatedPtrFieldBase directly.
333 total_size +=
334 GetRaw<RepeatedPtrFieldBase>(message, field)
335 .SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >();
336 }
337
338 break;
339 }
340 } else {
341 if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
342 continue;
343 }
344 switch (field->cpp_type()) {
345 case FieldDescriptor::CPPTYPE_INT32:
346 case FieldDescriptor::CPPTYPE_INT64:
347 case FieldDescriptor::CPPTYPE_UINT32:
348 case FieldDescriptor::CPPTYPE_UINT64:
349 case FieldDescriptor::CPPTYPE_DOUBLE:
350 case FieldDescriptor::CPPTYPE_FLOAT:
351 case FieldDescriptor::CPPTYPE_BOOL:
352 case FieldDescriptor::CPPTYPE_ENUM:
353 // Field is inline, so we've already counted it.
354 break;
355
356 case FieldDescriptor::CPPTYPE_STRING: {
357 switch (field->options().ctype()) {
358 default: // TODO(kenton): Support other string reps.
359 case FieldOptions::STRING:
360 if (IsInlined(field)) {
361 const std::string* ptr =
362 &GetField<InlinedStringField>(message, field).GetNoArena();
363 total_size += StringSpaceUsedExcludingSelfLong(str: *ptr);
364 } else {
365 // Initially, the string points to the default value stored
366 // in the prototype. Only count the string if it has been
367 // changed from the default value.
368 // Except oneof fields, those never point to a default instance,
369 // and there is no default instance to point to.
370 const auto& str = GetField<ArenaStringPtr>(message, field);
371 if (!str.IsDefault() || schema_.InRealOneof(field)) {
372 // string fields are represented by just a pointer, so also
373 // include sizeof(string) as well.
374 total_size += sizeof(std::string) +
375 StringSpaceUsedExcludingSelfLong(str: str.Get());
376 }
377 }
378 break;
379 }
380 break;
381 }
382
383 case FieldDescriptor::CPPTYPE_MESSAGE:
384 if (schema_.IsDefaultInstance(message)) {
385 // For singular fields, the prototype just stores a pointer to the
386 // external type's prototype, so there is no extra memory usage.
387 } else {
388 const Message* sub_message = GetRaw<const Message*>(message, field);
389 if (sub_message != nullptr) {
390 total_size += sub_message->SpaceUsedLong();
391 }
392 }
393 break;
394 }
395 }
396 }
397 return total_size;
398}
399
400namespace {
401
402template <bool unsafe_shallow_swap>
403struct OneofFieldMover {
404 template <typename FromType, typename ToType>
405 void operator()(const FieldDescriptor* field, FromType* from, ToType* to) {
406 switch (field->cpp_type()) {
407 case FieldDescriptor::CPPTYPE_INT32:
408 to->SetInt32(from->GetInt32());
409 break;
410 case FieldDescriptor::CPPTYPE_INT64:
411 to->SetInt64(from->GetInt64());
412 break;
413 case FieldDescriptor::CPPTYPE_UINT32:
414 to->SetUint32(from->GetUint32());
415 break;
416 case FieldDescriptor::CPPTYPE_UINT64:
417 to->SetUint64(from->GetUint64());
418 break;
419 case FieldDescriptor::CPPTYPE_FLOAT:
420 to->SetFloat(from->GetFloat());
421 break;
422 case FieldDescriptor::CPPTYPE_DOUBLE:
423 to->SetDouble(from->GetDouble());
424 break;
425 case FieldDescriptor::CPPTYPE_BOOL:
426 to->SetBool(from->GetBool());
427 break;
428 case FieldDescriptor::CPPTYPE_ENUM:
429 to->SetEnum(from->GetEnum());
430 break;
431 case FieldDescriptor::CPPTYPE_MESSAGE:
432 if (!unsafe_shallow_swap) {
433 to->SetMessage(from->GetMessage());
434 } else {
435 to->UnsafeSetMessage(from->UnsafeGetMessage());
436 }
437 break;
438 case FieldDescriptor::CPPTYPE_STRING:
439 if (!unsafe_shallow_swap) {
440 to->SetString(from->GetString());
441 break;
442 }
443 switch (field->options().ctype()) {
444 default:
445 case FieldOptions::STRING: {
446 to->SetArenaStringPtr(from->GetArenaStringPtr());
447 break;
448 }
449 }
450 break;
451 default:
452 GOOGLE_LOG(FATAL) << "unimplemented type: " << field->cpp_type();
453 }
454 if (unsafe_shallow_swap) {
455 // Not clearing oneof case after move may cause unwanted "ClearOneof"
456 // where the residual message or string value is deleted and causes
457 // use-after-free (only for unsafe swap).
458 from->ClearOneofCase();
459 }
460 }
461};
462
463} // namespace
464
465namespace internal {
466
467class SwapFieldHelper {
468 public:
469 template <bool unsafe_shallow_swap>
470 static void SwapRepeatedStringField(const Reflection* r, Message* lhs,
471 Message* rhs,
472 const FieldDescriptor* field);
473
474 template <bool unsafe_shallow_swap>
475 static void SwapInlinedStrings(const Reflection* r, Message* lhs,
476 Message* rhs, const FieldDescriptor* field);
477
478 template <bool unsafe_shallow_swap>
479 static void SwapNonInlinedStrings(const Reflection* r, Message* lhs,
480 Message* rhs, const FieldDescriptor* field);
481
482 template <bool unsafe_shallow_swap>
483 static void SwapStringField(const Reflection* r, Message* lhs, Message* rhs,
484 const FieldDescriptor* field);
485
486 static void SwapArenaStringPtr(ArenaStringPtr* lhs, Arena* lhs_arena,
487 ArenaStringPtr* rhs, Arena* rhs_arena);
488
489 template <bool unsafe_shallow_swap>
490 static void SwapRepeatedMessageField(const Reflection* r, Message* lhs,
491 Message* rhs,
492 const FieldDescriptor* field);
493
494 template <bool unsafe_shallow_swap>
495 static void SwapMessageField(const Reflection* r, Message* lhs, Message* rhs,
496 const FieldDescriptor* field);
497
498 static void SwapMessage(const Reflection* r, Message* lhs, Arena* lhs_arena,
499 Message* rhs, Arena* rhs_arena,
500 const FieldDescriptor* field);
501
502 static void SwapNonMessageNonStringField(const Reflection* r, Message* lhs,
503 Message* rhs,
504 const FieldDescriptor* field);
505};
506
507template <bool unsafe_shallow_swap>
508void SwapFieldHelper::SwapRepeatedStringField(const Reflection* r, Message* lhs,
509 Message* rhs,
510 const FieldDescriptor* field) {
511 switch (field->options().ctype()) {
512 default:
513 case FieldOptions::STRING: {
514 auto* lhs_string = r->MutableRaw<RepeatedPtrFieldBase>(message: lhs, field);
515 auto* rhs_string = r->MutableRaw<RepeatedPtrFieldBase>(message: rhs, field);
516 if (unsafe_shallow_swap) {
517 lhs_string->InternalSwap(rhs: rhs_string);
518 } else {
519 lhs_string->Swap<GenericTypeHandler<std::string>>(other: rhs_string);
520 }
521 break;
522 }
523 }
524}
525
526template <bool unsafe_shallow_swap>
527void SwapFieldHelper::SwapInlinedStrings(const Reflection* r, Message* lhs,
528 Message* rhs,
529 const FieldDescriptor* field) {
530 // Inlined string field.
531 Arena* lhs_arena = lhs->GetArenaForAllocation();
532 Arena* rhs_arena = rhs->GetArenaForAllocation();
533 auto* lhs_string = r->MutableRaw<InlinedStringField>(message: lhs, field);
534 auto* rhs_string = r->MutableRaw<InlinedStringField>(message: rhs, field);
535 uint32_t index = r->schema_.InlinedStringIndex(field);
536 GOOGLE_DCHECK_GT(index, 0);
537 uint32_t* lhs_array = r->MutableInlinedStringDonatedArray(message: lhs);
538 uint32_t* rhs_array = r->MutableInlinedStringDonatedArray(message: rhs);
539 uint32_t* lhs_state = &lhs_array[index / 32];
540 uint32_t* rhs_state = &rhs_array[index / 32];
541 bool lhs_arena_dtor_registered = (lhs_array[0] & 0x1u) == 0;
542 bool rhs_arena_dtor_registered = (rhs_array[0] & 0x1u) == 0;
543 const uint32_t mask = ~(static_cast<uint32_t>(1) << (index % 32));
544 if (unsafe_shallow_swap || lhs_arena == rhs_arena) {
545 InlinedStringField::InternalSwap(lhs: lhs_string, lhs_arena,
546 lhs_arena_dtor_registered, lhs_msg: lhs, rhs: rhs_string,
547 rhs_arena, rhs_arena_dtor_registered, rhs_msg: rhs);
548 } else {
549 const std::string temp = lhs_string->Get();
550 lhs_string->Set(value: rhs_string->Get(), arena: lhs_arena,
551 donated: r->IsInlinedStringDonated(message: *lhs, field), lhs_state, mask,
552 lhs);
553 rhs_string->Set(value: temp, arena: rhs_arena, donated: r->IsInlinedStringDonated(message: *rhs, field),
554 rhs_state, mask, rhs);
555 }
556}
557
558template <bool unsafe_shallow_swap>
559void SwapFieldHelper::SwapNonInlinedStrings(const Reflection* r, Message* lhs,
560 Message* rhs,
561 const FieldDescriptor* field) {
562 ArenaStringPtr* lhs_string = r->MutableRaw<ArenaStringPtr>(message: lhs, field);
563 ArenaStringPtr* rhs_string = r->MutableRaw<ArenaStringPtr>(message: rhs, field);
564 if (unsafe_shallow_swap) {
565 ArenaStringPtr::UnsafeShallowSwap(rhs: lhs_string, lhs: rhs_string);
566 } else {
567 SwapFieldHelper::SwapArenaStringPtr(
568 lhs: lhs_string, lhs_arena: lhs->GetArenaForAllocation(), //
569 rhs: rhs_string, rhs_arena: rhs->GetArenaForAllocation());
570 }
571}
572
573template <bool unsafe_shallow_swap>
574void SwapFieldHelper::SwapStringField(const Reflection* r, Message* lhs,
575 Message* rhs,
576 const FieldDescriptor* field) {
577 switch (field->options().ctype()) {
578 default:
579 case FieldOptions::STRING: {
580 if (r->IsInlined(field)) {
581 SwapFieldHelper::SwapInlinedStrings<unsafe_shallow_swap>(r, lhs, rhs,
582 field);
583 } else {
584 SwapFieldHelper::SwapNonInlinedStrings<unsafe_shallow_swap>(r, lhs, rhs,
585 field);
586 }
587 break;
588 }
589 }
590}
591
592void SwapFieldHelper::SwapArenaStringPtr(ArenaStringPtr* lhs, Arena* lhs_arena,
593 ArenaStringPtr* rhs,
594 Arena* rhs_arena) {
595 if (lhs_arena == rhs_arena) {
596 ArenaStringPtr::InternalSwap(rhs: lhs, rhs_arena: lhs_arena, lhs: rhs, lhs_arena: rhs_arena);
597 } else if (lhs->IsDefault() && rhs->IsDefault()) {
598 // Nothing to do.
599 } else if (lhs->IsDefault()) {
600 lhs->Set(value: rhs->Get(), arena: lhs_arena);
601 // rhs needs to be destroyed before overwritten.
602 rhs->Destroy();
603 rhs->InitDefault();
604 } else if (rhs->IsDefault()) {
605 rhs->Set(value: lhs->Get(), arena: rhs_arena);
606 // lhs needs to be destroyed before overwritten.
607 lhs->Destroy();
608 lhs->InitDefault();
609 } else {
610 std::string temp = lhs->Get();
611 lhs->Set(value: rhs->Get(), arena: lhs_arena);
612 rhs->Set(value: std::move(temp), arena: rhs_arena);
613 }
614}
615
616template <bool unsafe_shallow_swap>
617void SwapFieldHelper::SwapRepeatedMessageField(const Reflection* r,
618 Message* lhs, Message* rhs,
619 const FieldDescriptor* field) {
620 if (IsMapFieldInApi(field)) {
621 auto* lhs_map = r->MutableRaw<MapFieldBase>(message: lhs, field);
622 auto* rhs_map = r->MutableRaw<MapFieldBase>(message: rhs, field);
623 if (unsafe_shallow_swap) {
624 lhs_map->UnsafeShallowSwap(other: rhs_map);
625 } else {
626 lhs_map->Swap(other: rhs_map);
627 }
628 } else {
629 auto* lhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(message: lhs, field);
630 auto* rhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(message: rhs, field);
631 if (unsafe_shallow_swap) {
632 lhs_rm->InternalSwap(rhs: rhs_rm);
633 } else {
634 lhs_rm->Swap<GenericTypeHandler<Message>>(other: rhs_rm);
635 }
636 }
637}
638
639template <bool unsafe_shallow_swap>
640void SwapFieldHelper::SwapMessageField(const Reflection* r, Message* lhs,
641 Message* rhs,
642 const FieldDescriptor* field) {
643 if (unsafe_shallow_swap) {
644 std::swap(a&: *r->MutableRaw<Message*>(message: lhs, field),
645 b&: *r->MutableRaw<Message*>(message: rhs, field));
646 } else {
647 SwapMessage(r, lhs, lhs_arena: lhs->GetArenaForAllocation(), rhs,
648 rhs_arena: rhs->GetArenaForAllocation(), field);
649 }
650}
651
652void SwapFieldHelper::SwapMessage(const Reflection* r, Message* lhs,
653 Arena* lhs_arena, Message* rhs,
654 Arena* rhs_arena,
655 const FieldDescriptor* field) {
656 Message** lhs_sub = r->MutableRaw<Message*>(message: lhs, field);
657 Message** rhs_sub = r->MutableRaw<Message*>(message: rhs, field);
658
659 if (*lhs_sub == *rhs_sub) return;
660
661#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
662 if (lhs_arena != nullptr && lhs_arena == rhs_arena) {
663#else // PROTOBUF_FORCE_COPY_IN_SWAP
664 if (lhs_arena == rhs_arena) {
665#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
666 std::swap(a&: *lhs_sub, b&: *rhs_sub);
667 return;
668 }
669
670 if (*lhs_sub != nullptr && *rhs_sub != nullptr) {
671 (*lhs_sub)->GetReflection()->Swap(message1: *lhs_sub, message2: *rhs_sub);
672 } else if (*lhs_sub == nullptr && r->HasBit(message: *rhs, field)) {
673 *lhs_sub = (*rhs_sub)->New(arena: lhs_arena);
674 (*lhs_sub)->CopyFrom(from: **rhs_sub);
675 r->ClearField(message: rhs, field);
676 // Ensures has bit is unchanged after ClearField.
677 r->SetBit(message: rhs, field);
678 } else if (*rhs_sub == nullptr && r->HasBit(message: *lhs, field)) {
679 *rhs_sub = (*lhs_sub)->New(arena: rhs_arena);
680 (*rhs_sub)->CopyFrom(from: **lhs_sub);
681 r->ClearField(message: lhs, field);
682 // Ensures has bit is unchanged after ClearField.
683 r->SetBit(message: lhs, field);
684 }
685}
686
687void SwapFieldHelper::SwapNonMessageNonStringField(
688 const Reflection* r, Message* lhs, Message* rhs,
689 const FieldDescriptor* field) {
690 switch (field->cpp_type()) {
691#define SWAP_VALUES(CPPTYPE, TYPE) \
692 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
693 std::swap(*r->MutableRaw<TYPE>(lhs, field), \
694 *r->MutableRaw<TYPE>(rhs, field)); \
695 break;
696
697 SWAP_VALUES(INT32, int32_t);
698 SWAP_VALUES(INT64, int64_t);
699 SWAP_VALUES(UINT32, uint32_t);
700 SWAP_VALUES(UINT64, uint64_t);
701 SWAP_VALUES(FLOAT, float);
702 SWAP_VALUES(DOUBLE, double);
703 SWAP_VALUES(BOOL, bool);
704 SWAP_VALUES(ENUM, int);
705#undef SWAP_VALUES
706 default:
707 GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
708 }
709}
710
711} // namespace internal
712
713void Reflection::SwapField(Message* message1, Message* message2,
714 const FieldDescriptor* field) const {
715 if (field->is_repeated()) {
716 switch (field->cpp_type()) {
717#define SWAP_ARRAYS(CPPTYPE, TYPE) \
718 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
719 MutableRaw<RepeatedField<TYPE> >(message1, field) \
720 ->Swap(MutableRaw<RepeatedField<TYPE> >(message2, field)); \
721 break;
722
723 SWAP_ARRAYS(INT32, int32_t);
724 SWAP_ARRAYS(INT64, int64_t);
725 SWAP_ARRAYS(UINT32, uint32_t);
726 SWAP_ARRAYS(UINT64, uint64_t);
727 SWAP_ARRAYS(FLOAT, float);
728 SWAP_ARRAYS(DOUBLE, double);
729 SWAP_ARRAYS(BOOL, bool);
730 SWAP_ARRAYS(ENUM, int);
731#undef SWAP_ARRAYS
732
733 case FieldDescriptor::CPPTYPE_STRING:
734 internal::SwapFieldHelper::SwapRepeatedStringField<false>(
735 r: this, lhs: message1, rhs: message2, field);
736 break;
737 case FieldDescriptor::CPPTYPE_MESSAGE:
738 internal::SwapFieldHelper::SwapRepeatedMessageField<false>(
739 r: this, lhs: message1, rhs: message2, field);
740 break;
741
742 default:
743 GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
744 }
745 } else {
746 switch (field->cpp_type()) {
747 case FieldDescriptor::CPPTYPE_MESSAGE:
748 internal::SwapFieldHelper::SwapMessageField<false>(r: this, lhs: message1,
749 rhs: message2, field);
750 break;
751
752 case FieldDescriptor::CPPTYPE_STRING:
753 internal::SwapFieldHelper::SwapStringField<false>(r: this, lhs: message1,
754 rhs: message2, field);
755 break;
756 default:
757 internal::SwapFieldHelper::SwapNonMessageNonStringField(
758 r: this, lhs: message1, rhs: message2, field);
759 }
760 }
761}
762
763void Reflection::UnsafeShallowSwapField(Message* message1, Message* message2,
764 const FieldDescriptor* field) const {
765 if (!field->is_repeated()) {
766 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
767 internal::SwapFieldHelper::SwapMessageField<true>(r: this, lhs: message1,
768 rhs: message2, field);
769 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
770 internal::SwapFieldHelper::SwapStringField<true>(r: this, lhs: message1, rhs: message2,
771 field);
772 } else {
773 internal::SwapFieldHelper::SwapNonMessageNonStringField(r: this, lhs: message1,
774 rhs: message2, field);
775 }
776 return;
777 }
778
779 switch (field->cpp_type()) {
780#define SHALLOW_SWAP_ARRAYS(CPPTYPE, TYPE) \
781 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
782 MutableRaw<RepeatedField<TYPE>>(message1, field) \
783 ->InternalSwap(MutableRaw<RepeatedField<TYPE>>(message2, field)); \
784 break;
785
786 SHALLOW_SWAP_ARRAYS(INT32, int32_t);
787 SHALLOW_SWAP_ARRAYS(INT64, int64_t);
788 SHALLOW_SWAP_ARRAYS(UINT32, uint32_t);
789 SHALLOW_SWAP_ARRAYS(UINT64, uint64_t);
790 SHALLOW_SWAP_ARRAYS(FLOAT, float);
791 SHALLOW_SWAP_ARRAYS(DOUBLE, double);
792 SHALLOW_SWAP_ARRAYS(BOOL, bool);
793 SHALLOW_SWAP_ARRAYS(ENUM, int);
794#undef SHALLOW_SWAP_ARRAYS
795
796 case FieldDescriptor::CPPTYPE_STRING:
797 internal::SwapFieldHelper::SwapRepeatedStringField<true>(r: this, lhs: message1,
798 rhs: message2, field);
799 break;
800 case FieldDescriptor::CPPTYPE_MESSAGE:
801 internal::SwapFieldHelper::SwapRepeatedMessageField<true>(
802 r: this, lhs: message1, rhs: message2, field);
803 break;
804
805 default:
806 GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
807 }
808}
809
810// Swaps oneof field between lhs and rhs. If unsafe_shallow_swap is true, it
811// directly swaps oneof values; otherwise, it may involve copy/delete. Note that
812// two messages may have different oneof cases. So, it has to be done in three
813// steps (i.e. lhs -> temp, rhs -> lhs, temp -> rhs).
814template <bool unsafe_shallow_swap>
815void Reflection::SwapOneofField(Message* lhs, Message* rhs,
816 const OneofDescriptor* oneof_descriptor) const {
817 // Wraps a local variable to temporarily store oneof value.
818 struct LocalVarWrapper {
819#define LOCAL_VAR_ACCESSOR(type, var, name) \
820 type Get##name() const { return oneof_val.type_##var; } \
821 void Set##name(type v) { oneof_val.type_##var = v; }
822
823 LOCAL_VAR_ACCESSOR(int32_t, int32, Int32);
824 LOCAL_VAR_ACCESSOR(int64_t, int64, Int64);
825 LOCAL_VAR_ACCESSOR(uint32_t, uint32, Uint32);
826 LOCAL_VAR_ACCESSOR(uint64_t, uint64, Uint64);
827 LOCAL_VAR_ACCESSOR(float, float, Float);
828 LOCAL_VAR_ACCESSOR(double, double, Double);
829 LOCAL_VAR_ACCESSOR(bool, bool, Bool);
830 LOCAL_VAR_ACCESSOR(int, enum, Enum);
831 LOCAL_VAR_ACCESSOR(Message*, message, Message);
832 LOCAL_VAR_ACCESSOR(ArenaStringPtr, arena_string_ptr, ArenaStringPtr);
833 const std::string& GetString() const { return string_val; }
834 void SetString(const std::string& v) { string_val = v; }
835 Message* UnsafeGetMessage() const { return GetMessage(); }
836 void UnsafeSetMessage(Message* v) { SetMessage(v); }
837 void ClearOneofCase() {}
838
839 union {
840 int32_t type_int32;
841 int64_t type_int64;
842 uint32_t type_uint32;
843 uint64_t type_uint64;
844 float type_float;
845 double type_double;
846 bool type_bool;
847 int type_enum;
848 Message* type_message;
849 internal::ArenaStringPtr type_arena_string_ptr;
850 } oneof_val;
851
852 // std::string cannot be in union.
853 std::string string_val;
854 };
855
856 // Wraps a message pointer to read and write a field.
857 struct MessageWrapper {
858#define MESSAGE_FIELD_ACCESSOR(type, var, name) \
859 type Get##name() const { \
860 return reflection->GetField<type>(*message, field); \
861 } \
862 void Set##name(type v) { reflection->SetField<type>(message, field, v); }
863
864 MESSAGE_FIELD_ACCESSOR(int32_t, int32, Int32);
865 MESSAGE_FIELD_ACCESSOR(int64_t, int64, Int64);
866 MESSAGE_FIELD_ACCESSOR(uint32_t, uint32, Uint32);
867 MESSAGE_FIELD_ACCESSOR(uint64_t, uint64, Uint64);
868 MESSAGE_FIELD_ACCESSOR(float, float, Float);
869 MESSAGE_FIELD_ACCESSOR(double, double, Double);
870 MESSAGE_FIELD_ACCESSOR(bool, bool, Bool);
871 MESSAGE_FIELD_ACCESSOR(int, enum, Enum);
872 MESSAGE_FIELD_ACCESSOR(ArenaStringPtr, arena_string_ptr, ArenaStringPtr);
873 std::string GetString() const {
874 return reflection->GetString(message: *message, field);
875 }
876 void SetString(const std::string& v) {
877 reflection->SetString(message, field, value: v);
878 }
879 Message* GetMessage() const {
880 return reflection->ReleaseMessage(message, field);
881 }
882 void SetMessage(Message* v) {
883 reflection->SetAllocatedMessage(message, sub_message: v, field);
884 }
885 Message* UnsafeGetMessage() const {
886 return reflection->UnsafeArenaReleaseMessage(message, field);
887 }
888 void UnsafeSetMessage(Message* v) {
889 reflection->UnsafeArenaSetAllocatedMessage(message, sub_message: v, field);
890 }
891 void ClearOneofCase() {
892 *reflection->MutableOneofCase(message, oneof_descriptor: field->containing_oneof()) = 0;
893 }
894
895 const Reflection* reflection;
896 Message* message;
897 const FieldDescriptor* field;
898 };
899
900 GOOGLE_DCHECK(!oneof_descriptor->is_synthetic());
901 uint32_t oneof_case_lhs = GetOneofCase(message: *lhs, oneof_descriptor);
902 uint32_t oneof_case_rhs = GetOneofCase(message: *rhs, oneof_descriptor);
903
904 LocalVarWrapper temp;
905 MessageWrapper lhs_wrapper, rhs_wrapper;
906 const FieldDescriptor* field_lhs = nullptr;
907 OneofFieldMover<unsafe_shallow_swap> mover;
908 // lhs --> temp
909 if (oneof_case_lhs > 0) {
910 field_lhs = descriptor_->FindFieldByNumber(number: oneof_case_lhs);
911 lhs_wrapper = {this, lhs, field_lhs};
912 mover(field_lhs, &lhs_wrapper, &temp);
913 }
914 // rhs --> lhs
915 if (oneof_case_rhs > 0) {
916 const FieldDescriptor* f = descriptor_->FindFieldByNumber(number: oneof_case_rhs);
917 lhs_wrapper = {this, lhs, f};
918 rhs_wrapper = {this, rhs, f};
919 mover(f, &rhs_wrapper, &lhs_wrapper);
920 } else if (!unsafe_shallow_swap) {
921 ClearOneof(message: lhs, oneof_descriptor);
922 }
923 // temp --> rhs
924 if (oneof_case_lhs > 0) {
925 rhs_wrapper = {this, rhs, field_lhs};
926 mover(field_lhs, &temp, &rhs_wrapper);
927 } else if (!unsafe_shallow_swap) {
928 ClearOneof(message: rhs, oneof_descriptor);
929 }
930
931 if (unsafe_shallow_swap) {
932 *MutableOneofCase(message: lhs, oneof_descriptor) = oneof_case_rhs;
933 *MutableOneofCase(message: rhs, oneof_descriptor) = oneof_case_lhs;
934 }
935}
936
937void Reflection::Swap(Message* message1, Message* message2) const {
938 if (message1 == message2) return;
939
940 // TODO(kenton): Other Reflection methods should probably check this too.
941 GOOGLE_CHECK_EQ(message1->GetReflection(), this)
942 << "First argument to Swap() (of type \""
943 << message1->GetDescriptor()->full_name()
944 << "\") is not compatible with this reflection object (which is for type "
945 "\""
946 << descriptor_->full_name()
947 << "\"). Note that the exact same class is required; not just the same "
948 "descriptor.";
949 GOOGLE_CHECK_EQ(message2->GetReflection(), this)
950 << "Second argument to Swap() (of type \""
951 << message2->GetDescriptor()->full_name()
952 << "\") is not compatible with this reflection object (which is for type "
953 "\""
954 << descriptor_->full_name()
955 << "\"). Note that the exact same class is required; not just the same "
956 "descriptor.";
957
958 // Check that both messages are in the same arena (or both on the heap). We
959 // need to copy all data if not, due to ownership semantics.
960#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
961 if (message1->GetOwningArena() == nullptr ||
962 message1->GetOwningArena() != message2->GetOwningArena()) {
963#else // PROTOBUF_FORCE_COPY_IN_SWAP
964 if (message1->GetOwningArena() != message2->GetOwningArena()) {
965#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
966 // One of the two is guaranteed to have an arena. Switch things around
967 // to guarantee that message1 has an arena.
968 Arena* arena = message1->GetOwningArena();
969 if (arena == nullptr) {
970 arena = message2->GetOwningArena();
971 std::swap(a&: message1, b&: message2); // Swapping names for pointers!
972 }
973
974 Message* temp = message1->New(arena);
975 temp->MergeFrom(from: *message2);
976 message2->CopyFrom(from: *message1);
977#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
978 message1->CopyFrom(*temp);
979 if (arena == nullptr) delete temp;
980#else // PROTOBUF_FORCE_COPY_IN_SWAP
981 Swap(message1, message2: temp);
982#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
983 return;
984 }
985
986 GOOGLE_DCHECK_EQ(message1->GetOwningArena(), message2->GetOwningArena());
987
988 UnsafeArenaSwap(lhs: message1, rhs: message2);
989}
990
991template <bool unsafe_shallow_swap>
992void Reflection::SwapFieldsImpl(
993 Message* message1, Message* message2,
994 const std::vector<const FieldDescriptor*>& fields) const {
995 if (message1 == message2) return;
996
997 // TODO(kenton): Other Reflection methods should probably check this too.
998 GOOGLE_CHECK_EQ(message1->GetReflection(), this)
999 << "First argument to SwapFields() (of type \""
1000 << message1->GetDescriptor()->full_name()
1001 << "\") is not compatible with this reflection object (which is for type "
1002 "\""
1003 << descriptor_->full_name()
1004 << "\"). Note that the exact same class is required; not just the same "
1005 "descriptor.";
1006 GOOGLE_CHECK_EQ(message2->GetReflection(), this)
1007 << "Second argument to SwapFields() (of type \""
1008 << message2->GetDescriptor()->full_name()
1009 << "\") is not compatible with this reflection object (which is for type "
1010 "\""
1011 << descriptor_->full_name()
1012 << "\"). Note that the exact same class is required; not just the same "
1013 "descriptor.";
1014
1015 std::set<int> swapped_oneof;
1016
1017 GOOGLE_DCHECK(!unsafe_shallow_swap || message1->GetArenaForAllocation() ==
1018 message2->GetArenaForAllocation());
1019
1020 const Message* prototype =
1021 message_factory_->GetPrototype(type: message1->GetDescriptor());
1022 for (const auto* field : fields) {
1023 CheckInvalidAccess(schema: schema_, field);
1024 if (field->is_extension()) {
1025 if (unsafe_shallow_swap) {
1026 MutableExtensionSet(message: message1)->UnsafeShallowSwapExtension(
1027 other: MutableExtensionSet(message: message2), number: field->number());
1028 } else {
1029 MutableExtensionSet(message: message1)->SwapExtension(
1030 extendee: prototype, other: MutableExtensionSet(message: message2), number: field->number());
1031 }
1032 } else {
1033 if (schema_.InRealOneof(field)) {
1034 int oneof_index = field->containing_oneof()->index();
1035 // Only swap the oneof field once.
1036 if (swapped_oneof.find(x: oneof_index) != swapped_oneof.end()) {
1037 continue;
1038 }
1039 swapped_oneof.insert(x: oneof_index);
1040 SwapOneofField<unsafe_shallow_swap>(message1, message2,
1041 field->containing_oneof());
1042 } else {
1043 // Swap field.
1044 if (unsafe_shallow_swap) {
1045 UnsafeShallowSwapField(message1, message2, field);
1046 } else {
1047 SwapField(message1, message2, field);
1048 }
1049 // Swap has bit for non-repeated fields. We have already checked for
1050 // oneof already. This has to be done after SwapField, because SwapField
1051 // may depend on the information in has bits.
1052 if (!field->is_repeated()) {
1053 SwapBit(message1, message2, field);
1054 if (field->options().ctype() == FieldOptions::STRING &&
1055 IsInlined(field)) {
1056 GOOGLE_DCHECK(!unsafe_shallow_swap ||
1057 message1->GetArenaForAllocation() ==
1058 message2->GetArenaForAllocation());
1059 SwapInlinedStringDonated(lhs: message1, rhs: message2, field);
1060 }
1061 }
1062 }
1063 }
1064 }
1065}
1066
1067void Reflection::SwapFields(
1068 Message* message1, Message* message2,
1069 const std::vector<const FieldDescriptor*>& fields) const {
1070 SwapFieldsImpl<false>(message1, message2, fields);
1071}
1072
1073void Reflection::UnsafeShallowSwapFields(
1074 Message* message1, Message* message2,
1075 const std::vector<const FieldDescriptor*>& fields) const {
1076 SwapFieldsImpl<true>(message1, message2, fields);
1077}
1078
1079void Reflection::UnsafeArenaSwapFields(
1080 Message* lhs, Message* rhs,
1081 const std::vector<const FieldDescriptor*>& fields) const {
1082 GOOGLE_DCHECK_EQ(lhs->GetArenaForAllocation(), rhs->GetArenaForAllocation());
1083 UnsafeShallowSwapFields(message1: lhs, message2: rhs, fields);
1084}
1085
1086// -------------------------------------------------------------------
1087
1088bool Reflection::HasField(const Message& message,
1089 const FieldDescriptor* field) const {
1090 USAGE_CHECK_MESSAGE_TYPE(HasField);
1091 USAGE_CHECK_SINGULAR(HasField);
1092 CheckInvalidAccess(schema: schema_, field);
1093
1094 if (field->is_extension()) {
1095 return GetExtensionSet(message).Has(number: field->number());
1096 } else {
1097 if (schema_.InRealOneof(field)) {
1098 return HasOneofField(message, field);
1099 } else {
1100 return HasBit(message, field);
1101 }
1102 }
1103}
1104
1105void Reflection::UnsafeArenaSwap(Message* lhs, Message* rhs) const {
1106 if (lhs == rhs) return;
1107
1108 MutableInternalMetadata(message: lhs)->InternalSwap(other: MutableInternalMetadata(message: rhs));
1109
1110 for (int i = 0; i <= last_non_weak_field_index_; i++) {
1111 const FieldDescriptor* field = descriptor_->field(index: i);
1112 if (schema_.InRealOneof(field)) continue;
1113 if (schema_.IsFieldStripped(field)) continue;
1114 UnsafeShallowSwapField(message1: lhs, message2: rhs, field);
1115 }
1116 const int oneof_decl_count = descriptor_->oneof_decl_count();
1117 for (int i = 0; i < oneof_decl_count; i++) {
1118 const OneofDescriptor* oneof = descriptor_->oneof_decl(index: i);
1119 if (!oneof->is_synthetic()) {
1120 SwapOneofField<true>(lhs, rhs, oneof_descriptor: oneof);
1121 }
1122 }
1123
1124 // Swapping bits need to happen after swapping fields, because the latter may
1125 // depend on the has bit information.
1126 if (schema_.HasHasbits()) {
1127 uint32_t* lhs_has_bits = MutableHasBits(message: lhs);
1128 uint32_t* rhs_has_bits = MutableHasBits(message: rhs);
1129
1130 int fields_with_has_bits = 0;
1131 for (int i = 0; i < descriptor_->field_count(); i++) {
1132 const FieldDescriptor* field = descriptor_->field(index: i);
1133 if (field->is_repeated() || schema_.InRealOneof(field)) {
1134 continue;
1135 }
1136 fields_with_has_bits++;
1137 }
1138
1139 int has_bits_size = (fields_with_has_bits + 31) / 32;
1140
1141 for (int i = 0; i < has_bits_size; i++) {
1142 std::swap(a&: lhs_has_bits[i], b&: rhs_has_bits[i]);
1143 }
1144 }
1145
1146 if (schema_.HasInlinedString()) {
1147 uint32_t* lhs_donated_array = MutableInlinedStringDonatedArray(message: lhs);
1148 uint32_t* rhs_donated_array = MutableInlinedStringDonatedArray(message: rhs);
1149 int inlined_string_count = 0;
1150 for (int i = 0; i < descriptor_->field_count(); i++) {
1151 const FieldDescriptor* field = descriptor_->field(index: i);
1152 if (field->is_extension() || field->is_repeated() ||
1153 schema_.InRealOneof(field) ||
1154 field->options().ctype() != FieldOptions::STRING ||
1155 !IsInlined(field)) {
1156 continue;
1157 }
1158 inlined_string_count++;
1159 }
1160
1161 int donated_array_size = inlined_string_count == 0
1162 ? 0
1163 // One extra bit for the arena dtor tracking.
1164 : (inlined_string_count + 1 + 31) / 32;
1165 GOOGLE_CHECK_EQ((lhs_donated_array[0] & 0x1u) == 0,
1166 (rhs_donated_array[0] & 0x1u) == 0);
1167 for (int i = 0; i < donated_array_size; i++) {
1168 std::swap(a&: lhs_donated_array[i], b&: rhs_donated_array[i]);
1169 }
1170 }
1171
1172 if (schema_.HasExtensionSet()) {
1173 MutableExtensionSet(message: lhs)->InternalSwap(other: MutableExtensionSet(message: rhs));
1174 }
1175}
1176
1177int Reflection::FieldSize(const Message& message,
1178 const FieldDescriptor* field) const {
1179 USAGE_CHECK_MESSAGE_TYPE(FieldSize);
1180 USAGE_CHECK_REPEATED(FieldSize);
1181 CheckInvalidAccess(schema: schema_, field);
1182
1183 if (field->is_extension()) {
1184 return GetExtensionSet(message).ExtensionSize(number: field->number());
1185 } else {
1186 switch (field->cpp_type()) {
1187#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1188 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
1189 return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
1190
1191 HANDLE_TYPE(INT32, int32_t);
1192 HANDLE_TYPE(INT64, int64_t);
1193 HANDLE_TYPE(UINT32, uint32_t);
1194 HANDLE_TYPE(UINT64, uint64_t);
1195 HANDLE_TYPE(DOUBLE, double);
1196 HANDLE_TYPE(FLOAT, float);
1197 HANDLE_TYPE(BOOL, bool);
1198 HANDLE_TYPE(ENUM, int);
1199#undef HANDLE_TYPE
1200
1201 case FieldDescriptor::CPPTYPE_STRING:
1202 case FieldDescriptor::CPPTYPE_MESSAGE:
1203 if (IsMapFieldInApi(field)) {
1204 const internal::MapFieldBase& map =
1205 GetRaw<MapFieldBase>(message, field);
1206 if (map.IsRepeatedFieldValid()) {
1207 return map.GetRepeatedField().size();
1208 } else {
1209 // No need to materialize the repeated field if it is out of sync:
1210 // its size will be the same as the map's size.
1211 return map.size();
1212 }
1213 } else {
1214 return GetRaw<RepeatedPtrFieldBase>(message, field).size();
1215 }
1216 }
1217
1218 GOOGLE_LOG(FATAL) << "Can't get here.";
1219 return 0;
1220 }
1221}
1222
1223void Reflection::ClearField(Message* message,
1224 const FieldDescriptor* field) const {
1225 USAGE_CHECK_MESSAGE_TYPE(ClearField);
1226 CheckInvalidAccess(schema: schema_, field);
1227
1228 if (field->is_extension()) {
1229 MutableExtensionSet(message)->ClearExtension(number: field->number());
1230 } else if (!field->is_repeated()) {
1231 if (schema_.InRealOneof(field)) {
1232 ClearOneofField(message, field);
1233 return;
1234 }
1235 if (HasBit(message: *message, field)) {
1236 ClearBit(message, field);
1237
1238 // We need to set the field back to its default value.
1239 switch (field->cpp_type()) {
1240#define CLEAR_TYPE(CPPTYPE, TYPE) \
1241 case FieldDescriptor::CPPTYPE_##CPPTYPE: \
1242 *MutableRaw<TYPE>(message, field) = field->default_value_##TYPE(); \
1243 break;
1244
1245 CLEAR_TYPE(INT32, int32_t);
1246 CLEAR_TYPE(INT64, int64_t);
1247 CLEAR_TYPE(UINT32, uint32_t);
1248 CLEAR_TYPE(UINT64, uint64_t);
1249 CLEAR_TYPE(FLOAT, float);
1250 CLEAR_TYPE(DOUBLE, double);
1251 CLEAR_TYPE(BOOL, bool);
1252#undef CLEAR_TYPE
1253
1254 case FieldDescriptor::CPPTYPE_ENUM:
1255 *MutableRaw<int>(message, field) =
1256 field->default_value_enum()->number();
1257 break;
1258
1259 case FieldDescriptor::CPPTYPE_STRING: {
1260 switch (field->options().ctype()) {
1261 default: // TODO(kenton): Support other string reps.
1262 case FieldOptions::STRING:
1263 if (IsInlined(field)) {
1264 // Currently, string with default value can't be inlined. So we
1265 // don't have to handle default value here.
1266 MutableRaw<InlinedStringField>(message, field)->ClearToEmpty();
1267 } else {
1268 auto* str = MutableRaw<ArenaStringPtr>(message, field);
1269 str->Destroy();
1270 str->InitDefault();
1271 }
1272 break;
1273 }
1274 break;
1275 }
1276
1277 case FieldDescriptor::CPPTYPE_MESSAGE:
1278 if (schema_.HasBitIndex(field) == static_cast<uint32_t>(-1)) {
1279 // Proto3 does not have has-bits and we need to set a message field
1280 // to nullptr in order to indicate its un-presence.
1281 if (message->GetArenaForAllocation() == nullptr) {
1282 delete *MutableRaw<Message*>(message, field);
1283 }
1284 *MutableRaw<Message*>(message, field) = nullptr;
1285 } else {
1286 (*MutableRaw<Message*>(message, field))->Clear();
1287 }
1288 break;
1289 }
1290 }
1291 } else {
1292 switch (field->cpp_type()) {
1293#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1294 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
1295 MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear(); \
1296 break
1297
1298 HANDLE_TYPE(INT32, int32_t);
1299 HANDLE_TYPE(INT64, int64_t);
1300 HANDLE_TYPE(UINT32, uint32_t);
1301 HANDLE_TYPE(UINT64, uint64_t);
1302 HANDLE_TYPE(DOUBLE, double);
1303 HANDLE_TYPE(FLOAT, float);
1304 HANDLE_TYPE(BOOL, bool);
1305 HANDLE_TYPE(ENUM, int);
1306#undef HANDLE_TYPE
1307
1308 case FieldDescriptor::CPPTYPE_STRING: {
1309 switch (field->options().ctype()) {
1310 default: // TODO(kenton): Support other string reps.
1311 case FieldOptions::STRING:
1312 MutableRaw<RepeatedPtrField<std::string> >(message, field)->Clear();
1313 break;
1314 }
1315 break;
1316 }
1317
1318 case FieldDescriptor::CPPTYPE_MESSAGE: {
1319 if (IsMapFieldInApi(field)) {
1320 MutableRaw<MapFieldBase>(message, field)->Clear();
1321 } else {
1322 // We don't know which subclass of RepeatedPtrFieldBase the type is,
1323 // so we use RepeatedPtrFieldBase directly.
1324 MutableRaw<RepeatedPtrFieldBase>(message, field)
1325 ->Clear<GenericTypeHandler<Message> >();
1326 }
1327 break;
1328 }
1329 }
1330 }
1331}
1332
1333void Reflection::RemoveLast(Message* message,
1334 const FieldDescriptor* field) const {
1335 USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
1336 USAGE_CHECK_REPEATED(RemoveLast);
1337 CheckInvalidAccess(schema: schema_, field);
1338
1339 if (field->is_extension()) {
1340 MutableExtensionSet(message)->RemoveLast(number: field->number());
1341 } else {
1342 switch (field->cpp_type()) {
1343#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1344 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
1345 MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast(); \
1346 break
1347
1348 HANDLE_TYPE(INT32, int32_t);
1349 HANDLE_TYPE(INT64, int64_t);
1350 HANDLE_TYPE(UINT32, uint32_t);
1351 HANDLE_TYPE(UINT64, uint64_t);
1352 HANDLE_TYPE(DOUBLE, double);
1353 HANDLE_TYPE(FLOAT, float);
1354 HANDLE_TYPE(BOOL, bool);
1355 HANDLE_TYPE(ENUM, int);
1356#undef HANDLE_TYPE
1357
1358 case FieldDescriptor::CPPTYPE_STRING:
1359 switch (field->options().ctype()) {
1360 default: // TODO(kenton): Support other string reps.
1361 case FieldOptions::STRING:
1362 MutableRaw<RepeatedPtrField<std::string> >(message, field)
1363 ->RemoveLast();
1364 break;
1365 }
1366 break;
1367
1368 case FieldDescriptor::CPPTYPE_MESSAGE:
1369 if (IsMapFieldInApi(field)) {
1370 MutableRaw<MapFieldBase>(message, field)
1371 ->MutableRepeatedField()
1372 ->RemoveLast<GenericTypeHandler<Message> >();
1373 } else {
1374 MutableRaw<RepeatedPtrFieldBase>(message, field)
1375 ->RemoveLast<GenericTypeHandler<Message> >();
1376 }
1377 break;
1378 }
1379 }
1380}
1381
1382Message* Reflection::ReleaseLast(Message* message,
1383 const FieldDescriptor* field) const {
1384 USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
1385 CheckInvalidAccess(schema: schema_, field);
1386
1387 Message* released;
1388 if (field->is_extension()) {
1389 released = static_cast<Message*>(
1390 MutableExtensionSet(message)->ReleaseLast(number: field->number()));
1391 } else {
1392 if (IsMapFieldInApi(field)) {
1393 released = MutableRaw<MapFieldBase>(message, field)
1394 ->MutableRepeatedField()
1395 ->ReleaseLast<GenericTypeHandler<Message>>();
1396 } else {
1397 released = MutableRaw<RepeatedPtrFieldBase>(message, field)
1398 ->ReleaseLast<GenericTypeHandler<Message>>();
1399 }
1400 }
1401#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
1402 return MaybeForceCopy(message->GetArenaForAllocation(), released);
1403#else // PROTOBUF_FORCE_COPY_IN_RELEASE
1404 return released;
1405#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE
1406}
1407
1408Message* Reflection::UnsafeArenaReleaseLast(
1409 Message* message, const FieldDescriptor* field) const {
1410 USAGE_CHECK_ALL(UnsafeArenaReleaseLast, REPEATED, MESSAGE);
1411 CheckInvalidAccess(schema: schema_, field);
1412
1413 if (field->is_extension()) {
1414 return static_cast<Message*>(
1415 MutableExtensionSet(message)->UnsafeArenaReleaseLast(number: field->number()));
1416 } else {
1417 if (IsMapFieldInApi(field)) {
1418 return MutableRaw<MapFieldBase>(message, field)
1419 ->MutableRepeatedField()
1420 ->UnsafeArenaReleaseLast<GenericTypeHandler<Message>>();
1421 } else {
1422 return MutableRaw<RepeatedPtrFieldBase>(message, field)
1423 ->UnsafeArenaReleaseLast<GenericTypeHandler<Message>>();
1424 }
1425 }
1426}
1427
1428void Reflection::SwapElements(Message* message, const FieldDescriptor* field,
1429 int index1, int index2) const {
1430 USAGE_CHECK_MESSAGE_TYPE(Swap);
1431 USAGE_CHECK_REPEATED(Swap);
1432 CheckInvalidAccess(schema: schema_, field);
1433
1434 if (field->is_extension()) {
1435 MutableExtensionSet(message)->SwapElements(number: field->number(), index1, index2);
1436 } else {
1437 switch (field->cpp_type()) {
1438#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1439 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
1440 MutableRaw<RepeatedField<LOWERCASE> >(message, field) \
1441 ->SwapElements(index1, index2); \
1442 break
1443
1444 HANDLE_TYPE(INT32, int32_t);
1445 HANDLE_TYPE(INT64, int64_t);
1446 HANDLE_TYPE(UINT32, uint32_t);
1447 HANDLE_TYPE(UINT64, uint64_t);
1448 HANDLE_TYPE(DOUBLE, double);
1449 HANDLE_TYPE(FLOAT, float);
1450 HANDLE_TYPE(BOOL, bool);
1451 HANDLE_TYPE(ENUM, int);
1452#undef HANDLE_TYPE
1453
1454 case FieldDescriptor::CPPTYPE_STRING:
1455 case FieldDescriptor::CPPTYPE_MESSAGE:
1456 if (IsMapFieldInApi(field)) {
1457 MutableRaw<MapFieldBase>(message, field)
1458 ->MutableRepeatedField()
1459 ->SwapElements(index1, index2);
1460 } else {
1461 MutableRaw<RepeatedPtrFieldBase>(message, field)
1462 ->SwapElements(index1, index2);
1463 }
1464 break;
1465 }
1466 }
1467}
1468
1469namespace {
1470// Comparison functor for sorting FieldDescriptors by field number.
1471struct FieldNumberSorter {
1472 bool operator()(const FieldDescriptor* left,
1473 const FieldDescriptor* right) const {
1474 return left->number() < right->number();
1475 }
1476};
1477
1478bool IsIndexInHasBitSet(const uint32_t* has_bit_set, uint32_t has_bit_index) {
1479 GOOGLE_DCHECK_NE(has_bit_index, ~0u);
1480 return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) &
1481 static_cast<uint32_t>(1)) != 0;
1482}
1483
1484bool CreateUnknownEnumValues(const FileDescriptor* file) {
1485 return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
1486}
1487} // namespace
1488
1489namespace internal {
1490bool CreateUnknownEnumValues(const FieldDescriptor* field) {
1491 bool open_enum = false;
1492 return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || open_enum;
1493}
1494} // namespace internal
1495using internal::CreateUnknownEnumValues;
1496
1497void Reflection::ListFieldsMayFailOnStripped(
1498 const Message& message, bool should_fail,
1499 std::vector<const FieldDescriptor*>* output) const {
1500 output->clear();
1501
1502 // Optimization: The default instance never has any fields set.
1503 if (schema_.IsDefaultInstance(message)) return;
1504
1505 // Optimization: Avoid calling GetHasBits() and HasOneofField() many times
1506 // within the field loop. We allow this violation of ReflectionSchema
1507 // encapsulation because this function takes a noticeable about of CPU
1508 // fleetwide and properly allowing this optimization through public interfaces
1509 // seems more trouble than it is worth.
1510 const uint32_t* const has_bits =
1511 schema_.HasHasbits() ? GetHasBits(message) : nullptr;
1512 const uint32_t* const has_bits_indices = schema_.has_bit_indices_;
1513 output->reserve(n: descriptor_->field_count());
1514 const int last_non_weak_field_index = last_non_weak_field_index_;
1515 for (int i = 0; i <= last_non_weak_field_index; i++) {
1516 const FieldDescriptor* field = descriptor_->field(index: i);
1517 if (!should_fail && schema_.IsFieldStripped(field)) {
1518 continue;
1519 }
1520 if (field->is_repeated()) {
1521 if (FieldSize(message, field) > 0) {
1522 output->push_back(x: field);
1523 }
1524 } else {
1525 const OneofDescriptor* containing_oneof = field->containing_oneof();
1526 if (schema_.InRealOneof(field)) {
1527 const uint32_t* const oneof_case_array =
1528 GetConstPointerAtOffset<uint32_t>(message: &message,
1529 offset: schema_.oneof_case_offset_);
1530 // Equivalent to: HasOneofField(message, field)
1531 if (static_cast<int64_t>(oneof_case_array[containing_oneof->index()]) ==
1532 field->number()) {
1533 output->push_back(x: field);
1534 }
1535 } else if (has_bits && has_bits_indices[i] != static_cast<uint32_t>(-1)) {
1536 CheckInvalidAccess(schema: schema_, field);
1537 // Equivalent to: HasBit(message, field)
1538 if (IsIndexInHasBitSet(has_bit_set: has_bits, has_bit_index: has_bits_indices[i])) {
1539 output->push_back(x: field);
1540 }
1541 } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit.
1542 output->push_back(x: field);
1543 }
1544 }
1545 }
1546 if (schema_.HasExtensionSet()) {
1547 GetExtensionSet(message).AppendToList(extendee: descriptor_, pool: descriptor_pool_,
1548 output);
1549 }
1550
1551 // ListFields() must sort output by field number.
1552 std::sort(first: output->begin(), last: output->end(), comp: FieldNumberSorter());
1553}
1554
1555void Reflection::ListFields(const Message& message,
1556 std::vector<const FieldDescriptor*>* output) const {
1557 ListFieldsMayFailOnStripped(message, should_fail: true, output);
1558}
1559
1560void Reflection::ListFieldsOmitStripped(
1561 const Message& message, std::vector<const FieldDescriptor*>* output) const {
1562 ListFieldsMayFailOnStripped(message, should_fail: false, output);
1563}
1564
1565// -------------------------------------------------------------------
1566
1567#undef DEFINE_PRIMITIVE_ACCESSORS
1568#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
1569 PASSTYPE Reflection::Get##TYPENAME(const Message& message, \
1570 const FieldDescriptor* field) const { \
1571 USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
1572 if (field->is_extension()) { \
1573 return GetExtensionSet(message).Get##TYPENAME( \
1574 field->number(), field->default_value_##PASSTYPE()); \
1575 } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { \
1576 return field->default_value_##PASSTYPE(); \
1577 } else { \
1578 return GetField<TYPE>(message, field); \
1579 } \
1580 } \
1581 \
1582 void Reflection::Set##TYPENAME( \
1583 Message* message, const FieldDescriptor* field, PASSTYPE value) const { \
1584 USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
1585 if (field->is_extension()) { \
1586 return MutableExtensionSet(message)->Set##TYPENAME( \
1587 field->number(), field->type(), value, field); \
1588 } else { \
1589 SetField<TYPE>(message, field, value); \
1590 } \
1591 } \
1592 \
1593 PASSTYPE Reflection::GetRepeated##TYPENAME( \
1594 const Message& message, const FieldDescriptor* field, int index) const { \
1595 USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
1596 if (field->is_extension()) { \
1597 return GetExtensionSet(message).GetRepeated##TYPENAME(field->number(), \
1598 index); \
1599 } else { \
1600 return GetRepeatedField<TYPE>(message, field, index); \
1601 } \
1602 } \
1603 \
1604 void Reflection::SetRepeated##TYPENAME(Message* message, \
1605 const FieldDescriptor* field, \
1606 int index, PASSTYPE value) const { \
1607 USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
1608 if (field->is_extension()) { \
1609 MutableExtensionSet(message)->SetRepeated##TYPENAME(field->number(), \
1610 index, value); \
1611 } else { \
1612 SetRepeatedField<TYPE>(message, field, index, value); \
1613 } \
1614 } \
1615 \
1616 void Reflection::Add##TYPENAME( \
1617 Message* message, const FieldDescriptor* field, PASSTYPE value) const { \
1618 USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
1619 if (field->is_extension()) { \
1620 MutableExtensionSet(message)->Add##TYPENAME( \
1621 field->number(), field->type(), field->options().packed(), value, \
1622 field); \
1623 } else { \
1624 AddField<TYPE>(message, field, value); \
1625 } \
1626 }
1627
1628DEFINE_PRIMITIVE_ACCESSORS(Int32, int32_t, int32_t, INT32)
1629DEFINE_PRIMITIVE_ACCESSORS(Int64, int64_t, int64_t, INT64)
1630DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32_t, uint32_t, UINT32)
1631DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64_t, uint64_t, UINT64)
1632DEFINE_PRIMITIVE_ACCESSORS(Float, float, float, FLOAT)
1633DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
1634DEFINE_PRIMITIVE_ACCESSORS(Bool, bool, bool, BOOL)
1635#undef DEFINE_PRIMITIVE_ACCESSORS
1636
1637// -------------------------------------------------------------------
1638
1639std::string Reflection::GetString(const Message& message,
1640 const FieldDescriptor* field) const {
1641 USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
1642 if (field->is_extension()) {
1643 return GetExtensionSet(message).GetString(number: field->number(),
1644 default_value: field->default_value_string());
1645 } else {
1646 if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
1647 return field->default_value_string();
1648 }
1649 switch (field->options().ctype()) {
1650 default: // TODO(kenton): Support other string reps.
1651 case FieldOptions::STRING:
1652 if (IsInlined(field)) {
1653 return GetField<InlinedStringField>(message, field).GetNoArena();
1654 } else {
1655 const auto& str = GetField<ArenaStringPtr>(message, field);
1656 return str.IsDefault() ? field->default_value_string() : str.Get();
1657 }
1658 }
1659 }
1660}
1661
1662const std::string& Reflection::GetStringReference(const Message& message,
1663 const FieldDescriptor* field,
1664 std::string* scratch) const {
1665 (void)scratch; // Parameter is used by Google-internal code.
1666 USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
1667 if (field->is_extension()) {
1668 return GetExtensionSet(message).GetString(number: field->number(),
1669 default_value: field->default_value_string());
1670 } else {
1671 if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
1672 return field->default_value_string();
1673 }
1674 switch (field->options().ctype()) {
1675 default: // TODO(kenton): Support other string reps.
1676 case FieldOptions::STRING:
1677 if (IsInlined(field)) {
1678 return GetField<InlinedStringField>(message, field).GetNoArena();
1679 } else {
1680 const auto& str = GetField<ArenaStringPtr>(message, field);
1681 return str.IsDefault() ? field->default_value_string() : str.Get();
1682 }
1683 }
1684 }
1685}
1686
1687
1688void Reflection::SetString(Message* message, const FieldDescriptor* field,
1689 std::string value) const {
1690 USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
1691 if (field->is_extension()) {
1692 return MutableExtensionSet(message)->SetString(
1693 number: field->number(), type: field->type(), value: std::move(value), descriptor: field);
1694 } else {
1695 switch (field->options().ctype()) {
1696 default: // TODO(kenton): Support other string reps.
1697 case FieldOptions::STRING: {
1698 if (IsInlined(field)) {
1699 const uint32_t index = schema_.InlinedStringIndex(field);
1700 GOOGLE_DCHECK_GT(index, 0);
1701 uint32_t* states =
1702 &MutableInlinedStringDonatedArray(message)[index / 32];
1703 uint32_t mask = ~(static_cast<uint32_t>(1) << (index % 32));
1704 MutableField<InlinedStringField>(message, field)
1705 ->Set(value, arena: message->GetArenaForAllocation(),
1706 donated: IsInlinedStringDonated(message: *message, field), states, mask,
1707 message);
1708 break;
1709 }
1710
1711 // Oneof string fields are never set as a default instance.
1712 // We just need to pass some arbitrary default string to make it work.
1713 // This allows us to not have the real default accessible from
1714 // reflection.
1715 if (schema_.InRealOneof(field) && !HasOneofField(message: *message, field)) {
1716 ClearOneof(message, oneof_descriptor: field->containing_oneof());
1717 MutableField<ArenaStringPtr>(message, field)->InitDefault();
1718 }
1719 MutableField<ArenaStringPtr>(message, field)
1720 ->Set(value: std::move(value), arena: message->GetArenaForAllocation());
1721 break;
1722 }
1723 }
1724 }
1725}
1726
1727
1728std::string Reflection::GetRepeatedString(const Message& message,
1729 const FieldDescriptor* field,
1730 int index) const {
1731 USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
1732 if (field->is_extension()) {
1733 return GetExtensionSet(message).GetRepeatedString(number: field->number(), index);
1734 } else {
1735 switch (field->options().ctype()) {
1736 default: // TODO(kenton): Support other string reps.
1737 case FieldOptions::STRING:
1738 return GetRepeatedPtrField<std::string>(message, field, index);
1739 }
1740 }
1741}
1742
1743const std::string& Reflection::GetRepeatedStringReference(
1744 const Message& message, const FieldDescriptor* field, int index,
1745 std::string* scratch) const {
1746 (void)scratch; // Parameter is used by Google-internal code.
1747 USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
1748 if (field->is_extension()) {
1749 return GetExtensionSet(message).GetRepeatedString(number: field->number(), index);
1750 } else {
1751 switch (field->options().ctype()) {
1752 default: // TODO(kenton): Support other string reps.
1753 case FieldOptions::STRING:
1754 return GetRepeatedPtrField<std::string>(message, field, index);
1755 }
1756 }
1757}
1758
1759
1760void Reflection::SetRepeatedString(Message* message,
1761 const FieldDescriptor* field, int index,
1762 std::string value) const {
1763 USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
1764 if (field->is_extension()) {
1765 MutableExtensionSet(message)->SetRepeatedString(number: field->number(), index,
1766 value: std::move(value));
1767 } else {
1768 switch (field->options().ctype()) {
1769 default: // TODO(kenton): Support other string reps.
1770 case FieldOptions::STRING:
1771 MutableRepeatedField<std::string>(message, field, index)
1772 ->assign(str: std::move(value));
1773 break;
1774 }
1775 }
1776}
1777
1778
1779void Reflection::AddString(Message* message, const FieldDescriptor* field,
1780 std::string value) const {
1781 USAGE_CHECK_ALL(AddString, REPEATED, STRING);
1782 if (field->is_extension()) {
1783 MutableExtensionSet(message)->AddString(number: field->number(), type: field->type(),
1784 value: std::move(value), descriptor: field);
1785 } else {
1786 switch (field->options().ctype()) {
1787 default: // TODO(kenton): Support other string reps.
1788 case FieldOptions::STRING:
1789 AddField<std::string>(message, field)->assign(str: std::move(value));
1790 break;
1791 }
1792 }
1793}
1794
1795
1796// -------------------------------------------------------------------
1797
1798const EnumValueDescriptor* Reflection::GetEnum(
1799 const Message& message, const FieldDescriptor* field) const {
1800 // Usage checked by GetEnumValue.
1801 int value = GetEnumValue(message, field);
1802 return field->enum_type()->FindValueByNumberCreatingIfUnknown(number: value);
1803}
1804
1805int Reflection::GetEnumValue(const Message& message,
1806 const FieldDescriptor* field) const {
1807 USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
1808
1809 int32_t value;
1810 if (field->is_extension()) {
1811 value = GetExtensionSet(message).GetEnum(
1812 number: field->number(), default_value: field->default_value_enum()->number());
1813 } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
1814 value = field->default_value_enum()->number();
1815 } else {
1816 value = GetField<int>(message, field);
1817 }
1818 return value;
1819}
1820
1821void Reflection::SetEnum(Message* message, const FieldDescriptor* field,
1822 const EnumValueDescriptor* value) const {
1823 // Usage checked by SetEnumValue.
1824 USAGE_CHECK_ENUM_VALUE(SetEnum);
1825 SetEnumValueInternal(message, field, value: value->number());
1826}
1827
1828void Reflection::SetEnumValue(Message* message, const FieldDescriptor* field,
1829 int value) const {
1830 USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
1831 if (!CreateUnknownEnumValues(field)) {
1832 // Check that the value is valid if we don't support direct storage of
1833 // unknown enum values.
1834 const EnumValueDescriptor* value_desc =
1835 field->enum_type()->FindValueByNumber(number: value);
1836 if (value_desc == nullptr) {
1837 MutableUnknownFields(message)->AddVarint(number: field->number(), value);
1838 return;
1839 }
1840 }
1841 SetEnumValueInternal(message, field, value);
1842}
1843
1844void Reflection::SetEnumValueInternal(Message* message,
1845 const FieldDescriptor* field,
1846 int value) const {
1847 if (field->is_extension()) {
1848 MutableExtensionSet(message)->SetEnum(number: field->number(), type: field->type(), value,
1849 descriptor: field);
1850 } else {
1851 SetField<int>(message, field, value);
1852 }
1853}
1854
1855const EnumValueDescriptor* Reflection::GetRepeatedEnum(
1856 const Message& message, const FieldDescriptor* field, int index) const {
1857 // Usage checked by GetRepeatedEnumValue.
1858 int value = GetRepeatedEnumValue(message, field, index);
1859 return field->enum_type()->FindValueByNumberCreatingIfUnknown(number: value);
1860}
1861
1862int Reflection::GetRepeatedEnumValue(const Message& message,
1863 const FieldDescriptor* field,
1864 int index) const {
1865 USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
1866
1867 int value;
1868 if (field->is_extension()) {
1869 value = GetExtensionSet(message).GetRepeatedEnum(number: field->number(), index);
1870 } else {
1871 value = GetRepeatedField<int>(message, field, index);
1872 }
1873 return value;
1874}
1875
1876void Reflection::SetRepeatedEnum(Message* message, const FieldDescriptor* field,
1877 int index,
1878 const EnumValueDescriptor* value) const {
1879 // Usage checked by SetRepeatedEnumValue.
1880 USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
1881 SetRepeatedEnumValueInternal(message, field, index, value: value->number());
1882}
1883
1884void Reflection::SetRepeatedEnumValue(Message* message,
1885 const FieldDescriptor* field, int index,
1886 int value) const {
1887 USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
1888 if (!CreateUnknownEnumValues(field)) {
1889 // Check that the value is valid if we don't support direct storage of
1890 // unknown enum values.
1891 const EnumValueDescriptor* value_desc =
1892 field->enum_type()->FindValueByNumber(number: value);
1893 if (value_desc == nullptr) {
1894 MutableUnknownFields(message)->AddVarint(number: field->number(), value);
1895 return;
1896 }
1897 }
1898 SetRepeatedEnumValueInternal(message, field, index, value);
1899}
1900
1901void Reflection::SetRepeatedEnumValueInternal(Message* message,
1902 const FieldDescriptor* field,
1903 int index, int value) const {
1904 if (field->is_extension()) {
1905 MutableExtensionSet(message)->SetRepeatedEnum(number: field->number(), index,
1906 value);
1907 } else {
1908 SetRepeatedField<int>(message, field, index, value);
1909 }
1910}
1911
1912void Reflection::AddEnum(Message* message, const FieldDescriptor* field,
1913 const EnumValueDescriptor* value) const {
1914 // Usage checked by AddEnumValue.
1915 USAGE_CHECK_ENUM_VALUE(AddEnum);
1916 AddEnumValueInternal(message, field, value: value->number());
1917}
1918
1919void Reflection::AddEnumValue(Message* message, const FieldDescriptor* field,
1920 int value) const {
1921 USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
1922 if (!CreateUnknownEnumValues(field)) {
1923 // Check that the value is valid if we don't support direct storage of
1924 // unknown enum values.
1925 const EnumValueDescriptor* value_desc =
1926 field->enum_type()->FindValueByNumber(number: value);
1927 if (value_desc == nullptr) {
1928 MutableUnknownFields(message)->AddVarint(number: field->number(), value);
1929 return;
1930 }
1931 }
1932 AddEnumValueInternal(message, field, value);
1933}
1934
1935void Reflection::AddEnumValueInternal(Message* message,
1936 const FieldDescriptor* field,
1937 int value) const {
1938 if (field->is_extension()) {
1939 MutableExtensionSet(message)->AddEnum(number: field->number(), type: field->type(),
1940 packed: field->options().packed(), value,
1941 descriptor: field);
1942 } else {
1943 AddField<int>(message, field, value);
1944 }
1945}
1946
1947// -------------------------------------------------------------------
1948
1949const Message* Reflection::GetDefaultMessageInstance(
1950 const FieldDescriptor* field) const {
1951 // If we are using the generated factory, we cache the prototype in the field
1952 // descriptor for faster access.
1953 // The default instances of generated messages are not cross-linked, which
1954 // means they contain null pointers on their message fields and can't be used
1955 // to get the default of submessages.
1956 if (message_factory_ == MessageFactory::generated_factory()) {
1957 auto& ptr = field->default_generated_instance_;
1958 auto* res = ptr.load(m: std::memory_order_acquire);
1959 if (res == nullptr) {
1960 // First time asking for this field's default. Load it and cache it.
1961 res = message_factory_->GetPrototype(type: field->message_type());
1962 ptr.store(p: res, m: std::memory_order_release);
1963 }
1964 return res;
1965 }
1966
1967 // For other factories, we try the default's object field.
1968 // In particular, the DynamicMessageFactory will cross link the default
1969 // instances to allow for this. But only do this for real fields.
1970 // This is an optimization to avoid going to GetPrototype() below, as that
1971 // requires a lock and a map lookup.
1972 if (!field->is_extension() && !field->options().weak() &&
1973 !IsLazyField(field) && !schema_.InRealOneof(field)) {
1974 auto* res = DefaultRaw<const Message*>(field);
1975 if (res != nullptr) {
1976 return res;
1977 }
1978 }
1979 // Otherwise, just go to the factory.
1980 return message_factory_->GetPrototype(type: field->message_type());
1981}
1982
1983const Message& Reflection::GetMessage(const Message& message,
1984 const FieldDescriptor* field,
1985 MessageFactory* factory) const {
1986 USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
1987 CheckInvalidAccess(schema: schema_, field);
1988
1989 if (factory == nullptr) factory = message_factory_;
1990
1991 if (field->is_extension()) {
1992 return static_cast<const Message&>(GetExtensionSet(message).GetMessage(
1993 number: field->number(), message_type: field->message_type(), factory));
1994 } else {
1995 if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
1996 return *GetDefaultMessageInstance(field);
1997 }
1998 const Message* result = GetRaw<const Message*>(message, field);
1999 if (result == nullptr) {
2000 result = GetDefaultMessageInstance(field);
2001 }
2002 return *result;
2003 }
2004}
2005
2006Message* Reflection::MutableMessage(Message* message,
2007 const FieldDescriptor* field,
2008 MessageFactory* factory) const {
2009 USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
2010 CheckInvalidAccess(schema: schema_, field);
2011
2012 if (factory == nullptr) factory = message_factory_;
2013
2014 if (field->is_extension()) {
2015 return static_cast<Message*>(
2016 MutableExtensionSet(message)->MutableMessage(descriptor: field, factory));
2017 } else {
2018 Message* result;
2019
2020 Message** result_holder = MutableRaw<Message*>(message, field);
2021
2022 if (schema_.InRealOneof(field)) {
2023 if (!HasOneofField(message: *message, field)) {
2024 ClearOneof(message, oneof_descriptor: field->containing_oneof());
2025 result_holder = MutableField<Message*>(message, field);
2026 const Message* default_message = GetDefaultMessageInstance(field);
2027 *result_holder = default_message->New(arena: message->GetArenaForAllocation());
2028 }
2029 } else {
2030 SetBit(message, field);
2031 }
2032
2033 if (*result_holder == nullptr) {
2034 const Message* default_message = GetDefaultMessageInstance(field);
2035 *result_holder = default_message->New(arena: message->GetArenaForAllocation());
2036 }
2037 result = *result_holder;
2038 return result;
2039 }
2040}
2041
2042void Reflection::UnsafeArenaSetAllocatedMessage(
2043 Message* message, Message* sub_message,
2044 const FieldDescriptor* field) const {
2045 USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
2046 CheckInvalidAccess(schema: schema_, field);
2047
2048
2049 if (field->is_extension()) {
2050 MutableExtensionSet(message)->UnsafeArenaSetAllocatedMessage(
2051 number: field->number(), type: field->type(), descriptor: field, message: sub_message);
2052 } else {
2053 if (schema_.InRealOneof(field)) {
2054 if (sub_message == nullptr) {
2055 ClearOneof(message, oneof_descriptor: field->containing_oneof());
2056 return;
2057 }
2058 ClearOneof(message, oneof_descriptor: field->containing_oneof());
2059 *MutableRaw<Message*>(message, field) = sub_message;
2060 SetOneofCase(message, field);
2061 return;
2062 }
2063
2064 if (sub_message == nullptr) {
2065 ClearBit(message, field);
2066 } else {
2067 SetBit(message, field);
2068 }
2069 Message** sub_message_holder = MutableRaw<Message*>(message, field);
2070 if (message->GetArenaForAllocation() == nullptr) {
2071 delete *sub_message_holder;
2072 }
2073 *sub_message_holder = sub_message;
2074 }
2075}
2076
2077void Reflection::SetAllocatedMessage(Message* message, Message* sub_message,
2078 const FieldDescriptor* field) const {
2079 GOOGLE_DCHECK(sub_message == nullptr || sub_message->GetOwningArena() == nullptr ||
2080 sub_message->GetOwningArena() == message->GetArenaForAllocation());
2081 CheckInvalidAccess(schema: schema_, field);
2082
2083 // If message and sub-message are in different memory ownership domains
2084 // (different arenas, or one is on heap and one is not), then we may need to
2085 // do a copy.
2086 if (sub_message != nullptr &&
2087 sub_message->GetOwningArena() != message->GetArenaForAllocation()) {
2088 if (sub_message->GetOwningArena() == nullptr &&
2089 message->GetArenaForAllocation() != nullptr) {
2090 // Case 1: parent is on an arena and child is heap-allocated. We can add
2091 // the child to the arena's Own() list to free on arena destruction, then
2092 // set our pointer.
2093 message->GetArenaForAllocation()->Own(object: sub_message);
2094 UnsafeArenaSetAllocatedMessage(message, sub_message, field);
2095 } else {
2096 // Case 2: all other cases. We need to make a copy. MutableMessage() will
2097 // either get the existing message object, or instantiate a new one as
2098 // appropriate w.r.t. our arena.
2099 Message* sub_message_copy = MutableMessage(message, field);
2100 sub_message_copy->CopyFrom(from: *sub_message);
2101 }
2102 } else {
2103 // Same memory ownership domains.
2104 UnsafeArenaSetAllocatedMessage(message, sub_message, field);
2105 }
2106}
2107
2108Message* Reflection::UnsafeArenaReleaseMessage(Message* message,
2109 const FieldDescriptor* field,
2110 MessageFactory* factory) const {
2111 USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
2112 CheckInvalidAccess(schema: schema_, field);
2113
2114 if (factory == nullptr) factory = message_factory_;
2115
2116 if (field->is_extension()) {
2117 return static_cast<Message*>(
2118 MutableExtensionSet(message)->UnsafeArenaReleaseMessage(descriptor: field,
2119 factory));
2120 } else {
2121 if (!(field->is_repeated() || schema_.InRealOneof(field))) {
2122 ClearBit(message, field);
2123 }
2124 if (schema_.InRealOneof(field)) {
2125 if (HasOneofField(message: *message, field)) {
2126 *MutableOneofCase(message, oneof_descriptor: field->containing_oneof()) = 0;
2127 } else {
2128 return nullptr;
2129 }
2130 }
2131 Message** result = MutableRaw<Message*>(message, field);
2132 Message* ret = *result;
2133 *result = nullptr;
2134 return ret;
2135 }
2136}
2137
2138Message* Reflection::ReleaseMessage(Message* message,
2139 const FieldDescriptor* field,
2140 MessageFactory* factory) const {
2141 CheckInvalidAccess(schema: schema_, field);
2142
2143 Message* released = UnsafeArenaReleaseMessage(message, field, factory);
2144#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
2145 released = MaybeForceCopy(message->GetArenaForAllocation(), released);
2146#endif // PROTOBUF_FORCE_COPY_IN_RELEASE
2147 if (message->GetArenaForAllocation() != nullptr && released != nullptr) {
2148 Message* copy_from_arena = released->New();
2149 copy_from_arena->CopyFrom(from: *released);
2150 released = copy_from_arena;
2151 }
2152 return released;
2153}
2154
2155const Message& Reflection::GetRepeatedMessage(const Message& message,
2156 const FieldDescriptor* field,
2157 int index) const {
2158 USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
2159 CheckInvalidAccess(schema: schema_, field);
2160
2161 if (field->is_extension()) {
2162 return static_cast<const Message&>(
2163 GetExtensionSet(message).GetRepeatedMessage(number: field->number(), index));
2164 } else {
2165 if (IsMapFieldInApi(field)) {
2166 return GetRaw<MapFieldBase>(message, field)
2167 .GetRepeatedField()
2168 .Get<GenericTypeHandler<Message> >(index);
2169 } else {
2170 return GetRaw<RepeatedPtrFieldBase>(message, field)
2171 .Get<GenericTypeHandler<Message> >(index);
2172 }
2173 }
2174}
2175
2176Message* Reflection::MutableRepeatedMessage(Message* message,
2177 const FieldDescriptor* field,
2178 int index) const {
2179 USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
2180 CheckInvalidAccess(schema: schema_, field);
2181
2182 if (field->is_extension()) {
2183 return static_cast<Message*>(
2184 MutableExtensionSet(message)->MutableRepeatedMessage(number: field->number(),
2185 index));
2186 } else {
2187 if (IsMapFieldInApi(field)) {
2188 return MutableRaw<MapFieldBase>(message, field)
2189 ->MutableRepeatedField()
2190 ->Mutable<GenericTypeHandler<Message> >(index);
2191 } else {
2192 return MutableRaw<RepeatedPtrFieldBase>(message, field)
2193 ->Mutable<GenericTypeHandler<Message> >(index);
2194 }
2195 }
2196}
2197
2198Message* Reflection::AddMessage(Message* message, const FieldDescriptor* field,
2199 MessageFactory* factory) const {
2200 USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
2201 CheckInvalidAccess(schema: schema_, field);
2202
2203 if (factory == nullptr) factory = message_factory_;
2204
2205 if (field->is_extension()) {
2206 return static_cast<Message*>(
2207 MutableExtensionSet(message)->AddMessage(descriptor: field, factory));
2208 } else {
2209 Message* result = nullptr;
2210
2211 // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
2212 // know how to allocate one.
2213 RepeatedPtrFieldBase* repeated = nullptr;
2214 if (IsMapFieldInApi(field)) {
2215 repeated =
2216 MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
2217 } else {
2218 repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
2219 }
2220 result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
2221 if (result == nullptr) {
2222 // We must allocate a new object.
2223 const Message* prototype;
2224 if (repeated->size() == 0) {
2225 prototype = factory->GetPrototype(type: field->message_type());
2226 } else {
2227 prototype = &repeated->Get<GenericTypeHandler<Message> >(index: 0);
2228 }
2229 result = prototype->New(arena: message->GetArenaForAllocation());
2230 // We can guarantee here that repeated and result are either both heap
2231 // allocated or arena owned. So it is safe to call the unsafe version
2232 // of AddAllocated.
2233 repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(value: result);
2234 }
2235
2236 return result;
2237 }
2238}
2239
2240void Reflection::AddAllocatedMessage(Message* message,
2241 const FieldDescriptor* field,
2242 Message* new_entry) const {
2243 USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
2244 CheckInvalidAccess(schema: schema_, field);
2245
2246 if (field->is_extension()) {
2247 MutableExtensionSet(message)->AddAllocatedMessage(descriptor: field, new_entry);
2248 } else {
2249 RepeatedPtrFieldBase* repeated = nullptr;
2250 if (IsMapFieldInApi(field)) {
2251 repeated =
2252 MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
2253 } else {
2254 repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
2255 }
2256 repeated->AddAllocated<GenericTypeHandler<Message> >(value: new_entry);
2257 }
2258}
2259
2260void Reflection::UnsafeArenaAddAllocatedMessage(Message* message,
2261 const FieldDescriptor* field,
2262 Message* new_entry) const {
2263 USAGE_CHECK_ALL(UnsafeArenaAddAllocatedMessage, REPEATED, MESSAGE);
2264 CheckInvalidAccess(schema: schema_, field);
2265
2266 if (field->is_extension()) {
2267 MutableExtensionSet(message)->UnsafeArenaAddAllocatedMessage(descriptor: field,
2268 new_entry);
2269 } else {
2270 RepeatedPtrFieldBase* repeated = nullptr;
2271 if (IsMapFieldInApi(field)) {
2272 repeated =
2273 MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
2274 } else {
2275 repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
2276 }
2277 repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message>>(value: new_entry);
2278 }
2279}
2280
2281void* Reflection::MutableRawRepeatedField(Message* message,
2282 const FieldDescriptor* field,
2283 FieldDescriptor::CppType cpptype,
2284 int ctype,
2285 const Descriptor* desc) const {
2286 (void)ctype; // Parameter is used by Google-internal code.
2287 USAGE_CHECK_REPEATED("MutableRawRepeatedField");
2288 CheckInvalidAccess(schema: schema_, field);
2289
2290 if (field->cpp_type() != cpptype &&
2291 (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM ||
2292 cpptype != FieldDescriptor::CPPTYPE_INT32))
2293 ReportReflectionUsageTypeError(descriptor: descriptor_, field,
2294 method: "MutableRawRepeatedField", expected_type: cpptype);
2295 if (desc != nullptr)
2296 GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
2297 if (field->is_extension()) {
2298 return MutableExtensionSet(message)->MutableRawRepeatedField(
2299 number: field->number(), field_type: field->type(), packed: field->is_packed(), desc: field);
2300 } else {
2301 // Trigger transform for MapField
2302 if (IsMapFieldInApi(field)) {
2303 return MutableRawNonOneof<MapFieldBase>(message, field)
2304 ->MutableRepeatedField();
2305 }
2306 return MutableRawNonOneof<void>(message, field);
2307 }
2308}
2309
2310const void* Reflection::GetRawRepeatedField(const Message& message,
2311 const FieldDescriptor* field,
2312 FieldDescriptor::CppType cpptype,
2313 int ctype,
2314 const Descriptor* desc) const {
2315 USAGE_CHECK_REPEATED("GetRawRepeatedField");
2316 if (field->cpp_type() != cpptype)
2317 ReportReflectionUsageTypeError(descriptor: descriptor_, field, method: "GetRawRepeatedField",
2318 expected_type: cpptype);
2319 if (ctype >= 0)
2320 GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
2321 if (desc != nullptr)
2322 GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
2323 if (field->is_extension()) {
2324 // Should use extension_set::GetRawRepeatedField. However, the required
2325 // parameter "default repeated value" is not very easy to get here.
2326 // Map is not supported in extensions, it is acceptable to use
2327 // extension_set::MutableRawRepeatedField which does not change the message.
2328 return MutableExtensionSet(message: const_cast<Message*>(&message))
2329 ->MutableRawRepeatedField(number: field->number(), field_type: field->type(),
2330 packed: field->is_packed(), desc: field);
2331 } else {
2332 // Trigger transform for MapField
2333 if (IsMapFieldInApi(field)) {
2334 return &(GetRawNonOneof<MapFieldBase>(message, field).GetRepeatedField());
2335 }
2336 return &GetRawNonOneof<char>(message, field);
2337 }
2338}
2339
2340const FieldDescriptor* Reflection::GetOneofFieldDescriptor(
2341 const Message& message, const OneofDescriptor* oneof_descriptor) const {
2342 if (oneof_descriptor->is_synthetic()) {
2343 const FieldDescriptor* field = oneof_descriptor->field(index: 0);
2344 return HasField(message, field) ? field : nullptr;
2345 }
2346 uint32_t field_number = GetOneofCase(message, oneof_descriptor);
2347 if (field_number == 0) {
2348 return nullptr;
2349 }
2350 return descriptor_->FindFieldByNumber(number: field_number);
2351}
2352
2353bool Reflection::ContainsMapKey(const Message& message,
2354 const FieldDescriptor* field,
2355 const MapKey& key) const {
2356 USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue",
2357 "Field is not a map field.");
2358 return GetRaw<MapFieldBase>(message, field).ContainsMapKey(map_key: key);
2359}
2360
2361bool Reflection::InsertOrLookupMapValue(Message* message,
2362 const FieldDescriptor* field,
2363 const MapKey& key,
2364 MapValueRef* val) const {
2365 USAGE_CHECK(IsMapFieldInApi(field), "InsertOrLookupMapValue",
2366 "Field is not a map field.");
2367 val->SetType(field->message_type()->map_value()->cpp_type());
2368 return MutableRaw<MapFieldBase>(message, field)
2369 ->InsertOrLookupMapValue(map_key: key, val);
2370}
2371
2372bool Reflection::LookupMapValue(const Message& message,
2373 const FieldDescriptor* field, const MapKey& key,
2374 MapValueConstRef* val) const {
2375 USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue",
2376 "Field is not a map field.");
2377 val->SetType(field->message_type()->map_value()->cpp_type());
2378 return GetRaw<MapFieldBase>(message, field).LookupMapValue(map_key: key, val);
2379}
2380
2381bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field,
2382 const MapKey& key) const {
2383 USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue",
2384 "Field is not a map field.");
2385 return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(map_key: key);
2386}
2387
2388MapIterator Reflection::MapBegin(Message* message,
2389 const FieldDescriptor* field) const {
2390 USAGE_CHECK(IsMapFieldInApi(field), "MapBegin", "Field is not a map field.");
2391 MapIterator iter(message, field);
2392 GetRaw<MapFieldBase>(message: *message, field).MapBegin(map_iter: &iter);
2393 return iter;
2394}
2395
2396MapIterator Reflection::MapEnd(Message* message,
2397 const FieldDescriptor* field) const {
2398 USAGE_CHECK(IsMapFieldInApi(field), "MapEnd", "Field is not a map field.");
2399 MapIterator iter(message, field);
2400 GetRaw<MapFieldBase>(message: *message, field).MapEnd(map_iter: &iter);
2401 return iter;
2402}
2403
2404int Reflection::MapSize(const Message& message,
2405 const FieldDescriptor* field) const {
2406 USAGE_CHECK(IsMapFieldInApi(field), "MapSize", "Field is not a map field.");
2407 return GetRaw<MapFieldBase>(message, field).size();
2408}
2409
2410// -----------------------------------------------------------------------------
2411
2412const FieldDescriptor* Reflection::FindKnownExtensionByName(
2413 const std::string& name) const {
2414 if (!schema_.HasExtensionSet()) return nullptr;
2415 return descriptor_pool_->FindExtensionByPrintableName(extendee: descriptor_, printable_name: name);
2416}
2417
2418const FieldDescriptor* Reflection::FindKnownExtensionByNumber(
2419 int number) const {
2420 if (!schema_.HasExtensionSet()) return nullptr;
2421 return descriptor_pool_->FindExtensionByNumber(extendee: descriptor_, number);
2422}
2423
2424bool Reflection::SupportsUnknownEnumValues() const {
2425 return CreateUnknownEnumValues(file: descriptor_->file());
2426}
2427
2428// ===================================================================
2429// Some private helpers.
2430
2431// These simple template accessors obtain pointers (or references) to
2432// the given field.
2433
2434template <class Type>
2435const Type& Reflection::GetRawNonOneof(const Message& message,
2436 const FieldDescriptor* field) const {
2437 return GetConstRefAtOffset<Type>(message,
2438 schema_.GetFieldOffsetNonOneof(field));
2439}
2440
2441template <class Type>
2442Type* Reflection::MutableRawNonOneof(Message* message,
2443 const FieldDescriptor* field) const {
2444 return GetPointerAtOffset<Type>(message,
2445 schema_.GetFieldOffsetNonOneof(field));
2446}
2447
2448template <typename Type>
2449Type* Reflection::MutableRaw(Message* message,
2450 const FieldDescriptor* field) const {
2451 return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field));
2452}
2453
2454const uint32_t* Reflection::GetHasBits(const Message& message) const {
2455 GOOGLE_DCHECK(schema_.HasHasbits());
2456 return &GetConstRefAtOffset<uint32_t>(message, offset: schema_.HasBitsOffset());
2457}
2458
2459uint32_t* Reflection::MutableHasBits(Message* message) const {
2460 GOOGLE_DCHECK(schema_.HasHasbits());
2461 return GetPointerAtOffset<uint32_t>(message, offset: schema_.HasBitsOffset());
2462}
2463
2464uint32_t* Reflection::MutableOneofCase(
2465 Message* message, const OneofDescriptor* oneof_descriptor) const {
2466 GOOGLE_DCHECK(!oneof_descriptor->is_synthetic());
2467 return GetPointerAtOffset<uint32_t>(
2468 message, offset: schema_.GetOneofCaseOffset(oneof_descriptor));
2469}
2470
2471const ExtensionSet& Reflection::GetExtensionSet(const Message& message) const {
2472 return GetConstRefAtOffset<ExtensionSet>(message,
2473 offset: schema_.GetExtensionSetOffset());
2474}
2475
2476ExtensionSet* Reflection::MutableExtensionSet(Message* message) const {
2477 return GetPointerAtOffset<ExtensionSet>(message,
2478 offset: schema_.GetExtensionSetOffset());
2479}
2480
2481const InternalMetadata& Reflection::GetInternalMetadata(
2482 const Message& message) const {
2483 return GetConstRefAtOffset<InternalMetadata>(message,
2484 offset: schema_.GetMetadataOffset());
2485}
2486
2487InternalMetadata* Reflection::MutableInternalMetadata(Message* message) const {
2488 return GetPointerAtOffset<InternalMetadata>(message,
2489 offset: schema_.GetMetadataOffset());
2490}
2491
2492const uint32_t* Reflection::GetInlinedStringDonatedArray(
2493 const Message& message) const {
2494 GOOGLE_DCHECK(schema_.HasInlinedString());
2495 return &GetConstRefAtOffset<uint32_t>(message,
2496 offset: schema_.InlinedStringDonatedOffset());
2497}
2498
2499uint32_t* Reflection::MutableInlinedStringDonatedArray(Message* message) const {
2500 GOOGLE_DCHECK(schema_.HasInlinedString());
2501 return GetPointerAtOffset<uint32_t>(message,
2502 offset: schema_.InlinedStringDonatedOffset());
2503}
2504
2505// Simple accessors for manipulating _inlined_string_donated_;
2506bool Reflection::IsInlinedStringDonated(const Message& message,
2507 const FieldDescriptor* field) const {
2508 uint32_t index = schema_.InlinedStringIndex(field);
2509 GOOGLE_DCHECK_GT(index, 0);
2510 return IsIndexInHasBitSet(has_bit_set: GetInlinedStringDonatedArray(message), has_bit_index: index);
2511}
2512
2513inline void SetInlinedStringDonated(uint32_t index, uint32_t* array) {
2514 array[index / 32] |= (static_cast<uint32_t>(1) << (index % 32));
2515}
2516
2517inline void ClearInlinedStringDonated(uint32_t index, uint32_t* array) {
2518 array[index / 32] &= ~(static_cast<uint32_t>(1) << (index % 32));
2519}
2520
2521void Reflection::SwapInlinedStringDonated(Message* lhs, Message* rhs,
2522 const FieldDescriptor* field) const {
2523 Arena* lhs_arena = lhs->GetArenaForAllocation();
2524 Arena* rhs_arena = rhs->GetArenaForAllocation();
2525 // If arenas differ, inined string fields are swapped by copying values.
2526 // Donation status should not be swapped.
2527 if (lhs_arena != rhs_arena) {
2528 return;
2529 }
2530 bool lhs_donated = IsInlinedStringDonated(message: *lhs, field);
2531 bool rhs_donated = IsInlinedStringDonated(message: *rhs, field);
2532 if (lhs_donated == rhs_donated) {
2533 return;
2534 }
2535 // If one is undonated, both must have already registered ArenaDtor.
2536 uint32_t* lhs_array = MutableInlinedStringDonatedArray(message: lhs);
2537 uint32_t* rhs_array = MutableInlinedStringDonatedArray(message: rhs);
2538 GOOGLE_CHECK_EQ(lhs_array[0] & 0x1u, 0u);
2539 GOOGLE_CHECK_EQ(rhs_array[0] & 0x1u, 0u);
2540 // Swap donation status bit.
2541 uint32_t index = schema_.InlinedStringIndex(field);
2542 GOOGLE_DCHECK_GT(index, 0);
2543 if (rhs_donated) {
2544 SetInlinedStringDonated(index, array: lhs_array);
2545 ClearInlinedStringDonated(index, array: rhs_array);
2546 } else { // lhs_donated
2547 ClearInlinedStringDonated(index, array: lhs_array);
2548 SetInlinedStringDonated(index, array: rhs_array);
2549 }
2550}
2551
2552// Simple accessors for manipulating has_bits_.
2553bool Reflection::HasBit(const Message& message,
2554 const FieldDescriptor* field) const {
2555 GOOGLE_DCHECK(!field->options().weak());
2556 if (schema_.HasBitIndex(field) != static_cast<uint32_t>(-1)) {
2557 return IsIndexInHasBitSet(has_bit_set: GetHasBits(message), has_bit_index: schema_.HasBitIndex(field));
2558 }
2559
2560 // Intentionally check here because HasBitIndex(field) != -1 means valid.
2561 CheckInvalidAccess(schema: schema_, field);
2562
2563 // proto3: no has-bits. All fields present except messages, which are
2564 // present only if their message-field pointer is non-null.
2565 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2566 return !schema_.IsDefaultInstance(message) &&
2567 GetRaw<const Message*>(message, field) != nullptr;
2568 } else {
2569 // Non-message field (and non-oneof, since that was handled in HasField()
2570 // before calling us), and singular (again, checked in HasField). So, this
2571 // field must be a scalar.
2572
2573 // Scalar primitive (numeric or string/bytes) fields are present if
2574 // their value is non-zero (numeric) or non-empty (string/bytes). N.B.:
2575 // we must use this definition here, rather than the "scalar fields
2576 // always present" in the proto3 docs, because MergeFrom() semantics
2577 // require presence as "present on wire", and reflection-based merge
2578 // (which uses HasField()) needs to be consistent with this.
2579 switch (field->cpp_type()) {
2580 case FieldDescriptor::CPPTYPE_STRING:
2581 switch (field->options().ctype()) {
2582 default: {
2583 if (IsInlined(field)) {
2584 return !GetField<InlinedStringField>(message, field)
2585 .GetNoArena()
2586 .empty();
2587 }
2588
2589 return GetField<ArenaStringPtr>(message, field).Get().size() > 0;
2590 }
2591 }
2592 return false;
2593 case FieldDescriptor::CPPTYPE_BOOL:
2594 return GetRaw<bool>(message, field) != false;
2595 case FieldDescriptor::CPPTYPE_INT32:
2596 return GetRaw<int32_t>(message, field) != 0;
2597 case FieldDescriptor::CPPTYPE_INT64:
2598 return GetRaw<int64_t>(message, field) != 0;
2599 case FieldDescriptor::CPPTYPE_UINT32:
2600 return GetRaw<uint32_t>(message, field) != 0;
2601 case FieldDescriptor::CPPTYPE_UINT64:
2602 return GetRaw<uint64_t>(message, field) != 0;
2603 case FieldDescriptor::CPPTYPE_FLOAT:
2604 static_assert(sizeof(uint32_t) == sizeof(float),
2605 "Code assumes uint32_t and float are the same size.");
2606 return GetRaw<uint32_t>(message, field) != 0;
2607 case FieldDescriptor::CPPTYPE_DOUBLE:
2608 static_assert(sizeof(uint64_t) == sizeof(double),
2609 "Code assumes uint64_t and double are the same size.");
2610 return GetRaw<uint64_t>(message, field) != 0;
2611 case FieldDescriptor::CPPTYPE_ENUM:
2612 return GetRaw<int>(message, field) != 0;
2613 case FieldDescriptor::CPPTYPE_MESSAGE:
2614 // handled above; avoid warning
2615 break;
2616 }
2617 GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
2618 return false;
2619 }
2620}
2621
2622void Reflection::SetBit(Message* message, const FieldDescriptor* field) const {
2623 GOOGLE_DCHECK(!field->options().weak());
2624 const uint32_t index = schema_.HasBitIndex(field);
2625 if (index == static_cast<uint32_t>(-1)) return;
2626 MutableHasBits(message)[index / 32] |=
2627 (static_cast<uint32_t>(1) << (index % 32));
2628}
2629
2630void Reflection::ClearBit(Message* message,
2631 const FieldDescriptor* field) const {
2632 GOOGLE_DCHECK(!field->options().weak());
2633 const uint32_t index = schema_.HasBitIndex(field);
2634 if (index == static_cast<uint32_t>(-1)) return;
2635 MutableHasBits(message)[index / 32] &=
2636 ~(static_cast<uint32_t>(1) << (index % 32));
2637}
2638
2639void Reflection::SwapBit(Message* message1, Message* message2,
2640 const FieldDescriptor* field) const {
2641 GOOGLE_DCHECK(!field->options().weak());
2642 if (!schema_.HasHasbits()) {
2643 return;
2644 }
2645 bool temp_has_bit = HasBit(message: *message1, field);
2646 if (HasBit(message: *message2, field)) {
2647 SetBit(message: message1, field);
2648 } else {
2649 ClearBit(message: message1, field);
2650 }
2651 if (temp_has_bit) {
2652 SetBit(message: message2, field);
2653 } else {
2654 ClearBit(message: message2, field);
2655 }
2656}
2657
2658bool Reflection::HasOneof(const Message& message,
2659 const OneofDescriptor* oneof_descriptor) const {
2660 if (oneof_descriptor->is_synthetic()) {
2661 return HasField(message, field: oneof_descriptor->field(index: 0));
2662 }
2663 return (GetOneofCase(message, oneof_descriptor) > 0);
2664}
2665
2666void Reflection::SetOneofCase(Message* message,
2667 const FieldDescriptor* field) const {
2668 *MutableOneofCase(message, oneof_descriptor: field->containing_oneof()) = field->number();
2669}
2670
2671void Reflection::ClearOneofField(Message* message,
2672 const FieldDescriptor* field) const {
2673 if (HasOneofField(message: *message, field)) {
2674 ClearOneof(message, oneof_descriptor: field->containing_oneof());
2675 }
2676}
2677
2678void Reflection::ClearOneof(Message* message,
2679 const OneofDescriptor* oneof_descriptor) const {
2680 if (oneof_descriptor->is_synthetic()) {
2681 ClearField(message, field: oneof_descriptor->field(index: 0));
2682 return;
2683 }
2684 // TODO(jieluo): Consider to cache the unused object instead of deleting
2685 // it. It will be much faster if an application switches a lot from
2686 // a few oneof fields. Time/space tradeoff
2687 uint32_t oneof_case = GetOneofCase(message: *message, oneof_descriptor);
2688 if (oneof_case > 0) {
2689 const FieldDescriptor* field = descriptor_->FindFieldByNumber(number: oneof_case);
2690 if (message->GetArenaForAllocation() == nullptr) {
2691 switch (field->cpp_type()) {
2692 case FieldDescriptor::CPPTYPE_STRING: {
2693 switch (field->options().ctype()) {
2694 default: // TODO(kenton): Support other string reps.
2695 case FieldOptions::STRING: {
2696 // Oneof string fields are never set as a default instance.
2697 // We just need to pass some arbitrary default string to make it
2698 // work. This allows us to not have the real default accessible
2699 // from reflection.
2700 MutableField<ArenaStringPtr>(message, field)->Destroy();
2701 break;
2702 }
2703 }
2704 break;
2705 }
2706
2707 case FieldDescriptor::CPPTYPE_MESSAGE:
2708 delete *MutableRaw<Message*>(message, field);
2709 break;
2710 default:
2711 break;
2712 }
2713 } else {
2714 }
2715
2716 *MutableOneofCase(message, oneof_descriptor) = 0;
2717 }
2718}
2719
2720#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \
2721 template <> \
2722 const RepeatedField<TYPE>& Reflection::GetRepeatedFieldInternal<TYPE>( \
2723 const Message& message, const FieldDescriptor* field) const { \
2724 return *static_cast<RepeatedField<TYPE>*>(MutableRawRepeatedField( \
2725 const_cast<Message*>(&message), field, CPPTYPE, CTYPE, nullptr)); \
2726 } \
2727 \
2728 template <> \
2729 RepeatedField<TYPE>* Reflection::MutableRepeatedFieldInternal<TYPE>( \
2730 Message * message, const FieldDescriptor* field) const { \
2731 return static_cast<RepeatedField<TYPE>*>( \
2732 MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, nullptr)); \
2733 }
2734
2735HANDLE_TYPE(int32_t, FieldDescriptor::CPPTYPE_INT32, -1);
2736HANDLE_TYPE(int64_t, FieldDescriptor::CPPTYPE_INT64, -1);
2737HANDLE_TYPE(uint32_t, FieldDescriptor::CPPTYPE_UINT32, -1);
2738HANDLE_TYPE(uint64_t, FieldDescriptor::CPPTYPE_UINT64, -1);
2739HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
2740HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
2741HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
2742
2743
2744#undef HANDLE_TYPE
2745
2746void* Reflection::MutableRawRepeatedString(Message* message,
2747 const FieldDescriptor* field,
2748 bool is_string) const {
2749 (void)is_string; // Parameter is used by Google-internal code.
2750 return MutableRawRepeatedField(message, field,
2751 cpptype: FieldDescriptor::CPPTYPE_STRING,
2752 ctype: FieldOptions::STRING, desc: nullptr);
2753}
2754
2755// Template implementations of basic accessors. Inline because each
2756// template instance is only called from one location. These are
2757// used for all types except messages.
2758template <typename Type>
2759const Type& Reflection::GetField(const Message& message,
2760 const FieldDescriptor* field) const {
2761 return GetRaw<Type>(message, field);
2762}
2763
2764template <typename Type>
2765void Reflection::SetField(Message* message, const FieldDescriptor* field,
2766 const Type& value) const {
2767 bool real_oneof = schema_.InRealOneof(field);
2768 if (real_oneof && !HasOneofField(message: *message, field)) {
2769 ClearOneof(message, oneof_descriptor: field->containing_oneof());
2770 }
2771 *MutableRaw<Type>(message, field) = value;
2772 real_oneof ? SetOneofCase(message, field) : SetBit(message, field);
2773}
2774
2775template <typename Type>
2776Type* Reflection::MutableField(Message* message,
2777 const FieldDescriptor* field) const {
2778 schema_.InRealOneof(field) ? SetOneofCase(message, field)
2779 : SetBit(message, field);
2780 return MutableRaw<Type>(message, field);
2781}
2782
2783template <typename Type>
2784const Type& Reflection::GetRepeatedField(const Message& message,
2785 const FieldDescriptor* field,
2786 int index) const {
2787 return GetRaw<RepeatedField<Type> >(message, field).Get(index);
2788}
2789
2790template <typename Type>
2791const Type& Reflection::GetRepeatedPtrField(const Message& message,
2792 const FieldDescriptor* field,
2793 int index) const {
2794 return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
2795}
2796
2797template <typename Type>
2798void Reflection::SetRepeatedField(Message* message,
2799 const FieldDescriptor* field, int index,
2800 Type value) const {
2801 MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
2802}
2803
2804template <typename Type>
2805Type* Reflection::MutableRepeatedField(Message* message,
2806 const FieldDescriptor* field,
2807 int index) const {
2808 RepeatedPtrField<Type>* repeated =
2809 MutableRaw<RepeatedPtrField<Type> >(message, field);
2810 return repeated->Mutable(index);
2811}
2812
2813template <typename Type>
2814void Reflection::AddField(Message* message, const FieldDescriptor* field,
2815 const Type& value) const {
2816 MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
2817}
2818
2819template <typename Type>
2820Type* Reflection::AddField(Message* message,
2821 const FieldDescriptor* field) const {
2822 RepeatedPtrField<Type>* repeated =
2823 MutableRaw<RepeatedPtrField<Type> >(message, field);
2824 return repeated->Add();
2825}
2826
2827MessageFactory* Reflection::GetMessageFactory() const {
2828 return message_factory_;
2829}
2830
2831void* Reflection::RepeatedFieldData(Message* message,
2832 const FieldDescriptor* field,
2833 FieldDescriptor::CppType cpp_type,
2834 const Descriptor* message_type) const {
2835 GOOGLE_CHECK(field->is_repeated());
2836 GOOGLE_CHECK(field->cpp_type() == cpp_type ||
2837 (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
2838 cpp_type == FieldDescriptor::CPPTYPE_INT32))
2839 << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
2840 << "the actual field type (for enums T should be the generated enum "
2841 << "type or int32_t).";
2842 if (message_type != nullptr) {
2843 GOOGLE_CHECK_EQ(message_type, field->message_type());
2844 }
2845 if (field->is_extension()) {
2846 return MutableExtensionSet(message)->MutableRawRepeatedField(
2847 number: field->number(), field_type: field->type(), packed: field->is_packed(), desc: field);
2848 } else {
2849 return MutableRawNonOneof<char>(message, field);
2850 }
2851}
2852
2853MapFieldBase* Reflection::MutableMapData(Message* message,
2854 const FieldDescriptor* field) const {
2855 USAGE_CHECK(IsMapFieldInApi(field), "GetMapData",
2856 "Field is not a map field.");
2857 return MutableRaw<MapFieldBase>(message, field);
2858}
2859
2860const MapFieldBase* Reflection::GetMapData(const Message& message,
2861 const FieldDescriptor* field) const {
2862 USAGE_CHECK(IsMapFieldInApi(field), "GetMapData",
2863 "Field is not a map field.");
2864 return &(GetRaw<MapFieldBase>(message, field));
2865}
2866
2867namespace {
2868
2869// Helper function to transform migration schema into reflection schema.
2870ReflectionSchema MigrationToReflectionSchema(
2871 const Message* const* default_instance, const uint32_t* offsets,
2872 MigrationSchema migration_schema) {
2873 ReflectionSchema result;
2874 result.default_instance_ = *default_instance;
2875 // First 7 offsets are offsets to the special fields. The following offsets
2876 // are the proto fields.
2877 result.offsets_ = offsets + migration_schema.offsets_index + 6;
2878 result.has_bit_indices_ = offsets + migration_schema.has_bit_indices_index;
2879 result.has_bits_offset_ = offsets[migration_schema.offsets_index + 0];
2880 result.metadata_offset_ = offsets[migration_schema.offsets_index + 1];
2881 result.extensions_offset_ = offsets[migration_schema.offsets_index + 2];
2882 result.oneof_case_offset_ = offsets[migration_schema.offsets_index + 3];
2883 result.object_size_ = migration_schema.object_size;
2884 result.weak_field_map_offset_ = offsets[migration_schema.offsets_index + 4];
2885 result.inlined_string_donated_offset_ =
2886 offsets[migration_schema.offsets_index + 5];
2887 result.inlined_string_indices_ =
2888 offsets + migration_schema.inlined_string_indices_index;
2889 return result;
2890}
2891
2892} // namespace
2893
2894class AssignDescriptorsHelper {
2895 public:
2896 AssignDescriptorsHelper(MessageFactory* factory,
2897 Metadata* file_level_metadata,
2898 const EnumDescriptor** file_level_enum_descriptors,
2899 const MigrationSchema* schemas,
2900 const Message* const* default_instance_data,
2901 const uint32_t* offsets)
2902 : factory_(factory),
2903 file_level_metadata_(file_level_metadata),
2904 file_level_enum_descriptors_(file_level_enum_descriptors),
2905 schemas_(schemas),
2906 default_instance_data_(default_instance_data),
2907 offsets_(offsets) {}
2908
2909 void AssignMessageDescriptor(const Descriptor* descriptor) {
2910 for (int i = 0; i < descriptor->nested_type_count(); i++) {
2911 AssignMessageDescriptor(descriptor: descriptor->nested_type(index: i));
2912 }
2913
2914 file_level_metadata_->descriptor = descriptor;
2915
2916 file_level_metadata_->reflection =
2917 new Reflection(descriptor,
2918 MigrationToReflectionSchema(default_instance: default_instance_data_,
2919 offsets: offsets_, migration_schema: *schemas_),
2920 DescriptorPool::internal_generated_pool(), factory_);
2921 for (int i = 0; i < descriptor->enum_type_count(); i++) {
2922 AssignEnumDescriptor(descriptor: descriptor->enum_type(index: i));
2923 }
2924 schemas_++;
2925 default_instance_data_++;
2926 file_level_metadata_++;
2927 }
2928
2929 void AssignEnumDescriptor(const EnumDescriptor* descriptor) {
2930 *file_level_enum_descriptors_ = descriptor;
2931 file_level_enum_descriptors_++;
2932 }
2933
2934 const Metadata* GetCurrentMetadataPtr() const { return file_level_metadata_; }
2935
2936 private:
2937 MessageFactory* factory_;
2938 Metadata* file_level_metadata_;
2939 const EnumDescriptor** file_level_enum_descriptors_;
2940 const MigrationSchema* schemas_;
2941 const Message* const* default_instance_data_;
2942 const uint32_t* offsets_;
2943};
2944
2945namespace {
2946
2947// We have the routines that assign descriptors and build reflection
2948// automatically delete the allocated reflection. MetadataOwner owns
2949// all the allocated reflection instances.
2950struct MetadataOwner {
2951 ~MetadataOwner() {
2952 for (auto range : metadata_arrays_) {
2953 for (const Metadata* m = range.first; m < range.second; m++) {
2954 delete m->reflection;
2955 }
2956 }
2957 }
2958
2959 void AddArray(const Metadata* begin, const Metadata* end) {
2960 mu_.Lock();
2961 metadata_arrays_.push_back(x: std::make_pair(x&: begin, y&: end));
2962 mu_.Unlock();
2963 }
2964
2965 static MetadataOwner* Instance() {
2966 static MetadataOwner* res = OnShutdownDelete(p: new MetadataOwner);
2967 return res;
2968 }
2969
2970 private:
2971 MetadataOwner() = default; // private because singleton
2972
2973 WrappedMutex mu_;
2974 std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
2975};
2976
2977void AddDescriptors(const DescriptorTable* table);
2978
2979void AssignDescriptorsImpl(const DescriptorTable* table, bool eager) {
2980 // Ensure the file descriptor is added to the pool.
2981 {
2982 // This only happens once per proto file. So a global mutex to serialize
2983 // calls to AddDescriptors.
2984 static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
2985 mu.Lock();
2986 AddDescriptors(table);
2987 mu.Unlock();
2988 }
2989 if (eager) {
2990 // Normally we do not want to eagerly build descriptors of our deps.
2991 // However if this proto is optimized for code size (ie using reflection)
2992 // and it has a message extending a custom option of a descriptor with that
2993 // message being optimized for code size as well. Building the descriptors
2994 // in this file requires parsing the serialized file descriptor, which now
2995 // requires parsing the message extension, which potentially requires
2996 // building the descriptor of the message extending one of the options.
2997 // However we are already updating descriptor pool under a lock. To prevent
2998 // this the compiler statically looks for this case and we just make sure we
2999 // first build the descriptors of all our dependencies, preventing the
3000 // deadlock.
3001 int num_deps = table->num_deps;
3002 for (int i = 0; i < num_deps; i++) {
3003 // In case of weak fields deps[i] could be null.
3004 if (table->deps[i]) AssignDescriptors(table: table->deps[i], eager: true);
3005 }
3006 }
3007
3008 // Fill the arrays with pointers to descriptors and reflection classes.
3009 const FileDescriptor* file =
3010 DescriptorPool::internal_generated_pool()->FindFileByName(
3011 name: table->filename);
3012 GOOGLE_CHECK(file != nullptr);
3013
3014 MessageFactory* factory = MessageFactory::generated_factory();
3015
3016 AssignDescriptorsHelper helper(
3017 factory, table->file_level_metadata, table->file_level_enum_descriptors,
3018 table->schemas, table->default_instances, table->offsets);
3019
3020 for (int i = 0; i < file->message_type_count(); i++) {
3021 helper.AssignMessageDescriptor(descriptor: file->message_type(index: i));
3022 }
3023
3024 for (int i = 0; i < file->enum_type_count(); i++) {
3025 helper.AssignEnumDescriptor(descriptor: file->enum_type(index: i));
3026 }
3027 if (file->options().cc_generic_services()) {
3028 for (int i = 0; i < file->service_count(); i++) {
3029 table->file_level_service_descriptors[i] = file->service(index: i);
3030 }
3031 }
3032 MetadataOwner::Instance()->AddArray(begin: table->file_level_metadata,
3033 end: helper.GetCurrentMetadataPtr());
3034}
3035
3036void AddDescriptorsImpl(const DescriptorTable* table) {
3037 // Reflection refers to the default fields so make sure they are initialized.
3038 internal::InitProtobufDefaults();
3039
3040 // Ensure all dependent descriptors are registered to the generated descriptor
3041 // pool and message factory.
3042 int num_deps = table->num_deps;
3043 for (int i = 0; i < num_deps; i++) {
3044 // In case of weak fields deps[i] could be null.
3045 if (table->deps[i]) AddDescriptors(table: table->deps[i]);
3046 }
3047
3048 // Register the descriptor of this file.
3049 DescriptorPool::InternalAddGeneratedFile(encoded_file_descriptor: table->descriptor, size: table->size);
3050 MessageFactory::InternalRegisterGeneratedFile(table);
3051}
3052
3053void AddDescriptors(const DescriptorTable* table) {
3054 // AddDescriptors is not thread safe. Callers need to ensure calls are
3055 // properly serialized. This function is only called pre-main by global
3056 // descriptors and we can assume single threaded access or it's called
3057 // by AssignDescriptorImpl which uses a mutex to sequence calls.
3058 if (table->is_initialized) return;
3059 table->is_initialized = true;
3060 AddDescriptorsImpl(table);
3061}
3062
3063} // namespace
3064
3065// Separate function because it needs to be a friend of
3066// Reflection
3067void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) {
3068 for (int i = 0; i < size; i++) {
3069 const Reflection* reflection = file_level_metadata[i].reflection;
3070 MessageFactory::InternalRegisterGeneratedMessage(
3071 descriptor: file_level_metadata[i].descriptor,
3072 prototype: reflection->schema_.default_instance_);
3073 }
3074}
3075
3076namespace internal {
3077
3078Metadata AssignDescriptors(const DescriptorTable* (*table)(),
3079 internal::once_flag* once,
3080 const Metadata& metadata) {
3081 call_once(once&: *once, f: [=] {
3082 auto* t = table();
3083 AssignDescriptorsImpl(table: t, eager: t->is_eager);
3084 });
3085
3086 return metadata;
3087}
3088
3089void AssignDescriptors(const DescriptorTable* table, bool eager) {
3090 if (!eager) eager = table->is_eager;
3091 call_once(once&: *table->once, f&: AssignDescriptorsImpl, args&: table, args&: eager);
3092}
3093
3094AddDescriptorsRunner::AddDescriptorsRunner(const DescriptorTable* table) {
3095 AddDescriptors(table);
3096}
3097
3098void RegisterFileLevelMetadata(const DescriptorTable* table) {
3099 AssignDescriptors(table);
3100 RegisterAllTypesInternal(file_level_metadata: table->file_level_metadata, size: table->num_messages);
3101}
3102
3103void UnknownFieldSetSerializer(const uint8_t* base, uint32_t offset,
3104 uint32_t /*tag*/, uint32_t /*has_offset*/,
3105 io::CodedOutputStream* output) {
3106 const void* ptr = base + offset;
3107 const InternalMetadata* metadata = static_cast<const InternalMetadata*>(ptr);
3108 if (metadata->have_unknown_fields()) {
3109 metadata->unknown_fields<UnknownFieldSet>(default_instance: UnknownFieldSet::default_instance)
3110 .SerializeToCodedStream(output);
3111 }
3112}
3113
3114bool IsDescendant(Message& root, const Message& message) {
3115 const Reflection* reflection = root.GetReflection();
3116 std::vector<const FieldDescriptor*> fields;
3117 reflection->ListFieldsOmitStripped(message: root, output: &fields);
3118
3119 for (const auto* field : fields) {
3120 // Skip non-message fields.
3121 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
3122
3123 // Optional messages.
3124 if (!field->is_repeated()) {
3125 Message* sub_message = reflection->MutableMessage(message: &root, field);
3126 if (sub_message == &message || IsDescendant(root&: *sub_message, message)) {
3127 return true;
3128 }
3129 continue;
3130 }
3131
3132 // Repeated messages.
3133 if (!IsMapFieldInApi(field)) {
3134 int count = reflection->FieldSize(message: root, field);
3135 for (int i = 0; i < count; i++) {
3136 Message* sub_message =
3137 reflection->MutableRepeatedMessage(message: &root, field, index: i);
3138 if (sub_message == &message || IsDescendant(root&: *sub_message, message)) {
3139 return true;
3140 }
3141 }
3142 continue;
3143 }
3144
3145 // Map field: if accessed as repeated fields, messages are *copied* and
3146 // matching pointer won't work. Must directly access map.
3147 constexpr int kValIdx = 1;
3148 const FieldDescriptor* val_field = field->message_type()->field(index: kValIdx);
3149 // Skip map fields whose value type is not message.
3150 if (val_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
3151
3152 MapIterator end = reflection->MapEnd(message: &root, field);
3153 for (auto iter = reflection->MapBegin(message: &root, field); iter != end; ++iter) {
3154 Message* sub_message = iter.MutableValueRef()->MutableMessageValue();
3155 if (sub_message == &message || IsDescendant(root&: *sub_message, message)) {
3156 return true;
3157 }
3158 }
3159 }
3160
3161 return false;
3162}
3163
3164} // namespace internal
3165} // namespace protobuf
3166} // namespace google
3167
3168#include <google/protobuf/port_undef.inc>
3169