xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/extension_set.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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: [email protected] (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
57 namespace google {
58 namespace protobuf {
59 namespace internal {
60 
61 namespace {
62 
real_type(FieldType type)63 inline 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 
cpp_type(FieldType type)68 inline WireFormatLite::CppType cpp_type(FieldType type) {
69   return WireFormatLite::FieldTypeToCppType(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.
76 struct ExtensionEq {
operator ()google::protobuf::internal::__anonf4acc5f90111::ExtensionEq77   bool operator()(const ExtensionInfo& lhs, const ExtensionInfo& rhs) const {
78     return lhs.message == rhs.message && lhs.number == rhs.number;
79   }
80 };
81 
82 struct ExtensionHasher {
operator ()google::protobuf::internal::__anonf4acc5f90111::ExtensionHasher83   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 
89 using ExtensionRegistry =
90     std::unordered_set<ExtensionInfo, ExtensionHasher, ExtensionEq>;
91 
92 static const ExtensionRegistry* global_registry = nullptr;
93 
94 // This function is only called at startup, so there is no need for thread-
95 // safety.
Register(const ExtensionInfo & info)96 void Register(const ExtensionInfo& info) {
97   static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry);
98   global_registry = local_static_registry;
99   if (!InsertIfNotPresent(local_static_registry, info)) {
100     GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
101                << info.message->GetTypeName() << "\", field number "
102                << info.number << ".";
103   }
104 }
105 
FindRegisteredExtension(const MessageLite * extendee,int number)106 const 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(info);
115   if (it == global_registry->end()) {
116     return nullptr;
117   } else {
118     return &*it;
119   }
120 }
121 
122 }  // namespace
123 
Find(int number,ExtensionInfo * output)124 bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) {
125   const ExtensionInfo* extension = FindRegisteredExtension(extendee_, number);
126   if (extension == nullptr) {
127     return false;
128   } else {
129     *output = *extension;
130     return true;
131   }
132 }
133 
RegisterExtension(const MessageLite * extendee,int number,FieldType type,bool is_repeated,bool is_packed,LazyEagerVerifyFnType verify_func)134 void 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 
CallNoArgValidityFunc(const void * arg,int number)146 static 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 
RegisterEnumExtension(const MessageLite * extendee,int number,FieldType type,bool is_repeated,bool is_packed,EnumValidityFunc * is_valid)159 void 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 
RegisterMessageExtension(const MessageLite * extendee,int number,FieldType type,bool is_repeated,bool is_packed,const MessageLite * prototype,LazyEagerVerifyFnType verify_func)171 void 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};
181   Register(info);
182 }
183 
184 // ===================================================================
185 // Constructors and basic methods.
186 
ExtensionSet(Arena * arena)187 ExtensionSet::ExtensionSet(Arena* arena)
188     : arena_(arena),
189       flat_capacity_(0),
190       flat_size_(0),
191       map_{flat_capacity_ == 0
192                ? nullptr
193                : Arena::CreateArray<KeyValue>(arena_, flat_capacity_)} {}
194 
~ExtensionSet()195 ExtensionSet::~ExtensionSet() {
196   // Deletes all allocated extensions.
197   if (arena_ == nullptr) {
198     ForEach([](int /* number */, Extension& ext) { ext.Free(); });
199     if (PROTOBUF_PREDICT_FALSE(is_large())) {
200       delete map_.large;
201     } else {
202       DeleteFlatMap(map_.flat, flat_capacity_);
203     }
204   }
205 }
206 
DeleteFlatMap(const ExtensionSet::KeyValue * flat,uint16_t flat_capacity)207 void 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(const_cast<KeyValue*>(flat),
216                              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 
Has(int number) const224 bool ExtensionSet::Has(int number) const {
225   const Extension* ext = FindOrNull(number);
226   if (ext == nullptr) return false;
227   GOOGLE_DCHECK(!ext->is_repeated);
228   return !ext->is_cleared;
229 }
230 
HasLazy(int number) const231 bool ExtensionSet::HasLazy(int number) const {
232   return Has(number) && FindOrNull(number)->is_lazy;
233 }
234 
NumExtensions() const235 int ExtensionSet::NumExtensions() const {
236   int result = 0;
237   ForEach([&result](int /* number */, const Extension& ext) {
238     if (!ext.is_cleared) {
239       ++result;
240     }
241   });
242   return result;
243 }
244 
ExtensionSize(int number) const245 int ExtensionSet::ExtensionSize(int number) const {
246   const Extension* ext = FindOrNull(number);
247   return ext == nullptr ? 0 : ext->GetSize();
248 }
249 
ExtensionType(int number) const250 FieldType ExtensionSet::ExtensionType(int number) const {
251   const Extension* ext = FindOrNull(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 
ClearExtension(int number)262 void ExtensionSet::ClearExtension(int number) {
263   Extension* ext = FindOrNull(number);
264   if (ext == nullptr) return;
265   ext->Clear();
266 }
267 
268 // ===================================================================
269 // Field accessors
270 
271 namespace {
272 
273 enum { 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 
PRIMITIVE_ACCESSORS(INT32,int32_t,Int32)367 PRIMITIVE_ACCESSORS(INT32, int32_t, Int32)
368 PRIMITIVE_ACCESSORS(INT64, int64_t, Int64)
369 PRIMITIVE_ACCESSORS(UINT32, uint32_t, UInt32)
370 PRIMITIVE_ACCESSORS(UINT64, uint64_t, UInt64)
371 PRIMITIVE_ACCESSORS(FLOAT, float, Float)
372 PRIMITIVE_ACCESSORS(DOUBLE, double, Double)
373 PRIMITIVE_ACCESSORS(BOOL, bool, Bool)
374 
375 #undef PRIMITIVE_ACCESSORS
376 
377 const void* ExtensionSet::GetRawRepeatedField(int number,
378                                               const void* default_value) const {
379   const Extension* extension = FindOrNull(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 
MutableRawRepeatedField(int number,FieldType field_type,bool packed,const FieldDescriptor * desc)388 void* 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, desc, &extension)) {
396     extension->is_repeated = true;
397     extension->type = field_type;
398     extension->is_packed = packed;
399 
400     switch (WireFormatLite::FieldTypeToCppType(
401         static_cast<WireFormatLite::FieldType>(field_type))) {
402       case WireFormatLite::CPPTYPE_INT32:
403         extension->repeated_int32_t_value =
404             Arena::CreateMessage<RepeatedField<int32_t>>(arena_);
405         break;
406       case WireFormatLite::CPPTYPE_INT64:
407         extension->repeated_int64_t_value =
408             Arena::CreateMessage<RepeatedField<int64_t>>(arena_);
409         break;
410       case WireFormatLite::CPPTYPE_UINT32:
411         extension->repeated_uint32_t_value =
412             Arena::CreateMessage<RepeatedField<uint32_t>>(arena_);
413         break;
414       case WireFormatLite::CPPTYPE_UINT64:
415         extension->repeated_uint64_t_value =
416             Arena::CreateMessage<RepeatedField<uint64_t>>(arena_);
417         break;
418       case WireFormatLite::CPPTYPE_DOUBLE:
419         extension->repeated_double_value =
420             Arena::CreateMessage<RepeatedField<double>>(arena_);
421         break;
422       case WireFormatLite::CPPTYPE_FLOAT:
423         extension->repeated_float_value =
424             Arena::CreateMessage<RepeatedField<float>>(arena_);
425         break;
426       case WireFormatLite::CPPTYPE_BOOL:
427         extension->repeated_bool_value =
428             Arena::CreateMessage<RepeatedField<bool>>(arena_);
429         break;
430       case WireFormatLite::CPPTYPE_ENUM:
431         extension->repeated_enum_value =
432             Arena::CreateMessage<RepeatedField<int>>(arena_);
433         break;
434       case WireFormatLite::CPPTYPE_STRING:
435         extension->repeated_string_value =
436             Arena::CreateMessage<RepeatedPtrField<std::string>>(arena_);
437         break;
438       case WireFormatLite::CPPTYPE_MESSAGE:
439         extension->repeated_message_value =
440             Arena::CreateMessage<RepeatedPtrField<MessageLite>>(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.
MutableRawRepeatedField(int number)452 void* ExtensionSet::MutableRawRepeatedField(int number) {
453   Extension* extension = FindOrNull(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 
GetEnum(int number,int default_value) const463 int ExtensionSet::GetEnum(int number, int default_value) const {
464   const Extension* extension = FindOrNull(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 
GetRefEnum(int number,const int & default_value) const474 const int& ExtensionSet::GetRefEnum(int number,
475                                     const int& default_value) const {
476   const Extension* extension = FindOrNull(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 
SetEnum(int number,FieldType type,int value,const FieldDescriptor * descriptor)486 void ExtensionSet::SetEnum(int number, FieldType type, int value,
487                            const FieldDescriptor* descriptor) {
488   Extension* extension;
489   if (MaybeNewExtension(number, descriptor, &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 
GetRepeatedEnum(int number,int index) const500 int ExtensionSet::GetRepeatedEnum(int number, int index) const {
501   const Extension* extension = FindOrNull(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 
GetRefRepeatedEnum(int number,int index) const507 const int& ExtensionSet::GetRefRepeatedEnum(int number, int index) const {
508   const Extension* extension = FindOrNull(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 
SetRepeatedEnum(int number,int index,int value)514 void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
515   Extension* extension = FindOrNull(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 
AddEnum(int number,FieldType type,bool packed,int value,const FieldDescriptor * descriptor)521 void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value,
522                            const FieldDescriptor* descriptor) {
523   Extension* extension;
524   if (MaybeNewExtension(number, descriptor, &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_);
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 
GetString(int number,const std::string & default_value) const541 const std::string& ExtensionSet::GetString(
542     int number, const std::string& default_value) const {
543   const Extension* extension = FindOrNull(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 
MutableString(int number,FieldType type,const FieldDescriptor * descriptor)553 std::string* ExtensionSet::MutableString(int number, FieldType type,
554                                          const FieldDescriptor* descriptor) {
555   Extension* extension;
556   if (MaybeNewExtension(number, descriptor, &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_);
561   } else {
562     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING);
563   }
564   extension->is_cleared = false;
565   return extension->string_value;
566 }
567 
GetRepeatedString(int number,int index) const568 const std::string& ExtensionSet::GetRepeatedString(int number,
569                                                    int index) const {
570   const Extension* extension = FindOrNull(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 
MutableRepeatedString(int number,int index)576 std::string* ExtensionSet::MutableRepeatedString(int number, int index) {
577   Extension* extension = FindOrNull(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 
AddString(int number,FieldType type,const FieldDescriptor * descriptor)583 std::string* ExtensionSet::AddString(int number, FieldType type,
584                                      const FieldDescriptor* descriptor) {
585   Extension* extension;
586   if (MaybeNewExtension(number, descriptor, &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_);
593   } else {
594     GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING);
595   }
596   return extension->repeated_string_value->Add();
597 }
598 
599 // -------------------------------------------------------------------
600 // Messages
601 
GetMessage(int number,const MessageLite & default_value) const602 const MessageLite& ExtensionSet::GetMessage(
603     int number, const MessageLite& default_value) const {
604   const Extension* extension = FindOrNull(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(default_value, 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 
MutableMessage(int number,FieldType type,const MessageLite & prototype,const FieldDescriptor * descriptor)623 MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
624                                           const MessageLite& prototype,
625                                           const FieldDescriptor* descriptor) {
626   Extension* extension;
627   if (MaybeNewExtension(number, descriptor, &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_);
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_);
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 
SetAllocatedMessage(int number,FieldType type,const FieldDescriptor * descriptor,MessageLite * message)651 void 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, &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(message);  // not nullptr because not equal to message_arena
672     } else {
673       extension->message_value = message->New(arena_);
674       extension->message_value->CheckTypeAndMergeFrom(*message);
675     }
676   } else {
677     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
678     if (extension->is_lazy) {
679       extension->lazymessage_value->SetAllocatedMessage(message, 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(message);  // not nullptr because not equal to message_arena
689       } else {
690         extension->message_value = message->New(arena_);
691         extension->message_value->CheckTypeAndMergeFrom(*message);
692       }
693     }
694   }
695   extension->is_cleared = false;
696 }
697 
UnsafeArenaSetAllocatedMessage(int number,FieldType type,const FieldDescriptor * descriptor,MessageLite * message)698 void 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, &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_);
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 
ReleaseMessage(int number,const MessageLite & prototype)727 MessageLite* ExtensionSet::ReleaseMessage(int number,
728                                           const MessageLite& prototype) {
729   Extension* extension = FindOrNull(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_);
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(*extension->message_value);
749       }
750     }
751     Erase(number);
752     return ret;
753   }
754 }
755 
UnsafeArenaReleaseMessage(int number,const MessageLite & prototype)756 MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
757     int number, const MessageLite& prototype) {
758   Extension* extension = FindOrNull(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_);
768       if (arena_ == nullptr) {
769         delete extension->lazymessage_value;
770       }
771     } else {
772       ret = extension->message_value;
773     }
774     Erase(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 
GetRepeatedMessage(int number,int index) const783 const MessageLite& ExtensionSet::GetRepeatedMessage(int number,
784                                                     int index) const {
785   const Extension* extension = FindOrNull(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 
MutableRepeatedMessage(int number,int index)791 MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
792   Extension* extension = FindOrNull(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 
AddMessage(int number,FieldType type,const MessageLite & prototype,const FieldDescriptor * descriptor)798 MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
799                                       const MessageLite& prototype,
800                                       const FieldDescriptor* descriptor) {
801   Extension* extension;
802   if (MaybeNewExtension(number, descriptor, &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_);
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_);
819     extension->repeated_message_value->AddAllocated(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 
RemoveLast(int number)831 void ExtensionSet::RemoveLast(int number) {
832   Extension* extension = FindOrNull(number);
833   GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
834   GOOGLE_DCHECK(extension->is_repeated);
835 
836   switch (cpp_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 
ReleaseLast(int number)870 MessageLite* ExtensionSet::ReleaseLast(int number) {
871   Extension* extension = FindOrNull(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 
UnsafeArenaReleaseLast(int number)878 MessageLite* ExtensionSet::UnsafeArenaReleaseLast(int number) {
879   Extension* extension = FindOrNull(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 
SwapElements(int number,int index1,int index2)886 void ExtensionSet::SwapElements(int number, int index1, int index2) {
887   Extension* extension = FindOrNull(number);
888   GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty).";
889   GOOGLE_DCHECK(extension->is_repeated);
890 
891   switch (cpp_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 
Clear()927 void ExtensionSet::Clear() {
928   ForEach([](int /* number */, Extension& ext) { ext.Clear(); });
929 }
930 
931 namespace {
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.
937 template <typename ItX, typename ItY>
SizeOfUnion(ItX it_dest,ItX end_dest,ItY it_source,ItY end_source)938 size_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 
MergeFrom(const MessageLite * extendee,const ExtensionSet & other)965 void 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(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(),
970                                other.flat_end()));
971     } else {
972       GrowCapacity(SizeOfUnion(flat_begin(), flat_end(),
973                                other.map_.large->begin(),
974                                other.map_.large->end()));
975     }
976   }
977   other.ForEach([extendee, this, &other](int number, const Extension& ext) {
978     this->InternalExtensionMergeFrom(extendee, number, ext, other.arena_);
979   });
980 }
981 
InternalExtensionMergeFrom(const MessageLite * extendee,int number,const Extension & other_extension,Arena * other_arena)982 void 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, other_extension.descriptor, &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(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_);
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(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_);
1040             extension->repeated_message_value->AddAllocated(target);
1041           }
1042           target->CheckTypeAndMergeFrom(other_message);
1043         }
1044         break;
1045     }
1046   } else {
1047     if (!other_extension.is_cleared) {
1048       switch (cpp_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, other_extension.type, *other_extension.string_value,
1067                     other_extension.descriptor);
1068           break;
1069         case WireFormatLite::CPPTYPE_MESSAGE: {
1070           Extension* extension;
1071           bool is_new =
1072               MaybeNewExtension(number, other_extension.descriptor, &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_);
1081               extension->lazymessage_value->MergeFrom(
1082                   GetPrototypeForLazyMessage(extendee, number),
1083                   *other_extension.lazymessage_value, arena_);
1084             } else {
1085               extension->is_lazy = false;
1086               extension->message_value =
1087                   other_extension.message_value->New(arena_);
1088               extension->message_value->CheckTypeAndMergeFrom(
1089                   *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                     GetPrototypeForLazyMessage(extendee, number),
1099                     *other_extension.lazymessage_value, arena_);
1100               } else {
1101                 extension->message_value->CheckTypeAndMergeFrom(
1102                     other_extension.lazymessage_value->GetMessage(
1103                         *extension->message_value, other_arena));
1104               }
1105             } else {
1106               if (extension->is_lazy) {
1107                 extension->lazymessage_value
1108                     ->MutableMessage(*other_extension.message_value, arena_)
1109                     ->CheckTypeAndMergeFrom(*other_extension.message_value);
1110               } else {
1111                 extension->message_value->CheckTypeAndMergeFrom(
1112                     *other_extension.message_value);
1113               }
1114             }
1115           }
1116           extension->is_cleared = false;
1117           break;
1118         }
1119       }
1120     }
1121   }
1122 }
1123 
Swap(const MessageLite * extendee,ExtensionSet * other)1124 void 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);
1137     other->Clear();
1138     other->MergeFrom(extendee, *this);
1139     Clear();
1140     MergeFrom(extendee, extension_set);
1141   }
1142 }
1143 
1144 void ExtensionSet::InternalSwap(ExtensionSet* other) {
1145   using std::swap;
1146   swap(arena_, other->arena_);
1147   swap(flat_capacity_, other->flat_capacity_);
1148   swap(flat_size_, other->flat_size_);
1149   swap(map_, other->map_);
1150 }
1151 
1152 void 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(number);
1162   Extension* other_ext = other->FindOrNull(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_ext,
1174                                     other->GetArena());
1175     Extension* temp_ext = temp.FindOrNull(number);
1176 
1177     other_ext->Clear();
1178     other->InternalExtensionMergeFrom(extendee, number, *this_ext,
1179                                       this->GetArena());
1180     this_ext->Clear();
1181     InternalExtensionMergeFrom(extendee, number, *temp_ext, temp.GetArena());
1182   } else if (this_ext == nullptr) {
1183     InternalExtensionMergeFrom(extendee, number, *other_ext, other->GetArena());
1184     if (other->GetArena() == nullptr) other_ext->Free();
1185     other->Erase(number);
1186   } else {
1187     other->InternalExtensionMergeFrom(extendee, number, *this_ext,
1188                                       this->GetArena());
1189     if (GetArena() == nullptr) this_ext->Free();
1190     Erase(number);
1191   }
1192 }
1193 
1194 void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) {
1195   if (this == other) return;
1196 
1197   Extension* this_ext = FindOrNull(number);
1198   Extension* other_ext = other->FindOrNull(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(*this_ext, *other_ext);
1206   } else if (this_ext == nullptr) {
1207     *Insert(number).first = *other_ext;
1208     other->Erase(number);
1209   } else {
1210     *other->Insert(number).first = *this_ext;
1211     Erase(number);
1212   }
1213 }
1214 
1215 bool 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 
1230 const 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(tag & 7, number, &finder, &extension,
1239                                         &was_packed_on_wire)) {
1240     return UnknownFieldParse(
1241         tag, 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 
1247 const 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 
1254 uint8_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(start_field_number);
1260          it != end && it->first < end_field_number; ++it) {
1261       target = it->second.InternalSerializeFieldWithCachedSizesToArray(
1262           extendee, this, it->first, target, stream);
1263     }
1264     return target;
1265   }
1266   const KeyValue* end = flat_end();
1267   for (const KeyValue* it = std::lower_bound(
1268            flat_begin(), end, start_field_number, KeyValue::FirstComparator());
1269        it != end && it->first < end_field_number; ++it) {
1270     target = it->second.InternalSerializeFieldWithCachedSizesToArray(
1271         extendee, this, it->first, target, stream);
1272   }
1273   return target;
1274 }
1275 
1276 uint8_t* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
1277     const MessageLite* extendee, uint8_t* target,
1278     io::EpsCopyOutputStream* stream) const {
1279   const ExtensionSet* extension_set = this;
1280   ForEach([&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 
1288 size_t ExtensionSet::ByteSize() const {
1289   size_t total_size = 0;
1290   ForEach([&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 
1299 bool ExtensionSet::MaybeNewExtension(int number,
1300                                      const FieldDescriptor* descriptor,
1301                                      Extension** result) {
1302   bool extension_is_new = false;
1303   std::tie(*result, extension_is_new) = Insert(number);
1304   (*result)->descriptor = descriptor;
1305   return extension_is_new;
1306 }
1307 
1308 // ===================================================================
1309 // Methods of ExtensionSet::Extension
1310 
1311 void 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 
1356 size_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(result);
1403       if (result > 0) {
1404         result += io::CodedOutputStream::VarintSize32(result);
1405         result += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag(
1406             number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
1407       }
1408     } else {
1409       size_t tag_size = WireFormatLite::TagSize(number, 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(number, 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(size) + size;
1473         } else {
1474           result += WireFormatLite::MessageSize(*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 
1498 int 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.
1524 void 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 
1565 bool 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(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.
1587 void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {}
1588 
1589 const 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(flat_begin(), flat_end() - 1, key,
1594                                KeyValue::FirstComparator());
1595     return it->first == key ? &it->second : nullptr;
1596   } else {
1597     return FindOrNullInLargeMap(key);
1598   }
1599 }
1600 
1601 const ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(
1602     int key) const {
1603   assert(is_large());
1604   LargeMap::const_iterator it = map_.large->find(key);
1605   if (it != map_.large->end()) {
1606     return &it->second;
1607   }
1608   return nullptr;
1609 }
1610 
1611 ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) {
1612   const auto* const_this = this;
1613   return const_cast<ExtensionSet::Extension*>(const_this->FindOrNull(key));
1614 }
1615 
1616 ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) {
1617   const auto* const_this = this;
1618   return const_cast<ExtensionSet::Extension*>(
1619       const_this->FindOrNullInLargeMap(key));
1620 }
1621 
1622 std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) {
1623   if (PROTOBUF_PREDICT_FALSE(is_large())) {
1624     auto maybe = map_.large->insert({key, Extension()});
1625     return {&maybe.first->second, maybe.second};
1626   }
1627   KeyValue* end = flat_end();
1628   KeyValue* it =
1629       std::lower_bound(flat_begin(), end, key, 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(flat_size_ + 1);
1641   return Insert(key);
1642 }
1643 
1644 void 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_);
1662     LargeMap::iterator hint = new_map.large->begin();
1663     for (const KeyValue* it = begin; it != end; ++it) {
1664       hint = new_map.large->insert(hint, {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_, new_flat_capacity);
1670     std::copy(begin, end, new_map.flat);
1671   }
1672 
1673   if (arena_ == nullptr) {
1674     DeleteFlatMap(begin, 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
1683 constexpr uint16_t ExtensionSet::kMaximumFlatCapacity;
1684 #endif  //  (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900
1685         //  && _MSC_VER < 1912))
1686 
1687 void ExtensionSet::Erase(int key) {
1688   if (PROTOBUF_PREDICT_FALSE(is_large())) {
1689     map_.large->erase(key);
1690     return;
1691   }
1692   KeyValue* end = flat_end();
1693   KeyValue* it =
1694       std::lower_bound(flat_begin(), end, key, 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 
1704 const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() {
1705   static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults);
1706   return instance;
1707 }
1708 
1709 const RepeatedStringTypeTraits::RepeatedFieldType*
1710 RepeatedStringTypeTraits::GetDefaultRepeatedField() {
1711   static auto instance = OnShutdownDelete(new RepeatedFieldType);
1712   return instance;
1713 }
1714 
1715 uint8_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(target);
1723       target = WireFormatLite::WriteTagToArray(
1724           number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
1725       target = WireFormatLite::WriteInt32NoTagToArray(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(target);
1800             target = WireFormatLite::InternalWriteGroup(
1801                 number, repeated_message_value->Get(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(i);
1807             target = WireFormatLite::InternalWriteMessage(
1808                 number, msg, 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(target);
1846         target = WireFormatLite::InternalWriteGroup(number, *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               number, *message_value, message_value->GetCachedSize(), target,
1858               stream);
1859         }
1860         break;
1861     }
1862   }
1863   return target;
1864 }
1865 
1866 const 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           WireFormatLite::WireType::WIRETYPE_LENGTH_DELIMITED, number, &finder,
1873           &extension_info, &was_packed_on_wire)) {
1874     return nullptr;
1875   }
1876   return extension_info.message_info.prototype;
1877 }
1878 
1879 uint8_t*
1880 ExtensionSet::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(target);
1893   // Start group.
1894   target = io::CodedOutputStream::WriteTagToArray(
1895       WireFormatLite::kMessageSetItemStartTag, target);
1896   // Write type ID.
1897   target = WireFormatLite::WriteUInt32ToArray(
1898       WireFormatLite::kMessageSetTypeIdNumber, 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, WireFormatLite::kMessageSetMessageNumber, target, stream);
1905   } else {
1906     target = WireFormatLite::InternalWriteMessage(
1907         WireFormatLite::kMessageSetMessageNumber, *message_value,
1908         message_value->GetCachedSize(), target, stream);
1909   }
1910   // End group.
1911   target = stream->EnsureSpace(target);
1912   target = io::CodedOutputStream::WriteTagToArray(
1913       WireFormatLite::kMessageSetItemEndTag, target);
1914   return target;
1915 }
1916 
1917 size_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(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(message_size);
1940   our_size += message_size;
1941 
1942   return our_size;
1943 }
1944 
1945 size_t ExtensionSet::MessageSetByteSize() const {
1946   size_t total_size = 0;
1947   ForEach([&total_size](int number, const Extension& ext) {
1948     total_size += ext.MessageSetItemByteSize(number);
1949   });
1950   return total_size;
1951 }
1952 
1953 LazyEagerVerifyFnType 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