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/extension_set.h>
36
37#include <tuple>
38#include <unordered_set>
39#include <utility>
40
41#include <google/protobuf/stubs/common.h>
42#include <google/protobuf/io/coded_stream.h>
43#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
44#include <google/protobuf/arena.h>
45#include <google/protobuf/extension_set_inl.h>
46#include <google/protobuf/message_lite.h>
47#include <google/protobuf/metadata_lite.h>
48#include <google/protobuf/parse_context.h>
49#include <google/protobuf/port.h>
50#include <google/protobuf/repeated_field.h>
51#include <google/protobuf/stubs/map_util.h>
52#include <google/protobuf/stubs/hash.h>
53
54// clang-format off
55#include <google/protobuf/port_def.inc> // must be last.
56// clang-format on
57namespace google {
58namespace protobuf {
59namespace internal {
60
61namespace {
62
63inline WireFormatLite::FieldType real_type(FieldType type) {
64 GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
65 return static_cast<WireFormatLite::FieldType>(type);
66}
67
68inline WireFormatLite::CppType cpp_type(FieldType type) {
69 return WireFormatLite::FieldTypeToCppType(type: real_type(type));
70}
71
72// Registry stuff.
73
74// Note that we cannot use hetererogeneous lookup for std containers since we
75// need to support C++11.
76struct ExtensionEq {
77 bool operator()(const ExtensionInfo& lhs, const ExtensionInfo& rhs) const {
78 return lhs.message == rhs.message && lhs.number == rhs.number;
79 }
80};
81
82struct ExtensionHasher {
83 std::size_t operator()(const ExtensionInfo& info) const {
84 return std::hash<const MessageLite*>{}(info.message) ^
85 std::hash<int>{}(info.number);
86 }
87};
88
89using ExtensionRegistry =
90 std::unordered_set<ExtensionInfo, ExtensionHasher, ExtensionEq>;
91
92static const ExtensionRegistry* global_registry = nullptr;
93
94// This function is only called at startup, so there is no need for thread-
95// safety.
96void Register(const ExtensionInfo& info) {
97 static auto local_static_registry = OnShutdownDelete(p: new ExtensionRegistry);
98 global_registry = local_static_registry;
99 if (!InsertIfNotPresent(collection: local_static_registry, vt: info)) {
100 GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
101 << info.message->GetTypeName() << "\", field number "
102 << info.number << ".";
103 }
104}
105
106const ExtensionInfo* FindRegisteredExtension(const MessageLite* extendee,
107 int number) {
108 if (!global_registry) return nullptr;
109
110 ExtensionInfo info;
111 info.message = extendee;
112 info.number = number;
113
114 auto it = global_registry->find(x: info);
115 if (it == global_registry->end()) {
116 return nullptr;
117 } else {
118 return &*it;
119 }
120}
121
122} // namespace
123
124bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) {
125 const ExtensionInfo* extension = FindRegisteredExtension(extendee: extendee_, number);
126 if (extension == nullptr) {
127 return false;
128 } else {
129 *output = *extension;
130 return true;
131 }
132}
133
134void ExtensionSet::RegisterExtension(const MessageLite* extendee, int number,
135 FieldType type, bool is_repeated,
136 bool is_packed,
137 LazyEagerVerifyFnType verify_func) {
138 GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM);
139 GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE);
140 GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP);
141 ExtensionInfo info(extendee, number, type, is_repeated, is_packed,
142 verify_func);
143 Register(info);
144}
145
146static bool CallNoArgValidityFunc(const void* arg, int number) {
147 // Note: Must use C-style cast here rather than reinterpret_cast because
148 // the C++ standard at one point did not allow casts between function and
149 // data pointers and some compilers enforce this for C++-style casts. No
150 // compiler enforces it for C-style casts since lots of C-style code has
151 // relied on these kinds of casts for a long time, despite being
152 // technically undefined. See:
153 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195
154 // Also note: Some compilers do not allow function pointers to be "const".
155 // Which makes sense, I suppose, because it's meaningless.
156 return ((EnumValidityFunc*)arg)(number);
157}
158
159void ExtensionSet::RegisterEnumExtension(const MessageLite* extendee,
160 int number, FieldType type,
161 bool is_repeated, bool is_packed,
162 EnumValidityFunc* is_valid) {
163 GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM);
164 ExtensionInfo info(extendee, number, type, is_repeated, is_packed, nullptr);
165 info.enum_validity_check.func = CallNoArgValidityFunc;
166 // See comment in CallNoArgValidityFunc() about why we use a c-style cast.
167 info.enum_validity_check.arg = (void*)is_valid;
168 Register(info);
169}
170
171void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee,
172 int number, FieldType type,
173 bool is_repeated, bool is_packed,
174 const MessageLite* prototype,
175 LazyEagerVerifyFnType verify_func) {
176 GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE ||
177 type == WireFormatLite::TYPE_GROUP);
178 ExtensionInfo info(extendee, number, type, is_repeated, is_packed,
179 verify_func);
180 info.message_info = {.prototype: prototype};
181 Register(info);
182}
183
184// ===================================================================
185// Constructors and basic methods.
186
187ExtensionSet::ExtensionSet(Arena* arena)
188 : arena_(arena),
189 flat_capacity_(0),
190 flat_size_(0),
191 map_{.flat: flat_capacity_ == 0
192 ? nullptr
193 : Arena::CreateArray<KeyValue>(arena: arena_, num_elements: flat_capacity_)} {}
194
195ExtensionSet::~ExtensionSet() {
196 // Deletes all allocated extensions.
197 if (arena_ == nullptr) {
198 ForEach(func: [](int /* number */, Extension& ext) { ext.Free(); });
199 if (PROTOBUF_PREDICT_FALSE(is_large())) {
200 delete map_.large;
201 } else {
202 DeleteFlatMap(flat: map_.flat, flat_capacity: flat_capacity_);
203 }
204 }
205}
206
207void ExtensionSet::DeleteFlatMap(const ExtensionSet::KeyValue* flat,
208 uint16_t flat_capacity) {
209 // Arena::CreateArray already requires a trivially destructible type, but
210 // ensure this constraint is not violated in the future.
211 static_assert(std::is_trivially_destructible<KeyValue>::value,
212 "CreateArray requires a trivially destructible type");
213 // A const-cast is needed, but this is safe as we are about to deallocate the
214 // array.
215 internal::SizedArrayDelete(p: const_cast<KeyValue*>(flat),
216 size: sizeof(*flat) * flat_capacity);
217}
218
219// Defined in extension_set_heavy.cc.
220// void ExtensionSet::AppendToList(const Descriptor* extendee,
221// const DescriptorPool* pool,
222// vector<const FieldDescriptor*>* output) const
223
224bool ExtensionSet::Has(int number) const {
225 const Extension* ext = FindOrNull(key: number);
226 if (ext == nullptr) return false;
227 GOOGLE_DCHECK(!ext->is_repeated);
228 return !ext->is_cleared;
229}
230
231bool ExtensionSet::HasLazy(int number) const {
232 return Has(number) && FindOrNull(key: number)->is_lazy;
233}
234
235int ExtensionSet::NumExtensions() const {
236 int result = 0;
237 ForEach(func: [&result](int /* number */, const Extension& ext) {
238 if (!ext.is_cleared) {
239 ++result;
240 }
241 });
242 return result;
243}
244
245int ExtensionSet::ExtensionSize(int number) const {
246 const Extension* ext = FindOrNull(key: number);
247 return ext == nullptr ? 0 : ext->GetSize();
248}
249
250FieldType ExtensionSet::ExtensionType(int number) const {
251 const Extension* ext = FindOrNull(key: number);
252 if (ext == nullptr) {
253 GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). ";
254 return 0;
255 }
256 if (ext->is_cleared) {
257 GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). ";
258 }
259 return ext->type;
260}
261
262void ExtensionSet::ClearExtension(int number) {
263 Extension* ext = FindOrNull(key: number);
264 if (ext == nullptr) return;
265 ext->Clear();
266}
267
268// ===================================================================
269// Field accessors
270
271namespace {
272
273enum { REPEATED_FIELD, OPTIONAL_FIELD };
274
275} // namespace
276
277#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
278 GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED_FIELD : OPTIONAL_FIELD, LABEL); \
279 GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE)
280
281// -------------------------------------------------------------------
282// Primitives
283
284#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \
285 \
286 LOWERCASE ExtensionSet::Get##CAMELCASE(int number, LOWERCASE default_value) \
287 const { \
288 const Extension* extension = FindOrNull(number); \
289 if (extension == nullptr || extension->is_cleared) { \
290 return default_value; \
291 } else { \
292 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \
293 return extension->LOWERCASE##_value; \
294 } \
295 } \
296 \
297 const LOWERCASE& ExtensionSet::GetRef##CAMELCASE( \
298 int number, const LOWERCASE& default_value) const { \
299 const Extension* extension = FindOrNull(number); \
300 if (extension == nullptr || extension->is_cleared) { \
301 return default_value; \
302 } else { \
303 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \
304 return extension->LOWERCASE##_value; \
305 } \
306 } \
307 \
308 void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \
309 LOWERCASE value, \
310 const FieldDescriptor* descriptor) { \
311 Extension* extension; \
312 if (MaybeNewExtension(number, descriptor, &extension)) { \
313 extension->type = type; \
314 GOOGLE_DCHECK_EQ(cpp_type(extension->type), \
315 WireFormatLite::CPPTYPE_##UPPERCASE); \
316 extension->is_repeated = false; \
317 } else { \
318 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \
319 } \
320 extension->is_cleared = false; \
321 extension->LOWERCASE##_value = value; \
322 } \
323 \
324 LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) \
325 const { \
326 const Extension* extension = FindOrNull(number); \
327 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \
328 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \
329 return extension->repeated_##LOWERCASE##_value->Get(index); \
330 } \
331 \
332 const LOWERCASE& ExtensionSet::GetRefRepeated##CAMELCASE(int number, \
333 int index) const { \
334 const Extension* extension = FindOrNull(number); \
335 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \
336 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \
337 return extension->repeated_##LOWERCASE##_value->Get(index); \
338 } \
339 \
340 void ExtensionSet::SetRepeated##CAMELCASE(int number, int index, \
341 LOWERCASE value) { \
342 Extension* extension = FindOrNull(number); \
343 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \
344 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \
345 extension->repeated_##LOWERCASE##_value->Set(index, value); \
346 } \
347 \
348 void ExtensionSet::Add##CAMELCASE(int number, FieldType type, bool packed, \
349 LOWERCASE value, \
350 const FieldDescriptor* descriptor) { \
351 Extension* extension; \
352 if (MaybeNewExtension(number, descriptor, &extension)) { \
353 extension->type = type; \
354 GOOGLE_DCHECK_EQ(cpp_type(extension->type), \
355 WireFormatLite::CPPTYPE_##UPPERCASE); \
356 extension->is_repeated = true; \
357 extension->is_packed = packed; \
358 extension->repeated_##LOWERCASE##_value = \
359 Arena::CreateMessage<RepeatedField<LOWERCASE>>(arena_); \
360 } else { \
361 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \
362 GOOGLE_DCHECK_EQ(extension->is_packed, packed); \
363 } \
364 extension->repeated_##LOWERCASE##_value->Add(value); \
365 }
366
367PRIMITIVE_ACCESSORS(INT32, int32_t, Int32)
368PRIMITIVE_ACCESSORS(INT64, int64_t, Int64)
369PRIMITIVE_ACCESSORS(UINT32, uint32_t, UInt32)
370PRIMITIVE_ACCESSORS(UINT64, uint64_t, UInt64)
371PRIMITIVE_ACCESSORS(FLOAT, float, Float)
372PRIMITIVE_ACCESSORS(DOUBLE, double, Double)
373PRIMITIVE_ACCESSORS(BOOL, bool, Bool)
374
375#undef PRIMITIVE_ACCESSORS
376
377const void* ExtensionSet::GetRawRepeatedField(int number,
378 const void* default_value) const {
379 const Extension* extension = FindOrNull(key: number);
380 if (extension == nullptr) {
381 return default_value;
382 }
383 // We assume that all the RepeatedField<>* pointers have the same
384 // size and alignment within the anonymous union in Extension.
385 return extension->repeated_int32_t_value;
386}
387
388void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type,
389 bool packed,
390 const FieldDescriptor* desc) {
391 Extension* extension;
392
393 // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this
394 // extension.
395 if (MaybeNewExtension(number, descriptor: desc, result: &extension)) {
396 extension->is_repeated = true;
397 extension->type = field_type;
398 extension->is_packed = packed;
399
400 switch (WireFormatLite::FieldTypeToCppType(
401 type: static_cast<WireFormatLite::FieldType>(field_type))) {
402 case WireFormatLite::CPPTYPE_INT32:
403 extension->repeated_int32_t_value =
404 Arena::CreateMessage<RepeatedField<int32_t>>(arena: arena_);
405 break;
406 case WireFormatLite::CPPTYPE_INT64:
407 extension->repeated_int64_t_value =
408 Arena::CreateMessage<RepeatedField<int64_t>>(arena: arena_);
409 break;
410 case WireFormatLite::CPPTYPE_UINT32:
411 extension->repeated_uint32_t_value =
412 Arena::CreateMessage<RepeatedField<uint32_t>>(arena: arena_);
413 break;
414 case WireFormatLite::CPPTYPE_UINT64:
415 extension->repeated_uint64_t_value =
416 Arena::CreateMessage<RepeatedField<uint64_t>>(arena: arena_);
417 break;
418 case WireFormatLite::CPPTYPE_DOUBLE:
419 extension->repeated_double_value =
420 Arena::CreateMessage<RepeatedField<double>>(arena: arena_);
421 break;
422 case WireFormatLite::CPPTYPE_FLOAT:
423 extension->repeated_float_value =
424 Arena::CreateMessage<RepeatedField<float>>(arena: arena_);
425 break;
426 case WireFormatLite::CPPTYPE_BOOL:
427 extension->repeated_bool_value =
428 Arena::CreateMessage<RepeatedField<bool>>(arena: arena_);
429 break;
430 case WireFormatLite::CPPTYPE_ENUM:
431 extension->repeated_enum_value =
432 Arena::CreateMessage<RepeatedField<int>>(arena: arena_);
433 break;
434 case WireFormatLite::CPPTYPE_STRING:
435 extension->repeated_string_value =
436 Arena::CreateMessage<RepeatedPtrField<std::string>>(arena: arena_);
437 break;
438 case WireFormatLite::CPPTYPE_MESSAGE:
439 extension->repeated_message_value =
440 Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena: arena_);
441 break;
442 }
443 }
444
445 // We assume that all the RepeatedField<>* pointers have the same
446 // size and alignment within the anonymous union in Extension.
447 return extension->repeated_int32_t_value;
448}
449
450// Compatible version using old call signature. Does not create extensions when
451// the don't already exist; instead, just GOOGLE_CHECK-fails.
452void* ExtensionSet::MutableRawRepeatedField(int number) {
453 Extension* extension = FindOrNull(key: number);
454 GOOGLE_CHECK(extension != nullptr) << "Extension not found.";
455 // We assume that all the RepeatedField<>* pointers have the same
456 // size and alignment within the anonymous union in Extension.
457 return extension->repeated_int32_t_value;
458}
459
460// -------------------------------------------------------------------
461// Enums
462
463int ExtensionSet::GetEnum(int number, int default_value) const {
464 const Extension* extension = FindOrNull(key: number);
465 if (extension == nullptr || extension->is_cleared) {
466 // Not present. Return the default value.
467 return default_value;
468 } else {
469 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM);
470 return extension->enum_value;
471 }
472}
473
474const int& ExtensionSet::GetRefEnum(int number,
475 const int& default_value) const {
476 const Extension* extension = FindOrNull(key: number);
477 if (extension == nullptr || extension->is_cleared) {
478 // Not present. Return the default value.
479 return default_value;
480 } else {
481 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM);
482 return extension->enum_value;
483 }
484}
485
486void ExtensionSet::SetEnum(int number, FieldType type, int value,
487 const FieldDescriptor* descriptor) {
488 Extension* extension;
489 if (MaybeNewExtension(number, descriptor, result: &extension)) {
490 extension->type = type;
491 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
492 extension->is_repeated = false;
493 } else {
494 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM);
495 }
496 extension->is_cleared = false;
497 extension->enum_value = value;
498}
499
500int ExtensionSet::GetRepeatedEnum(int number, int index) const {
501 const Extension* extension = FindOrNull(key: number);
502 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
503 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM);
504 return extension->repeated_enum_value->Get(index);
505}
506
507const int& ExtensionSet::GetRefRepeatedEnum(int number, int index) const {
508 const Extension* extension = FindOrNull(key: number);
509 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
510 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM);
511 return extension->repeated_enum_value->Get(index);
512}
513
514void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
515 Extension* extension = FindOrNull(key: number);
516 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
517 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM);
518 extension->repeated_enum_value->Set(index, value);
519}
520
521void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value,
522 const FieldDescriptor* descriptor) {
523 Extension* extension;
524 if (MaybeNewExtension(number, descriptor, result: &extension)) {
525 extension->type = type;
526 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
527 extension->is_repeated = true;
528 extension->is_packed = packed;
529 extension->repeated_enum_value =
530 Arena::CreateMessage<RepeatedField<int>>(arena: arena_);
531 } else {
532 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM);
533 GOOGLE_DCHECK_EQ(extension->is_packed, packed);
534 }
535 extension->repeated_enum_value->Add(value);
536}
537
538// -------------------------------------------------------------------
539// Strings
540
541const std::string& ExtensionSet::GetString(
542 int number, const std::string& default_value) const {
543 const Extension* extension = FindOrNull(key: number);
544 if (extension == nullptr || extension->is_cleared) {
545 // Not present. Return the default value.
546 return default_value;
547 } else {
548 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING);
549 return *extension->string_value;
550 }
551}
552
553std::string* ExtensionSet::MutableString(int number, FieldType type,
554 const FieldDescriptor* descriptor) {
555 Extension* extension;
556 if (MaybeNewExtension(number, descriptor, result: &extension)) {
557 extension->type = type;
558 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
559 extension->is_repeated = false;
560 extension->string_value = Arena::Create<std::string>(arena: arena_);
561 } else {
562 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING);
563 }
564 extension->is_cleared = false;
565 return extension->string_value;
566}
567
568const std::string& ExtensionSet::GetRepeatedString(int number,
569 int index) const {
570 const Extension* extension = FindOrNull(key: number);
571 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
572 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING);
573 return extension->repeated_string_value->Get(index);
574}
575
576std::string* ExtensionSet::MutableRepeatedString(int number, int index) {
577 Extension* extension = FindOrNull(key: number);
578 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
579 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING);
580 return extension->repeated_string_value->Mutable(index);
581}
582
583std::string* ExtensionSet::AddString(int number, FieldType type,
584 const FieldDescriptor* descriptor) {
585 Extension* extension;
586 if (MaybeNewExtension(number, descriptor, result: &extension)) {
587 extension->type = type;
588 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
589 extension->is_repeated = true;
590 extension->is_packed = false;
591 extension->repeated_string_value =
592 Arena::CreateMessage<RepeatedPtrField<std::string>>(arena: arena_);
593 } else {
594 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING);
595 }
596 return extension->repeated_string_value->Add();
597}
598
599// -------------------------------------------------------------------
600// Messages
601
602const MessageLite& ExtensionSet::GetMessage(
603 int number, const MessageLite& default_value) const {
604 const Extension* extension = FindOrNull(key: number);
605 if (extension == nullptr) {
606 // Not present. Return the default value.
607 return default_value;
608 } else {
609 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
610 if (extension->is_lazy) {
611 return extension->lazymessage_value->GetMessage(prototype: default_value, arena: arena_);
612 } else {
613 return *extension->message_value;
614 }
615 }
616}
617
618// Defined in extension_set_heavy.cc.
619// const MessageLite& ExtensionSet::GetMessage(int number,
620// const Descriptor* message_type,
621// MessageFactory* factory) const
622
623MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
624 const MessageLite& prototype,
625 const FieldDescriptor* descriptor) {
626 Extension* extension;
627 if (MaybeNewExtension(number, descriptor, result: &extension)) {
628 extension->type = type;
629 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
630 extension->is_repeated = false;
631 extension->is_lazy = false;
632 extension->message_value = prototype.New(arena: arena_);
633 extension->is_cleared = false;
634 return extension->message_value;
635 } else {
636 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
637 extension->is_cleared = false;
638 if (extension->is_lazy) {
639 return extension->lazymessage_value->MutableMessage(prototype, arena: arena_);
640 } else {
641 return extension->message_value;
642 }
643 }
644}
645
646// Defined in extension_set_heavy.cc.
647// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
648// const Descriptor* message_type,
649// MessageFactory* factory)
650
651void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
652 const FieldDescriptor* descriptor,
653 MessageLite* message) {
654 if (message == nullptr) {
655 ClearExtension(number);
656 return;
657 }
658 GOOGLE_DCHECK(message->GetOwningArena() == nullptr ||
659 message->GetOwningArena() == arena_);
660 Arena* message_arena = message->GetOwningArena();
661 Extension* extension;
662 if (MaybeNewExtension(number, descriptor, result: &extension)) {
663 extension->type = type;
664 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
665 extension->is_repeated = false;
666 extension->is_lazy = false;
667 if (message_arena == arena_) {
668 extension->message_value = message;
669 } else if (message_arena == nullptr) {
670 extension->message_value = message;
671 arena_->Own(object: message); // not nullptr because not equal to message_arena
672 } else {
673 extension->message_value = message->New(arena: arena_);
674 extension->message_value->CheckTypeAndMergeFrom(other: *message);
675 }
676 } else {
677 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
678 if (extension->is_lazy) {
679 extension->lazymessage_value->SetAllocatedMessage(message, arena: arena_);
680 } else {
681 if (arena_ == nullptr) {
682 delete extension->message_value;
683 }
684 if (message_arena == arena_) {
685 extension->message_value = message;
686 } else if (message_arena == nullptr) {
687 extension->message_value = message;
688 arena_->Own(object: message); // not nullptr because not equal to message_arena
689 } else {
690 extension->message_value = message->New(arena: arena_);
691 extension->message_value->CheckTypeAndMergeFrom(other: *message);
692 }
693 }
694 }
695 extension->is_cleared = false;
696}
697
698void ExtensionSet::UnsafeArenaSetAllocatedMessage(
699 int number, FieldType type, const FieldDescriptor* descriptor,
700 MessageLite* message) {
701 if (message == nullptr) {
702 ClearExtension(number);
703 return;
704 }
705 Extension* extension;
706 if (MaybeNewExtension(number, descriptor, result: &extension)) {
707 extension->type = type;
708 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
709 extension->is_repeated = false;
710 extension->is_lazy = false;
711 extension->message_value = message;
712 } else {
713 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
714 if (extension->is_lazy) {
715 extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message,
716 arena: arena_);
717 } else {
718 if (arena_ == nullptr) {
719 delete extension->message_value;
720 }
721 extension->message_value = message;
722 }
723 }
724 extension->is_cleared = false;
725}
726
727MessageLite* ExtensionSet::ReleaseMessage(int number,
728 const MessageLite& prototype) {
729 Extension* extension = FindOrNull(key: number);
730 if (extension == nullptr) {
731 // Not present. Return nullptr.
732 return nullptr;
733 } else {
734 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
735 MessageLite* ret = nullptr;
736 if (extension->is_lazy) {
737 ret = extension->lazymessage_value->ReleaseMessage(prototype, arena: arena_);
738 if (arena_ == nullptr) {
739 delete extension->lazymessage_value;
740 }
741 } else {
742 if (arena_ == nullptr) {
743 ret = extension->message_value;
744 } else {
745 // ReleaseMessage() always returns a heap-allocated message, and we are
746 // on an arena, so we need to make a copy of this message to return.
747 ret = extension->message_value->New();
748 ret->CheckTypeAndMergeFrom(other: *extension->message_value);
749 }
750 }
751 Erase(key: number);
752 return ret;
753 }
754}
755
756MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
757 int number, const MessageLite& prototype) {
758 Extension* extension = FindOrNull(key: number);
759 if (extension == nullptr) {
760 // Not present. Return nullptr.
761 return nullptr;
762 } else {
763 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
764 MessageLite* ret = nullptr;
765 if (extension->is_lazy) {
766 ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype,
767 arena: arena_);
768 if (arena_ == nullptr) {
769 delete extension->lazymessage_value;
770 }
771 } else {
772 ret = extension->message_value;
773 }
774 Erase(key: number);
775 return ret;
776 }
777}
778
779// Defined in extension_set_heavy.cc.
780// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
781// MessageFactory* factory);
782
783const MessageLite& ExtensionSet::GetRepeatedMessage(int number,
784 int index) const {
785 const Extension* extension = FindOrNull(key: number);
786 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
787 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE);
788 return extension->repeated_message_value->Get(index);
789}
790
791MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
792 Extension* extension = FindOrNull(key: number);
793 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
794 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE);
795 return extension->repeated_message_value->Mutable(index);
796}
797
798MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
799 const MessageLite& prototype,
800 const FieldDescriptor* descriptor) {
801 Extension* extension;
802 if (MaybeNewExtension(number, descriptor, result: &extension)) {
803 extension->type = type;
804 GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
805 extension->is_repeated = true;
806 extension->repeated_message_value =
807 Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena: arena_);
808 } else {
809 GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE);
810 }
811
812 // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
813 // allocate an abstract object, so we have to be tricky.
814 MessageLite* result = reinterpret_cast<internal::RepeatedPtrFieldBase*>(
815 extension->repeated_message_value)
816 ->AddFromCleared<GenericTypeHandler<MessageLite>>();
817 if (result == nullptr) {
818 result = prototype.New(arena: arena_);
819 extension->repeated_message_value->AddAllocated(value: result);
820 }
821 return result;
822}
823
824// Defined in extension_set_heavy.cc.
825// MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
826// const Descriptor* message_type,
827// MessageFactory* factory)
828
829#undef GOOGLE_DCHECK_TYPE
830
831void ExtensionSet::RemoveLast(int number) {
832 Extension* extension = FindOrNull(key: number);
833 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
834 GOOGLE_DCHECK(extension->is_repeated);
835
836 switch (cpp_type(type: extension->type)) {
837 case WireFormatLite::CPPTYPE_INT32:
838 extension->repeated_int32_t_value->RemoveLast();
839 break;
840 case WireFormatLite::CPPTYPE_INT64:
841 extension->repeated_int64_t_value->RemoveLast();
842 break;
843 case WireFormatLite::CPPTYPE_UINT32:
844 extension->repeated_uint32_t_value->RemoveLast();
845 break;
846 case WireFormatLite::CPPTYPE_UINT64:
847 extension->repeated_uint64_t_value->RemoveLast();
848 break;
849 case WireFormatLite::CPPTYPE_FLOAT:
850 extension->repeated_float_value->RemoveLast();
851 break;
852 case WireFormatLite::CPPTYPE_DOUBLE:
853 extension->repeated_double_value->RemoveLast();
854 break;
855 case WireFormatLite::CPPTYPE_BOOL:
856 extension->repeated_bool_value->RemoveLast();
857 break;
858 case WireFormatLite::CPPTYPE_ENUM:
859 extension->repeated_enum_value->RemoveLast();
860 break;
861 case WireFormatLite::CPPTYPE_STRING:
862 extension->repeated_string_value->RemoveLast();
863 break;
864 case WireFormatLite::CPPTYPE_MESSAGE:
865 extension->repeated_message_value->RemoveLast();
866 break;
867 }
868}
869
870MessageLite* ExtensionSet::ReleaseLast(int number) {
871 Extension* extension = FindOrNull(key: number);
872 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
873 GOOGLE_DCHECK(extension->is_repeated);
874 GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE);
875 return extension->repeated_message_value->ReleaseLast();
876}
877
878MessageLite* ExtensionSet::UnsafeArenaReleaseLast(int number) {
879 Extension* extension = FindOrNull(key: number);
880 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
881 GOOGLE_DCHECK(extension->is_repeated);
882 GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE);
883 return extension->repeated_message_value->UnsafeArenaReleaseLast();
884}
885
886void ExtensionSet::SwapElements(int number, int index1, int index2) {
887 Extension* extension = FindOrNull(key: number);
888 GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
889 GOOGLE_DCHECK(extension->is_repeated);
890
891 switch (cpp_type(type: extension->type)) {
892 case WireFormatLite::CPPTYPE_INT32:
893 extension->repeated_int32_t_value->SwapElements(index1, index2);
894 break;
895 case WireFormatLite::CPPTYPE_INT64:
896 extension->repeated_int64_t_value->SwapElements(index1, index2);
897 break;
898 case WireFormatLite::CPPTYPE_UINT32:
899 extension->repeated_uint32_t_value->SwapElements(index1, index2);
900 break;
901 case WireFormatLite::CPPTYPE_UINT64:
902 extension->repeated_uint64_t_value->SwapElements(index1, index2);
903 break;
904 case WireFormatLite::CPPTYPE_FLOAT:
905 extension->repeated_float_value->SwapElements(index1, index2);
906 break;
907 case WireFormatLite::CPPTYPE_DOUBLE:
908 extension->repeated_double_value->SwapElements(index1, index2);
909 break;
910 case WireFormatLite::CPPTYPE_BOOL:
911 extension->repeated_bool_value->SwapElements(index1, index2);
912 break;
913 case WireFormatLite::CPPTYPE_ENUM:
914 extension->repeated_enum_value->SwapElements(index1, index2);
915 break;
916 case WireFormatLite::CPPTYPE_STRING:
917 extension->repeated_string_value->SwapElements(index1, index2);
918 break;
919 case WireFormatLite::CPPTYPE_MESSAGE:
920 extension->repeated_message_value->SwapElements(index1, index2);
921 break;
922 }
923}
924
925// ===================================================================
926
927void ExtensionSet::Clear() {
928 ForEach(func: [](int /* number */, Extension& ext) { ext.Clear(); });
929}
930
931namespace {
932// Computes the size of an ExtensionSet union without actually constructing the
933// union. Note that we do not count cleared extensions from the source to be
934// part of the total, because there is no need to allocate space for those. We
935// do include cleared extensions in the destination, though, because those are
936// already allocated and will not be going away.
937template <typename ItX, typename ItY>
938size_t SizeOfUnion(ItX it_dest, ItX end_dest, ItY it_source, ItY end_source) {
939 size_t result = 0;
940 while (it_dest != end_dest && it_source != end_source) {
941 if (it_dest->first < it_source->first) {
942 ++result;
943 ++it_dest;
944 } else if (it_dest->first == it_source->first) {
945 ++result;
946 ++it_dest;
947 ++it_source;
948 } else {
949 if (!it_source->second.is_cleared) {
950 ++result;
951 }
952 ++it_source;
953 }
954 }
955 result += std::distance(it_dest, end_dest);
956 for (; it_source != end_source; ++it_source) {
957 if (!it_source->second.is_cleared) {
958 ++result;
959 }
960 }
961 return result;
962}
963} // namespace
964
965void ExtensionSet::MergeFrom(const MessageLite* extendee,
966 const ExtensionSet& other) {
967 if (PROTOBUF_PREDICT_TRUE(!is_large())) {
968 if (PROTOBUF_PREDICT_TRUE(!other.is_large())) {
969 GrowCapacity(minimum_new_capacity: SizeOfUnion(it_dest: flat_begin(), end_dest: flat_end(), it_source: other.flat_begin(),
970 end_source: other.flat_end()));
971 } else {
972 GrowCapacity(minimum_new_capacity: SizeOfUnion(it_dest: flat_begin(), end_dest: flat_end(),
973 it_source: other.map_.large->begin(),
974 end_source: other.map_.large->end()));
975 }
976 }
977 other.ForEach(func: [extendee, this, &other](int number, const Extension& ext) {
978 this->InternalExtensionMergeFrom(extendee, number, other_extension: ext, other_arena: other.arena_);
979 });
980}
981
982void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
983 int number,
984 const Extension& other_extension,
985 Arena* other_arena) {
986 if (other_extension.is_repeated) {
987 Extension* extension;
988 bool is_new =
989 MaybeNewExtension(number, descriptor: other_extension.descriptor, result: &extension);
990 if (is_new) {
991 // Extension did not already exist in set.
992 extension->type = other_extension.type;
993 extension->is_packed = other_extension.is_packed;
994 extension->is_repeated = true;
995 } else {
996 GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
997 GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
998 GOOGLE_DCHECK(extension->is_repeated);
999 }
1000
1001 switch (cpp_type(type: other_extension.type)) {
1002#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \
1003 case WireFormatLite::CPPTYPE_##UPPERCASE: \
1004 if (is_new) { \
1005 extension->repeated_##LOWERCASE##_value = \
1006 Arena::CreateMessage<REPEATED_TYPE>(arena_); \
1007 } \
1008 extension->repeated_##LOWERCASE##_value->MergeFrom( \
1009 *other_extension.repeated_##LOWERCASE##_value); \
1010 break;
1011
1012 HANDLE_TYPE(INT32, int32_t, RepeatedField<int32_t>);
1013 HANDLE_TYPE(INT64, int64_t, RepeatedField<int64_t>);
1014 HANDLE_TYPE(UINT32, uint32_t, RepeatedField<uint32_t>);
1015 HANDLE_TYPE(UINT64, uint64_t, RepeatedField<uint64_t>);
1016 HANDLE_TYPE(FLOAT, float, RepeatedField<float>);
1017 HANDLE_TYPE(DOUBLE, double, RepeatedField<double>);
1018 HANDLE_TYPE(BOOL, bool, RepeatedField<bool>);
1019 HANDLE_TYPE(ENUM, enum, RepeatedField<int>);
1020 HANDLE_TYPE(STRING, string, RepeatedPtrField<std::string>);
1021#undef HANDLE_TYPE
1022
1023 case WireFormatLite::CPPTYPE_MESSAGE:
1024 if (is_new) {
1025 extension->repeated_message_value =
1026 Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena: arena_);
1027 }
1028 // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
1029 // it would attempt to allocate new objects.
1030 RepeatedPtrField<MessageLite>* other_repeated_message =
1031 other_extension.repeated_message_value;
1032 for (int i = 0; i < other_repeated_message->size(); i++) {
1033 const MessageLite& other_message = other_repeated_message->Get(index: i);
1034 MessageLite* target =
1035 reinterpret_cast<internal::RepeatedPtrFieldBase*>(
1036 extension->repeated_message_value)
1037 ->AddFromCleared<GenericTypeHandler<MessageLite>>();
1038 if (target == nullptr) {
1039 target = other_message.New(arena: arena_);
1040 extension->repeated_message_value->AddAllocated(value: target);
1041 }
1042 target->CheckTypeAndMergeFrom(other: other_message);
1043 }
1044 break;
1045 }
1046 } else {
1047 if (!other_extension.is_cleared) {
1048 switch (cpp_type(type: other_extension.type)) {
1049#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
1050 case WireFormatLite::CPPTYPE_##UPPERCASE: \
1051 Set##CAMELCASE(number, other_extension.type, \
1052 other_extension.LOWERCASE##_value, \
1053 other_extension.descriptor); \
1054 break;
1055
1056 HANDLE_TYPE(INT32, int32_t, Int32);
1057 HANDLE_TYPE(INT64, int64_t, Int64);
1058 HANDLE_TYPE(UINT32, uint32_t, UInt32);
1059 HANDLE_TYPE(UINT64, uint64_t, UInt64);
1060 HANDLE_TYPE(FLOAT, float, Float);
1061 HANDLE_TYPE(DOUBLE, double, Double);
1062 HANDLE_TYPE(BOOL, bool, Bool);
1063 HANDLE_TYPE(ENUM, enum, Enum);
1064#undef HANDLE_TYPE
1065 case WireFormatLite::CPPTYPE_STRING:
1066 SetString(number, type: other_extension.type, value: *other_extension.string_value,
1067 descriptor: other_extension.descriptor);
1068 break;
1069 case WireFormatLite::CPPTYPE_MESSAGE: {
1070 Extension* extension;
1071 bool is_new =
1072 MaybeNewExtension(number, descriptor: other_extension.descriptor, result: &extension);
1073 if (is_new) {
1074 extension->type = other_extension.type;
1075 extension->is_packed = other_extension.is_packed;
1076 extension->is_repeated = false;
1077 if (other_extension.is_lazy) {
1078 extension->is_lazy = true;
1079 extension->lazymessage_value =
1080 other_extension.lazymessage_value->New(arena: arena_);
1081 extension->lazymessage_value->MergeFrom(
1082 prototype: GetPrototypeForLazyMessage(extendee, number),
1083 other: *other_extension.lazymessage_value, arena: arena_);
1084 } else {
1085 extension->is_lazy = false;
1086 extension->message_value =
1087 other_extension.message_value->New(arena: arena_);
1088 extension->message_value->CheckTypeAndMergeFrom(
1089 other: *other_extension.message_value);
1090 }
1091 } else {
1092 GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
1093 GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
1094 GOOGLE_DCHECK(!extension->is_repeated);
1095 if (other_extension.is_lazy) {
1096 if (extension->is_lazy) {
1097 extension->lazymessage_value->MergeFrom(
1098 prototype: GetPrototypeForLazyMessage(extendee, number),
1099 other: *other_extension.lazymessage_value, arena: arena_);
1100 } else {
1101 extension->message_value->CheckTypeAndMergeFrom(
1102 other: other_extension.lazymessage_value->GetMessage(
1103 prototype: *extension->message_value, arena: other_arena));
1104 }
1105 } else {
1106 if (extension->is_lazy) {
1107 extension->lazymessage_value
1108 ->MutableMessage(prototype: *other_extension.message_value, arena: arena_)
1109 ->CheckTypeAndMergeFrom(other: *other_extension.message_value);
1110 } else {
1111 extension->message_value->CheckTypeAndMergeFrom(
1112 other: *other_extension.message_value);
1113 }
1114 }
1115 }
1116 extension->is_cleared = false;
1117 break;
1118 }
1119 }
1120 }
1121 }
1122}
1123
1124void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) {
1125#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
1126 if (GetArena() != nullptr && GetArena() == other->GetArena()) {
1127#else // PROTOBUF_FORCE_COPY_IN_SWAP
1128 if (GetArena() == other->GetArena()) {
1129#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
1130 InternalSwap(other);
1131 } else {
1132 // TODO(cfallin, rohananil): We maybe able to optimize a case where we are
1133 // swapping from heap to arena-allocated extension set, by just Own()'ing
1134 // the extensions.
1135 ExtensionSet extension_set;
1136 extension_set.MergeFrom(extendee, other: *other);
1137 other->Clear();
1138 other->MergeFrom(extendee, other: *this);
1139 Clear();
1140 MergeFrom(extendee, other: extension_set);
1141 }
1142}
1143
1144void ExtensionSet::InternalSwap(ExtensionSet* other) {
1145 using std::swap;
1146 swap(a&: arena_, b&: other->arena_);
1147 swap(a&: flat_capacity_, b&: other->flat_capacity_);
1148 swap(a&: flat_size_, b&: other->flat_size_);
1149 swap(a&: map_, b&: other->map_);
1150}
1151
1152void ExtensionSet::SwapExtension(const MessageLite* extendee,
1153 ExtensionSet* other, int number) {
1154 if (this == other) return;
1155
1156 if (GetArena() == other->GetArena()) {
1157 UnsafeShallowSwapExtension(other, number);
1158 return;
1159 }
1160
1161 Extension* this_ext = FindOrNull(key: number);
1162 Extension* other_ext = other->FindOrNull(key: number);
1163
1164 if (this_ext == other_ext) return;
1165
1166 if (this_ext != nullptr && other_ext != nullptr) {
1167 // TODO(cfallin, rohananil): We could further optimize these cases,
1168 // especially avoid creation of ExtensionSet, and move MergeFrom logic
1169 // into Extensions itself (which takes arena as an argument).
1170 // We do it this way to reuse the copy-across-arenas logic already
1171 // implemented in ExtensionSet's MergeFrom.
1172 ExtensionSet temp;
1173 temp.InternalExtensionMergeFrom(extendee, number, other_extension: *other_ext,
1174 other_arena: other->GetArena());
1175 Extension* temp_ext = temp.FindOrNull(key: number);
1176
1177 other_ext->Clear();
1178 other->InternalExtensionMergeFrom(extendee, number, other_extension: *this_ext,
1179 other_arena: this->GetArena());
1180 this_ext->Clear();
1181 InternalExtensionMergeFrom(extendee, number, other_extension: *temp_ext, other_arena: temp.GetArena());
1182 } else if (this_ext == nullptr) {
1183 InternalExtensionMergeFrom(extendee, number, other_extension: *other_ext, other_arena: other->GetArena());
1184 if (other->GetArena() == nullptr) other_ext->Free();
1185 other->Erase(key: number);
1186 } else {
1187 other->InternalExtensionMergeFrom(extendee, number, other_extension: *this_ext,
1188 other_arena: this->GetArena());
1189 if (GetArena() == nullptr) this_ext->Free();
1190 Erase(key: number);
1191 }
1192}
1193
1194void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) {
1195 if (this == other) return;
1196
1197 Extension* this_ext = FindOrNull(key: number);
1198 Extension* other_ext = other->FindOrNull(key: number);
1199
1200 if (this_ext == other_ext) return;
1201
1202 GOOGLE_DCHECK_EQ(GetArena(), other->GetArena());
1203
1204 if (this_ext != nullptr && other_ext != nullptr) {
1205 std::swap(a&: *this_ext, b&: *other_ext);
1206 } else if (this_ext == nullptr) {
1207 *Insert(key: number).first = *other_ext;
1208 other->Erase(key: number);
1209 } else {
1210 *other->Insert(key: number).first = *this_ext;
1211 Erase(key: number);
1212 }
1213}
1214
1215bool ExtensionSet::IsInitialized() const {
1216 // Extensions are never required. However, we need to check that all
1217 // embedded messages are initialized.
1218 if (PROTOBUF_PREDICT_FALSE(is_large())) {
1219 for (const auto& kv : *map_.large) {
1220 if (!kv.second.IsInitialized()) return false;
1221 }
1222 return true;
1223 }
1224 for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) {
1225 if (!it->second.IsInitialized()) return false;
1226 }
1227 return true;
1228}
1229
1230const char* ExtensionSet::ParseField(uint64_t tag, const char* ptr,
1231 const MessageLite* extendee,
1232 internal::InternalMetadata* metadata,
1233 internal::ParseContext* ctx) {
1234 GeneratedExtensionFinder finder(extendee);
1235 int number = tag >> 3;
1236 bool was_packed_on_wire;
1237 ExtensionInfo extension;
1238 if (!FindExtensionInfoFromFieldNumber(wire_type: tag & 7, field_number: number, extension_finder: &finder, extension: &extension,
1239 was_packed_on_wire: &was_packed_on_wire)) {
1240 return UnknownFieldParse(
1241 tag, unknown: metadata->mutable_unknown_fields<std::string>(), ptr, ctx);
1242 }
1243 return ParseFieldWithExtensionInfo<std::string>(
1244 number, was_packed_on_wire, extension, metadata, ptr, ctx);
1245}
1246
1247const char* ExtensionSet::ParseMessageSetItem(
1248 const char* ptr, const MessageLite* extendee,
1249 internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
1250 return ParseMessageSetItemTmpl<MessageLite, std::string>(ptr, extendee,
1251 metadata, ctx);
1252}
1253
1254uint8_t* ExtensionSet::_InternalSerializeImpl(
1255 const MessageLite* extendee, int start_field_number, int end_field_number,
1256 uint8_t* target, io::EpsCopyOutputStream* stream) const {
1257 if (PROTOBUF_PREDICT_FALSE(is_large())) {
1258 const auto& end = map_.large->end();
1259 for (auto it = map_.large->lower_bound(x: start_field_number);
1260 it != end && it->first < end_field_number; ++it) {
1261 target = it->second.InternalSerializeFieldWithCachedSizesToArray(
1262 extendee, extension_set: this, number: it->first, target, stream);
1263 }
1264 return target;
1265 }
1266 const KeyValue* end = flat_end();
1267 for (const KeyValue* it = std::lower_bound(
1268 first: flat_begin(), last: end, val: start_field_number, comp: KeyValue::FirstComparator());
1269 it != end && it->first < end_field_number; ++it) {
1270 target = it->second.InternalSerializeFieldWithCachedSizesToArray(
1271 extendee, extension_set: this, number: it->first, target, stream);
1272 }
1273 return target;
1274}
1275
1276uint8_t* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
1277 const MessageLite* extendee, uint8_t* target,
1278 io::EpsCopyOutputStream* stream) const {
1279 const ExtensionSet* extension_set = this;
1280 ForEach(func: [&target, extendee, stream, extension_set](int number,
1281 const Extension& ext) {
1282 target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray(
1283 extendee, extension_set, number, target, stream);
1284 });
1285 return target;
1286}
1287
1288size_t ExtensionSet::ByteSize() const {
1289 size_t total_size = 0;
1290 ForEach(func: [&total_size](int number, const Extension& ext) {
1291 total_size += ext.ByteSize(number);
1292 });
1293 return total_size;
1294}
1295
1296// Defined in extension_set_heavy.cc.
1297// int ExtensionSet::SpaceUsedExcludingSelf() const
1298
1299bool ExtensionSet::MaybeNewExtension(int number,
1300 const FieldDescriptor* descriptor,
1301 Extension** result) {
1302 bool extension_is_new = false;
1303 std::tie(args&: *result, args&: extension_is_new) = Insert(key: number);
1304 (*result)->descriptor = descriptor;
1305 return extension_is_new;
1306}
1307
1308// ===================================================================
1309// Methods of ExtensionSet::Extension
1310
1311void ExtensionSet::Extension::Clear() {
1312 if (is_repeated) {
1313 switch (cpp_type(type)) {
1314#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1315 case WireFormatLite::CPPTYPE_##UPPERCASE: \
1316 repeated_##LOWERCASE##_value->Clear(); \
1317 break
1318
1319 HANDLE_TYPE(INT32, int32_t);
1320 HANDLE_TYPE(INT64, int64_t);
1321 HANDLE_TYPE(UINT32, uint32_t);
1322 HANDLE_TYPE(UINT64, uint64_t);
1323 HANDLE_TYPE(FLOAT, float);
1324 HANDLE_TYPE(DOUBLE, double);
1325 HANDLE_TYPE(BOOL, bool);
1326 HANDLE_TYPE(ENUM, enum);
1327 HANDLE_TYPE(STRING, string);
1328 HANDLE_TYPE(MESSAGE, message);
1329#undef HANDLE_TYPE
1330 }
1331 } else {
1332 if (!is_cleared) {
1333 switch (cpp_type(type)) {
1334 case WireFormatLite::CPPTYPE_STRING:
1335 string_value->clear();
1336 break;
1337 case WireFormatLite::CPPTYPE_MESSAGE:
1338 if (is_lazy) {
1339 lazymessage_value->Clear();
1340 } else {
1341 message_value->Clear();
1342 }
1343 break;
1344 default:
1345 // No need to do anything. Get*() will return the default value
1346 // as long as is_cleared is true and Set*() will overwrite the
1347 // previous value.
1348 break;
1349 }
1350
1351 is_cleared = true;
1352 }
1353 }
1354}
1355
1356size_t ExtensionSet::Extension::ByteSize(int number) const {
1357 size_t result = 0;
1358
1359 if (is_repeated) {
1360 if (is_packed) {
1361 switch (real_type(type)) {
1362#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1363 case WireFormatLite::TYPE_##UPPERCASE: \
1364 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
1365 result += WireFormatLite::CAMELCASE##Size( \
1366 repeated_##LOWERCASE##_value->Get(i)); \
1367 } \
1368 break
1369
1370 HANDLE_TYPE(INT32, Int32, int32_t);
1371 HANDLE_TYPE(INT64, Int64, int64_t);
1372 HANDLE_TYPE(UINT32, UInt32, uint32_t);
1373 HANDLE_TYPE(UINT64, UInt64, uint64_t);
1374 HANDLE_TYPE(SINT32, SInt32, int32_t);
1375 HANDLE_TYPE(SINT64, SInt64, int64_t);
1376 HANDLE_TYPE(ENUM, Enum, enum);
1377#undef HANDLE_TYPE
1378
1379 // Stuff with fixed size.
1380#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1381 case WireFormatLite::TYPE_##UPPERCASE: \
1382 result += WireFormatLite::k##CAMELCASE##Size * \
1383 FromIntSize(repeated_##LOWERCASE##_value->size()); \
1384 break
1385 HANDLE_TYPE(FIXED32, Fixed32, uint32_t);
1386 HANDLE_TYPE(FIXED64, Fixed64, uint64_t);
1387 HANDLE_TYPE(SFIXED32, SFixed32, int32_t);
1388 HANDLE_TYPE(SFIXED64, SFixed64, int64_t);
1389 HANDLE_TYPE(FLOAT, Float, float);
1390 HANDLE_TYPE(DOUBLE, Double, double);
1391 HANDLE_TYPE(BOOL, Bool, bool);
1392#undef HANDLE_TYPE
1393
1394 case WireFormatLite::TYPE_STRING:
1395 case WireFormatLite::TYPE_BYTES:
1396 case WireFormatLite::TYPE_GROUP:
1397 case WireFormatLite::TYPE_MESSAGE:
1398 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
1399 break;
1400 }
1401
1402 cached_size = ToCachedSize(size: result);
1403 if (result > 0) {
1404 result += io::CodedOutputStream::VarintSize32(value: result);
1405 result += io::CodedOutputStream::VarintSize32(value: WireFormatLite::MakeTag(
1406 field_number: number, type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
1407 }
1408 } else {
1409 size_t tag_size = WireFormatLite::TagSize(field_number: number, type: real_type(type));
1410
1411 switch (real_type(type)) {
1412#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1413 case WireFormatLite::TYPE_##UPPERCASE: \
1414 result += tag_size * FromIntSize(repeated_##LOWERCASE##_value->size()); \
1415 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
1416 result += WireFormatLite::CAMELCASE##Size( \
1417 repeated_##LOWERCASE##_value->Get(i)); \
1418 } \
1419 break
1420
1421 HANDLE_TYPE(INT32, Int32, int32_t);
1422 HANDLE_TYPE(INT64, Int64, int64_t);
1423 HANDLE_TYPE(UINT32, UInt32, uint32_t);
1424 HANDLE_TYPE(UINT64, UInt64, uint64_t);
1425 HANDLE_TYPE(SINT32, SInt32, int32_t);
1426 HANDLE_TYPE(SINT64, SInt64, int64_t);
1427 HANDLE_TYPE(STRING, String, string);
1428 HANDLE_TYPE(BYTES, Bytes, string);
1429 HANDLE_TYPE(ENUM, Enum, enum);
1430 HANDLE_TYPE(GROUP, Group, message);
1431 HANDLE_TYPE(MESSAGE, Message, message);
1432#undef HANDLE_TYPE
1433
1434 // Stuff with fixed size.
1435#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1436 case WireFormatLite::TYPE_##UPPERCASE: \
1437 result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \
1438 FromIntSize(repeated_##LOWERCASE##_value->size()); \
1439 break
1440 HANDLE_TYPE(FIXED32, Fixed32, uint32_t);
1441 HANDLE_TYPE(FIXED64, Fixed64, uint64_t);
1442 HANDLE_TYPE(SFIXED32, SFixed32, int32_t);
1443 HANDLE_TYPE(SFIXED64, SFixed64, int64_t);
1444 HANDLE_TYPE(FLOAT, Float, float);
1445 HANDLE_TYPE(DOUBLE, Double, double);
1446 HANDLE_TYPE(BOOL, Bool, bool);
1447#undef HANDLE_TYPE
1448 }
1449 }
1450 } else if (!is_cleared) {
1451 result += WireFormatLite::TagSize(field_number: number, type: real_type(type));
1452 switch (real_type(type)) {
1453#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1454 case WireFormatLite::TYPE_##UPPERCASE: \
1455 result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \
1456 break
1457
1458 HANDLE_TYPE(INT32, Int32, int32_t_value);
1459 HANDLE_TYPE(INT64, Int64, int64_t_value);
1460 HANDLE_TYPE(UINT32, UInt32, uint32_t_value);
1461 HANDLE_TYPE(UINT64, UInt64, uint64_t_value);
1462 HANDLE_TYPE(SINT32, SInt32, int32_t_value);
1463 HANDLE_TYPE(SINT64, SInt64, int64_t_value);
1464 HANDLE_TYPE(STRING, String, *string_value);
1465 HANDLE_TYPE(BYTES, Bytes, *string_value);
1466 HANDLE_TYPE(ENUM, Enum, enum_value);
1467 HANDLE_TYPE(GROUP, Group, *message_value);
1468#undef HANDLE_TYPE
1469 case WireFormatLite::TYPE_MESSAGE: {
1470 if (is_lazy) {
1471 size_t size = lazymessage_value->ByteSizeLong();
1472 result += io::CodedOutputStream::VarintSize32(value: size) + size;
1473 } else {
1474 result += WireFormatLite::MessageSize(value: *message_value);
1475 }
1476 break;
1477 }
1478
1479 // Stuff with fixed size.
1480#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \
1481 case WireFormatLite::TYPE_##UPPERCASE: \
1482 result += WireFormatLite::k##CAMELCASE##Size; \
1483 break
1484 HANDLE_TYPE(FIXED32, Fixed32);
1485 HANDLE_TYPE(FIXED64, Fixed64);
1486 HANDLE_TYPE(SFIXED32, SFixed32);
1487 HANDLE_TYPE(SFIXED64, SFixed64);
1488 HANDLE_TYPE(FLOAT, Float);
1489 HANDLE_TYPE(DOUBLE, Double);
1490 HANDLE_TYPE(BOOL, Bool);
1491#undef HANDLE_TYPE
1492 }
1493 }
1494
1495 return result;
1496}
1497
1498int ExtensionSet::Extension::GetSize() const {
1499 GOOGLE_DCHECK(is_repeated);
1500 switch (cpp_type(type)) {
1501#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1502 case WireFormatLite::CPPTYPE_##UPPERCASE: \
1503 return repeated_##LOWERCASE##_value->size()
1504
1505 HANDLE_TYPE(INT32, int32_t);
1506 HANDLE_TYPE(INT64, int64_t);
1507 HANDLE_TYPE(UINT32, uint32_t);
1508 HANDLE_TYPE(UINT64, uint64_t);
1509 HANDLE_TYPE(FLOAT, float);
1510 HANDLE_TYPE(DOUBLE, double);
1511 HANDLE_TYPE(BOOL, bool);
1512 HANDLE_TYPE(ENUM, enum);
1513 HANDLE_TYPE(STRING, string);
1514 HANDLE_TYPE(MESSAGE, message);
1515#undef HANDLE_TYPE
1516 }
1517
1518 GOOGLE_LOG(FATAL) << "Can't get here.";
1519 return 0;
1520}
1521
1522// This function deletes all allocated objects. This function should be only
1523// called if the Extension was created without an arena.
1524void ExtensionSet::Extension::Free() {
1525 if (is_repeated) {
1526 switch (cpp_type(type)) {
1527#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
1528 case WireFormatLite::CPPTYPE_##UPPERCASE: \
1529 delete repeated_##LOWERCASE##_value; \
1530 break
1531
1532 HANDLE_TYPE(INT32, int32_t);
1533 HANDLE_TYPE(INT64, int64_t);
1534 HANDLE_TYPE(UINT32, uint32_t);
1535 HANDLE_TYPE(UINT64, uint64_t);
1536 HANDLE_TYPE(FLOAT, float);
1537 HANDLE_TYPE(DOUBLE, double);
1538 HANDLE_TYPE(BOOL, bool);
1539 HANDLE_TYPE(ENUM, enum);
1540 HANDLE_TYPE(STRING, string);
1541 HANDLE_TYPE(MESSAGE, message);
1542#undef HANDLE_TYPE
1543 }
1544 } else {
1545 switch (cpp_type(type)) {
1546 case WireFormatLite::CPPTYPE_STRING:
1547 delete string_value;
1548 break;
1549 case WireFormatLite::CPPTYPE_MESSAGE:
1550 if (is_lazy) {
1551 delete lazymessage_value;
1552 } else {
1553 delete message_value;
1554 }
1555 break;
1556 default:
1557 break;
1558 }
1559 }
1560}
1561
1562// Defined in extension_set_heavy.cc.
1563// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const
1564
1565bool ExtensionSet::Extension::IsInitialized() const {
1566 if (cpp_type(type) == WireFormatLite::CPPTYPE_MESSAGE) {
1567 if (is_repeated) {
1568 for (int i = 0; i < repeated_message_value->size(); i++) {
1569 if (!repeated_message_value->Get(index: i).IsInitialized()) {
1570 return false;
1571 }
1572 }
1573 } else {
1574 if (!is_cleared) {
1575 if (is_lazy) {
1576 if (!lazymessage_value->IsInitialized()) return false;
1577 } else {
1578 if (!message_value->IsInitialized()) return false;
1579 }
1580 }
1581 }
1582 }
1583 return true;
1584}
1585
1586// Dummy key method to avoid weak vtable.
1587void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {}
1588
1589const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const {
1590 if (flat_size_ == 0) {
1591 return nullptr;
1592 } else if (PROTOBUF_PREDICT_TRUE(!is_large())) {
1593 auto it = std::lower_bound(first: flat_begin(), last: flat_end() - 1, val: key,
1594 comp: KeyValue::FirstComparator());
1595 return it->first == key ? &it->second : nullptr;
1596 } else {
1597 return FindOrNullInLargeMap(key);
1598 }
1599}
1600
1601const ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(
1602 int key) const {
1603 assert(is_large());
1604 LargeMap::const_iterator it = map_.large->find(x: key);
1605 if (it != map_.large->end()) {
1606 return &it->second;
1607 }
1608 return nullptr;
1609}
1610
1611ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) {
1612 const auto* const_this = this;
1613 return const_cast<ExtensionSet::Extension*>(const_this->FindOrNull(key));
1614}
1615
1616ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) {
1617 const auto* const_this = this;
1618 return const_cast<ExtensionSet::Extension*>(
1619 const_this->FindOrNullInLargeMap(key));
1620}
1621
1622std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) {
1623 if (PROTOBUF_PREDICT_FALSE(is_large())) {
1624 auto maybe = map_.large->insert(x: {key, Extension()});
1625 return {&maybe.first->second, maybe.second};
1626 }
1627 KeyValue* end = flat_end();
1628 KeyValue* it =
1629 std::lower_bound(first: flat_begin(), last: end, val: key, comp: KeyValue::FirstComparator());
1630 if (it != end && it->first == key) {
1631 return {&it->second, false};
1632 }
1633 if (flat_size_ < flat_capacity_) {
1634 std::copy_backward(it, end, end + 1);
1635 ++flat_size_;
1636 it->first = key;
1637 it->second = Extension();
1638 return {&it->second, true};
1639 }
1640 GrowCapacity(minimum_new_capacity: flat_size_ + 1);
1641 return Insert(key);
1642}
1643
1644void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
1645 if (PROTOBUF_PREDICT_FALSE(is_large())) {
1646 return; // LargeMap does not have a "reserve" method.
1647 }
1648 if (flat_capacity_ >= minimum_new_capacity) {
1649 return;
1650 }
1651
1652 auto new_flat_capacity = flat_capacity_;
1653 do {
1654 new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4;
1655 } while (new_flat_capacity < minimum_new_capacity);
1656
1657 const KeyValue* begin = flat_begin();
1658 const KeyValue* end = flat_end();
1659 AllocatedData new_map;
1660 if (new_flat_capacity > kMaximumFlatCapacity) {
1661 new_map.large = Arena::Create<LargeMap>(arena: arena_);
1662 LargeMap::iterator hint = new_map.large->begin();
1663 for (const KeyValue* it = begin; it != end; ++it) {
1664 hint = new_map.large->insert(position: hint, x: {it->first, it->second});
1665 }
1666 flat_size_ = static_cast<uint16_t>(-1);
1667 GOOGLE_DCHECK(is_large());
1668 } else {
1669 new_map.flat = Arena::CreateArray<KeyValue>(arena: arena_, num_elements: new_flat_capacity);
1670 std::copy(begin, end, new_map.flat);
1671 }
1672
1673 if (arena_ == nullptr) {
1674 DeleteFlatMap(flat: begin, flat_capacity: flat_capacity_);
1675 }
1676 flat_capacity_ = new_flat_capacity;
1677 map_ = new_map;
1678}
1679
1680#if (__cplusplus < 201703) && \
1681 (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
1682// static
1683constexpr uint16_t ExtensionSet::kMaximumFlatCapacity;
1684#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900
1685 // && _MSC_VER < 1912))
1686
1687void ExtensionSet::Erase(int key) {
1688 if (PROTOBUF_PREDICT_FALSE(is_large())) {
1689 map_.large->erase(x: key);
1690 return;
1691 }
1692 KeyValue* end = flat_end();
1693 KeyValue* it =
1694 std::lower_bound(first: flat_begin(), last: end, val: key, comp: KeyValue::FirstComparator());
1695 if (it != end && it->first == key) {
1696 std::copy(it + 1, end, it);
1697 --flat_size_;
1698 }
1699}
1700
1701// ==================================================================
1702// Default repeated field instances for iterator-compatible accessors
1703
1704const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() {
1705 static auto instance = OnShutdownDelete(p: new RepeatedPrimitiveDefaults);
1706 return instance;
1707}
1708
1709const RepeatedStringTypeTraits::RepeatedFieldType*
1710RepeatedStringTypeTraits::GetDefaultRepeatedField() {
1711 static auto instance = OnShutdownDelete(p: new RepeatedFieldType);
1712 return instance;
1713}
1714
1715uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
1716 const MessageLite* extendee, const ExtensionSet* extension_set, int number,
1717 uint8_t* target, io::EpsCopyOutputStream* stream) const {
1718 if (is_repeated) {
1719 if (is_packed) {
1720 if (cached_size == 0) return target;
1721
1722 target = stream->EnsureSpace(ptr: target);
1723 target = WireFormatLite::WriteTagToArray(
1724 field_number: number, type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
1725 target = WireFormatLite::WriteInt32NoTagToArray(value: cached_size, target);
1726
1727 switch (real_type(type)) {
1728#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1729 case WireFormatLite::TYPE_##UPPERCASE: \
1730 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
1731 target = stream->EnsureSpace(target); \
1732 target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
1733 repeated_##LOWERCASE##_value->Get(i), target); \
1734 } \
1735 break
1736
1737 HANDLE_TYPE(INT32, Int32, int32_t);
1738 HANDLE_TYPE(INT64, Int64, int64_t);
1739 HANDLE_TYPE(UINT32, UInt32, uint32_t);
1740 HANDLE_TYPE(UINT64, UInt64, uint64_t);
1741 HANDLE_TYPE(SINT32, SInt32, int32_t);
1742 HANDLE_TYPE(SINT64, SInt64, int64_t);
1743 HANDLE_TYPE(FIXED32, Fixed32, uint32_t);
1744 HANDLE_TYPE(FIXED64, Fixed64, uint64_t);
1745 HANDLE_TYPE(SFIXED32, SFixed32, int32_t);
1746 HANDLE_TYPE(SFIXED64, SFixed64, int64_t);
1747 HANDLE_TYPE(FLOAT, Float, float);
1748 HANDLE_TYPE(DOUBLE, Double, double);
1749 HANDLE_TYPE(BOOL, Bool, bool);
1750 HANDLE_TYPE(ENUM, Enum, enum);
1751#undef HANDLE_TYPE
1752
1753 case WireFormatLite::TYPE_STRING:
1754 case WireFormatLite::TYPE_BYTES:
1755 case WireFormatLite::TYPE_GROUP:
1756 case WireFormatLite::TYPE_MESSAGE:
1757 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
1758 break;
1759 }
1760 } else {
1761 switch (real_type(type)) {
1762#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1763 case WireFormatLite::TYPE_##UPPERCASE: \
1764 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
1765 target = stream->EnsureSpace(target); \
1766 target = WireFormatLite::Write##CAMELCASE##ToArray( \
1767 number, repeated_##LOWERCASE##_value->Get(i), target); \
1768 } \
1769 break
1770
1771 HANDLE_TYPE(INT32, Int32, int32_t);
1772 HANDLE_TYPE(INT64, Int64, int64_t);
1773 HANDLE_TYPE(UINT32, UInt32, uint32_t);
1774 HANDLE_TYPE(UINT64, UInt64, uint64_t);
1775 HANDLE_TYPE(SINT32, SInt32, int32_t);
1776 HANDLE_TYPE(SINT64, SInt64, int64_t);
1777 HANDLE_TYPE(FIXED32, Fixed32, uint32_t);
1778 HANDLE_TYPE(FIXED64, Fixed64, uint64_t);
1779 HANDLE_TYPE(SFIXED32, SFixed32, int32_t);
1780 HANDLE_TYPE(SFIXED64, SFixed64, int64_t);
1781 HANDLE_TYPE(FLOAT, Float, float);
1782 HANDLE_TYPE(DOUBLE, Double, double);
1783 HANDLE_TYPE(BOOL, Bool, bool);
1784 HANDLE_TYPE(ENUM, Enum, enum);
1785#undef HANDLE_TYPE
1786#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
1787 case WireFormatLite::TYPE_##UPPERCASE: \
1788 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
1789 target = stream->EnsureSpace(target); \
1790 target = stream->WriteString( \
1791 number, repeated_##LOWERCASE##_value->Get(i), target); \
1792 } \
1793 break
1794 HANDLE_TYPE(STRING, String, string);
1795 HANDLE_TYPE(BYTES, Bytes, string);
1796#undef HANDLE_TYPE
1797 case WireFormatLite::TYPE_GROUP:
1798 for (int i = 0; i < repeated_message_value->size(); i++) {
1799 target = stream->EnsureSpace(ptr: target);
1800 target = WireFormatLite::InternalWriteGroup(
1801 field_number: number, value: repeated_message_value->Get(index: i), target, stream);
1802 }
1803 break;
1804 case WireFormatLite::TYPE_MESSAGE:
1805 for (int i = 0; i < repeated_message_value->size(); i++) {
1806 auto& msg = repeated_message_value->Get(index: i);
1807 target = WireFormatLite::InternalWriteMessage(
1808 field_number: number, value: msg, cached_size: msg.GetCachedSize(), target, stream);
1809 }
1810 break;
1811 }
1812 }
1813 } else if (!is_cleared) {
1814 switch (real_type(type)) {
1815#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
1816 case WireFormatLite::TYPE_##UPPERCASE: \
1817 target = stream->EnsureSpace(target); \
1818 target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \
1819 break
1820
1821 HANDLE_TYPE(INT32, Int32, int32_t_value);
1822 HANDLE_TYPE(INT64, Int64, int64_t_value);
1823 HANDLE_TYPE(UINT32, UInt32, uint32_t_value);
1824 HANDLE_TYPE(UINT64, UInt64, uint64_t_value);
1825 HANDLE_TYPE(SINT32, SInt32, int32_t_value);
1826 HANDLE_TYPE(SINT64, SInt64, int64_t_value);
1827 HANDLE_TYPE(FIXED32, Fixed32, uint32_t_value);
1828 HANDLE_TYPE(FIXED64, Fixed64, uint64_t_value);
1829 HANDLE_TYPE(SFIXED32, SFixed32, int32_t_value);
1830 HANDLE_TYPE(SFIXED64, SFixed64, int64_t_value);
1831 HANDLE_TYPE(FLOAT, Float, float_value);
1832 HANDLE_TYPE(DOUBLE, Double, double_value);
1833 HANDLE_TYPE(BOOL, Bool, bool_value);
1834 HANDLE_TYPE(ENUM, Enum, enum_value);
1835#undef HANDLE_TYPE
1836#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
1837 case WireFormatLite::TYPE_##UPPERCASE: \
1838 target = stream->EnsureSpace(target); \
1839 target = stream->WriteString(number, VALUE, target); \
1840 break
1841 HANDLE_TYPE(STRING, String, *string_value);
1842 HANDLE_TYPE(BYTES, Bytes, *string_value);
1843#undef HANDLE_TYPE
1844 case WireFormatLite::TYPE_GROUP:
1845 target = stream->EnsureSpace(ptr: target);
1846 target = WireFormatLite::InternalWriteGroup(field_number: number, value: *message_value,
1847 target, stream);
1848 break;
1849 case WireFormatLite::TYPE_MESSAGE:
1850 if (is_lazy) {
1851 const auto* prototype =
1852 extension_set->GetPrototypeForLazyMessage(extendee, number);
1853 target = lazymessage_value->WriteMessageToArray(prototype, number,
1854 target, stream);
1855 } else {
1856 target = WireFormatLite::InternalWriteMessage(
1857 field_number: number, value: *message_value, cached_size: message_value->GetCachedSize(), target,
1858 stream);
1859 }
1860 break;
1861 }
1862 }
1863 return target;
1864}
1865
1866const MessageLite* ExtensionSet::GetPrototypeForLazyMessage(
1867 const MessageLite* extendee, int number) const {
1868 GeneratedExtensionFinder finder(extendee);
1869 bool was_packed_on_wire = false;
1870 ExtensionInfo extension_info;
1871 if (!FindExtensionInfoFromFieldNumber(
1872 wire_type: WireFormatLite::WireType::WIRETYPE_LENGTH_DELIMITED, field_number: number, extension_finder: &finder,
1873 extension: &extension_info, was_packed_on_wire: &was_packed_on_wire)) {
1874 return nullptr;
1875 }
1876 return extension_info.message_info.prototype;
1877}
1878
1879uint8_t*
1880ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
1881 const MessageLite* extendee, const ExtensionSet* extension_set, int number,
1882 uint8_t* target, io::EpsCopyOutputStream* stream) const {
1883 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
1884 // Not a valid MessageSet extension, but serialize it the normal way.
1885 GOOGLE_LOG(WARNING) << "Invalid message set extension.";
1886 return InternalSerializeFieldWithCachedSizesToArray(extendee, extension_set,
1887 number, target, stream);
1888 }
1889
1890 if (is_cleared) return target;
1891
1892 target = stream->EnsureSpace(ptr: target);
1893 // Start group.
1894 target = io::CodedOutputStream::WriteTagToArray(
1895 value: WireFormatLite::kMessageSetItemStartTag, target);
1896 // Write type ID.
1897 target = WireFormatLite::WriteUInt32ToArray(
1898 field_number: WireFormatLite::kMessageSetTypeIdNumber, value: number, target);
1899 // Write message.
1900 if (is_lazy) {
1901 const auto* prototype =
1902 extension_set->GetPrototypeForLazyMessage(extendee, number);
1903 target = lazymessage_value->WriteMessageToArray(
1904 prototype, number: WireFormatLite::kMessageSetMessageNumber, target, stream);
1905 } else {
1906 target = WireFormatLite::InternalWriteMessage(
1907 field_number: WireFormatLite::kMessageSetMessageNumber, value: *message_value,
1908 cached_size: message_value->GetCachedSize(), target, stream);
1909 }
1910 // End group.
1911 target = stream->EnsureSpace(ptr: target);
1912 target = io::CodedOutputStream::WriteTagToArray(
1913 value: WireFormatLite::kMessageSetItemEndTag, target);
1914 return target;
1915}
1916
1917size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
1918 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
1919 // Not a valid MessageSet extension, but compute the byte size for it the
1920 // normal way.
1921 return ByteSize(number);
1922 }
1923
1924 if (is_cleared) return 0;
1925
1926 size_t our_size = WireFormatLite::kMessageSetItemTagsSize;
1927
1928 // type_id
1929 our_size += io::CodedOutputStream::VarintSize32(value: number);
1930
1931 // message
1932 size_t message_size = 0;
1933 if (is_lazy) {
1934 message_size = lazymessage_value->ByteSizeLong();
1935 } else {
1936 message_size = message_value->ByteSizeLong();
1937 }
1938
1939 our_size += io::CodedOutputStream::VarintSize32(value: message_size);
1940 our_size += message_size;
1941
1942 return our_size;
1943}
1944
1945size_t ExtensionSet::MessageSetByteSize() const {
1946 size_t total_size = 0;
1947 ForEach(func: [&total_size](int number, const Extension& ext) {
1948 total_size += ext.MessageSetItemByteSize(number);
1949 });
1950 return total_size;
1951}
1952
1953LazyEagerVerifyFnType FindExtensionLazyEagerVerifyFn(
1954 const MessageLite* extendee, int number) {
1955 const ExtensionInfo* registered = FindRegisteredExtension(extendee, number);
1956 if (registered != nullptr) {
1957 return registered->lazy_eager_verify_func;
1958 }
1959 return nullptr;
1960}
1961
1962
1963} // namespace internal
1964} // namespace protobuf
1965} // namespace google
1966
1967#include <google/protobuf/port_undef.inc>
1968