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