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