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