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 // Contains methods defined in extension_set.h which cannot be part of the
36 // lite library because they use descriptors or reflection.
37
38 #include <google/protobuf/extension_set.h>
39
40 #include <google/protobuf/stubs/casts.h>
41 #include <google/protobuf/descriptor.pb.h>
42 #include <google/protobuf/extension_set_inl.h>
43 #include <google/protobuf/parse_context.h>
44 #include <google/protobuf/io/coded_stream.h>
45 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
46 #include <google/protobuf/descriptor.h>
47 #include <google/protobuf/message.h>
48 #include <google/protobuf/repeated_field.h>
49 #include <google/protobuf/unknown_field_set.h>
50 #include <google/protobuf/wire_format.h>
51 #include <google/protobuf/wire_format_lite.h>
52
53
54 #include <google/protobuf/port_def.inc>
55
56 namespace google {
57 namespace protobuf {
58 namespace internal {
59
60 // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
61 class MessageSetFieldSkipper : public UnknownFieldSetFieldSkipper {
62 public:
MessageSetFieldSkipper(UnknownFieldSet * unknown_fields)63 explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
64 : UnknownFieldSetFieldSkipper(unknown_fields) {}
~MessageSetFieldSkipper()65 virtual ~MessageSetFieldSkipper() {}
66
67 virtual bool SkipMessageSetField(io::CodedInputStream* input,
68 int field_number);
69 };
SkipMessageSetField(io::CodedInputStream * input,int field_number)70 bool MessageSetFieldSkipper::SkipMessageSetField(io::CodedInputStream* input,
71 int field_number) {
72 uint32 length;
73 if (!input->ReadVarint32(&length)) return false;
74 if (unknown_fields_ == NULL) {
75 return input->Skip(length);
76 } else {
77 return input->ReadString(unknown_fields_->AddLengthDelimited(field_number),
78 length);
79 }
80 }
81
82
83 // Implementation of ExtensionFinder which finds extensions in a given
84 // DescriptorPool, using the given MessageFactory to construct sub-objects.
85 // This class is implemented in extension_set_heavy.cc.
86 class DescriptorPoolExtensionFinder : public ExtensionFinder {
87 public:
DescriptorPoolExtensionFinder(const DescriptorPool * pool,MessageFactory * factory,const Descriptor * containing_type)88 DescriptorPoolExtensionFinder(const DescriptorPool* pool,
89 MessageFactory* factory,
90 const Descriptor* containing_type)
91 : pool_(pool), factory_(factory), containing_type_(containing_type) {}
~DescriptorPoolExtensionFinder()92 ~DescriptorPoolExtensionFinder() override {}
93
94 bool Find(int number, ExtensionInfo* output) override;
95
96 private:
97 const DescriptorPool* pool_;
98 MessageFactory* factory_;
99 const Descriptor* containing_type_;
100 };
101
AppendToList(const Descriptor * containing_type,const DescriptorPool * pool,std::vector<const FieldDescriptor * > * output) const102 void ExtensionSet::AppendToList(
103 const Descriptor* containing_type, const DescriptorPool* pool,
104 std::vector<const FieldDescriptor*>* output) const {
105 ForEach([containing_type, pool, &output](int number, const Extension& ext) {
106 bool has = false;
107 if (ext.is_repeated) {
108 has = ext.GetSize() > 0;
109 } else {
110 has = !ext.is_cleared;
111 }
112
113 if (has) {
114 // TODO(kenton): Looking up each field by number is somewhat unfortunate.
115 // Is there a better way? The problem is that descriptors are lazily-
116 // initialized, so they might not even be constructed until
117 // AppendToList() is called.
118
119 if (ext.descriptor == NULL) {
120 output->push_back(pool->FindExtensionByNumber(containing_type, number));
121 } else {
122 output->push_back(ext.descriptor);
123 }
124 }
125 });
126 }
127
real_type(FieldType type)128 inline FieldDescriptor::Type real_type(FieldType type) {
129 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
130 return static_cast<FieldDescriptor::Type>(type);
131 }
132
cpp_type(FieldType type)133 inline FieldDescriptor::CppType cpp_type(FieldType type) {
134 return FieldDescriptor::TypeToCppType(
135 static_cast<FieldDescriptor::Type>(type));
136 }
137
field_type(FieldType type)138 inline WireFormatLite::FieldType field_type(FieldType type) {
139 GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
140 return static_cast<WireFormatLite::FieldType>(type);
141 }
142
143 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
144 GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
145 : FieldDescriptor::LABEL_OPTIONAL, \
146 FieldDescriptor::LABEL_##LABEL); \
147 GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
148
GetMessage(int number,const Descriptor * message_type,MessageFactory * factory) const149 const MessageLite& ExtensionSet::GetMessage(int number,
150 const Descriptor* message_type,
151 MessageFactory* factory) const {
152 const Extension* extension = FindOrNull(number);
153 if (extension == NULL || extension->is_cleared) {
154 // Not present. Return the default value.
155 return *factory->GetPrototype(message_type);
156 } else {
157 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
158 if (extension->is_lazy) {
159 return extension->lazymessage_value->GetMessage(
160 *factory->GetPrototype(message_type));
161 } else {
162 return *extension->message_value;
163 }
164 }
165 }
166
MutableMessage(const FieldDescriptor * descriptor,MessageFactory * factory)167 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
168 MessageFactory* factory) {
169 Extension* extension;
170 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
171 extension->type = descriptor->type();
172 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
173 extension->is_repeated = false;
174 extension->is_packed = false;
175 const MessageLite* prototype =
176 factory->GetPrototype(descriptor->message_type());
177 extension->is_lazy = false;
178 extension->message_value = prototype->New(arena_);
179 extension->is_cleared = false;
180 return extension->message_value;
181 } else {
182 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
183 extension->is_cleared = false;
184 if (extension->is_lazy) {
185 return extension->lazymessage_value->MutableMessage(
186 *factory->GetPrototype(descriptor->message_type()));
187 } else {
188 return extension->message_value;
189 }
190 }
191 }
192
ReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)193 MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
194 MessageFactory* factory) {
195 Extension* extension = FindOrNull(descriptor->number());
196 if (extension == NULL) {
197 // Not present. Return NULL.
198 return NULL;
199 } else {
200 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
201 MessageLite* ret = NULL;
202 if (extension->is_lazy) {
203 ret = extension->lazymessage_value->ReleaseMessage(
204 *factory->GetPrototype(descriptor->message_type()));
205 if (arena_ == NULL) {
206 delete extension->lazymessage_value;
207 }
208 } else {
209 if (arena_ != NULL) {
210 ret = extension->message_value->New();
211 ret->CheckTypeAndMergeFrom(*extension->message_value);
212 } else {
213 ret = extension->message_value;
214 }
215 }
216 Erase(descriptor->number());
217 return ret;
218 }
219 }
220
UnsafeArenaReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)221 MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
222 const FieldDescriptor* descriptor, MessageFactory* factory) {
223 Extension* extension = FindOrNull(descriptor->number());
224 if (extension == NULL) {
225 // Not present. Return NULL.
226 return NULL;
227 } else {
228 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
229 MessageLite* ret = NULL;
230 if (extension->is_lazy) {
231 ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(
232 *factory->GetPrototype(descriptor->message_type()));
233 if (arena_ == NULL) {
234 delete extension->lazymessage_value;
235 }
236 } else {
237 ret = extension->message_value;
238 }
239 Erase(descriptor->number());
240 return ret;
241 }
242 }
243
MaybeNewRepeatedExtension(const FieldDescriptor * descriptor)244 ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(
245 const FieldDescriptor* descriptor) {
246 Extension* extension;
247 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
248 extension->type = descriptor->type();
249 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
250 extension->is_repeated = true;
251 extension->repeated_message_value =
252 Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
253 } else {
254 GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
255 }
256 return extension;
257 }
258
AddMessage(const FieldDescriptor * descriptor,MessageFactory * factory)259 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
260 MessageFactory* factory) {
261 Extension* extension = MaybeNewRepeatedExtension(descriptor);
262
263 // RepeatedPtrField<Message> does not know how to Add() since it cannot
264 // allocate an abstract object, so we have to be tricky.
265 MessageLite* result =
266 reinterpret_cast<internal::RepeatedPtrFieldBase*>(
267 extension->repeated_message_value)
268 ->AddFromCleared<GenericTypeHandler<MessageLite> >();
269 if (result == NULL) {
270 const MessageLite* prototype;
271 if (extension->repeated_message_value->size() == 0) {
272 prototype = factory->GetPrototype(descriptor->message_type());
273 GOOGLE_CHECK(prototype != NULL);
274 } else {
275 prototype = &extension->repeated_message_value->Get(0);
276 }
277 result = prototype->New(arena_);
278 extension->repeated_message_value->AddAllocated(result);
279 }
280 return result;
281 }
282
AddAllocatedMessage(const FieldDescriptor * descriptor,MessageLite * new_entry)283 void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
284 MessageLite* new_entry) {
285 Extension* extension = MaybeNewRepeatedExtension(descriptor);
286
287 extension->repeated_message_value->AddAllocated(new_entry);
288 }
289
ValidateEnumUsingDescriptor(const void * arg,int number)290 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
291 return reinterpret_cast<const EnumDescriptor*>(arg)->FindValueByNumber(
292 number) != NULL;
293 }
294
Find(int number,ExtensionInfo * output)295 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
296 const FieldDescriptor* extension =
297 pool_->FindExtensionByNumber(containing_type_, number);
298 if (extension == NULL) {
299 return false;
300 } else {
301 output->type = extension->type();
302 output->is_repeated = extension->is_repeated();
303 output->is_packed = extension->options().packed();
304 output->descriptor = extension;
305 if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
306 output->message_info.prototype =
307 factory_->GetPrototype(extension->message_type());
308 GOOGLE_CHECK(output->message_info.prototype != nullptr)
309 << "Extension factory's GetPrototype() returned NULL for extension: "
310 << extension->full_name();
311 } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
312 output->enum_validity_check.func = ValidateEnumUsingDescriptor;
313 output->enum_validity_check.arg = extension->enum_type();
314 }
315
316 return true;
317 }
318 }
319
320
321 #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
FindExtension(int wire_type,uint32 field,const Message * containing_type,const internal::ParseContext * ctx,ExtensionInfo * extension,bool * was_packed_on_wire)322 bool ExtensionSet::FindExtension(int wire_type, uint32 field,
323 const Message* containing_type,
324 const internal::ParseContext* ctx,
325 ExtensionInfo* extension,
326 bool* was_packed_on_wire) {
327 if (ctx->data().pool == nullptr) {
328 GeneratedExtensionFinder finder(containing_type);
329 if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
330 was_packed_on_wire)) {
331 return false;
332 }
333 } else {
334 DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory,
335 containing_type->GetDescriptor());
336 if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension,
337 was_packed_on_wire)) {
338 return false;
339 }
340 }
341 return true;
342 }
343
ParseField(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)344 const char* ExtensionSet::ParseField(
345 uint64 tag, const char* ptr, const Message* containing_type,
346 internal::InternalMetadataWithArena* metadata,
347 internal::ParseContext* ctx) {
348 int number = tag >> 3;
349 bool was_packed_on_wire;
350 ExtensionInfo extension;
351 if (!FindExtension(tag & 7, number, containing_type, ctx, &extension,
352 &was_packed_on_wire)) {
353 return UnknownFieldParse(tag, metadata->mutable_unknown_fields(), ptr, ctx);
354 }
355 return ParseFieldWithExtensionInfo(number, was_packed_on_wire, extension,
356 metadata, ptr, ctx);
357 }
358
ParseFieldMaybeLazily(uint64 tag,const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)359 const char* ExtensionSet::ParseFieldMaybeLazily(
360 uint64 tag, const char* ptr, const Message* containing_type,
361 internal::InternalMetadataWithArena* metadata,
362 internal::ParseContext* ctx) {
363 return ParseField(tag, ptr, containing_type, metadata, ctx);
364 }
365
ParseMessageSetItem(const char * ptr,const Message * containing_type,internal::InternalMetadataWithArena * metadata,internal::ParseContext * ctx)366 const char* ExtensionSet::ParseMessageSetItem(
367 const char* ptr, const Message* containing_type,
368 internal::InternalMetadataWithArena* metadata,
369 internal::ParseContext* ctx) {
370 return ParseMessageSetItemTmpl(ptr, containing_type, metadata, ctx);
371 }
372
373 #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
374
ParseField(uint32 tag,io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)375 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
376 const Message* containing_type,
377 UnknownFieldSet* unknown_fields) {
378 UnknownFieldSetFieldSkipper skipper(unknown_fields);
379 if (input->GetExtensionPool() == NULL) {
380 GeneratedExtensionFinder finder(containing_type);
381 return ParseField(tag, input, &finder, &skipper);
382 } else {
383 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
384 input->GetExtensionFactory(),
385 containing_type->GetDescriptor());
386 return ParseField(tag, input, &finder, &skipper);
387 }
388 }
389
ParseMessageSet(io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)390 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
391 const Message* containing_type,
392 UnknownFieldSet* unknown_fields) {
393 MessageSetFieldSkipper skipper(unknown_fields);
394 if (input->GetExtensionPool() == NULL) {
395 GeneratedExtensionFinder finder(containing_type);
396 return ParseMessageSet(input, &finder, &skipper);
397 } else {
398 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
399 input->GetExtensionFactory(),
400 containing_type->GetDescriptor());
401 return ParseMessageSet(input, &finder, &skipper);
402 }
403 }
404
SpaceUsedExcludingSelf() const405 int ExtensionSet::SpaceUsedExcludingSelf() const {
406 return internal::FromIntSize(SpaceUsedExcludingSelfLong());
407 }
408
SpaceUsedExcludingSelfLong() const409 size_t ExtensionSet::SpaceUsedExcludingSelfLong() const {
410 size_t total_size = Size() * sizeof(KeyValue);
411 ForEach([&total_size](int /* number */, const Extension& ext) {
412 total_size += ext.SpaceUsedExcludingSelfLong();
413 });
414 return total_size;
415 }
416
RepeatedMessage_SpaceUsedExcludingSelfLong(RepeatedPtrFieldBase * field)417 inline size_t ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelfLong(
418 RepeatedPtrFieldBase* field) {
419 return field->SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >();
420 }
421
SpaceUsedExcludingSelfLong() const422 size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
423 size_t total_size = 0;
424 if (is_repeated) {
425 switch (cpp_type(type)) {
426 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
427 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
428 total_size += sizeof(*repeated_##LOWERCASE##_value) + \
429 repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \
430 break
431
432 HANDLE_TYPE(INT32, int32);
433 HANDLE_TYPE(INT64, int64);
434 HANDLE_TYPE(UINT32, uint32);
435 HANDLE_TYPE(UINT64, uint64);
436 HANDLE_TYPE(FLOAT, float);
437 HANDLE_TYPE(DOUBLE, double);
438 HANDLE_TYPE(BOOL, bool);
439 HANDLE_TYPE(ENUM, enum);
440 HANDLE_TYPE(STRING, string);
441 #undef HANDLE_TYPE
442
443 case FieldDescriptor::CPPTYPE_MESSAGE:
444 // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
445 // but MessageLite has no SpaceUsedLong(), so we must directly call
446 // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different
447 // type handler.
448 total_size += sizeof(*repeated_message_value) +
449 RepeatedMessage_SpaceUsedExcludingSelfLong(
450 reinterpret_cast<internal::RepeatedPtrFieldBase*>(
451 repeated_message_value));
452 break;
453 }
454 } else {
455 switch (cpp_type(type)) {
456 case FieldDescriptor::CPPTYPE_STRING:
457 total_size += sizeof(*string_value) +
458 StringSpaceUsedExcludingSelfLong(*string_value);
459 break;
460 case FieldDescriptor::CPPTYPE_MESSAGE:
461 if (is_lazy) {
462 total_size += lazymessage_value->SpaceUsedLong();
463 } else {
464 total_size += down_cast<Message*>(message_value)->SpaceUsedLong();
465 }
466 break;
467 default:
468 // No extra storage costs for primitive types.
469 break;
470 }
471 }
472 return total_size;
473 }
474
475 // The Serialize*ToArray methods are only needed in the heavy library, as
476 // the lite library only generates SerializeWithCachedSizes.
SerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const477 uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number,
478 int end_field_number,
479 uint8* target) const {
480 return InternalSerializeWithCachedSizesToArray(start_field_number,
481 end_field_number, target);
482 }
483
SerializeMessageSetWithCachedSizesToArray(uint8 * target) const484 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
485 uint8* target) const {
486 return InternalSerializeMessageSetWithCachedSizesToArray(target);
487 }
488
InternalSerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const489 uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray(
490 int start_field_number, int end_field_number, uint8* target) const {
491 if (PROTOBUF_PREDICT_FALSE(is_large())) {
492 const auto& end = map_.large->end();
493 for (auto it = map_.large->lower_bound(start_field_number);
494 it != end && it->first < end_field_number; ++it) {
495 target = it->second.InternalSerializeFieldWithCachedSizesToArray(
496 it->first, target);
497 }
498 return target;
499 }
500 const KeyValue* end = flat_end();
501 for (const KeyValue* it = std::lower_bound(
502 flat_begin(), end, start_field_number, KeyValue::FirstComparator());
503 it != end && it->first < end_field_number; ++it) {
504 target = it->second.InternalSerializeFieldWithCachedSizesToArray(it->first,
505 target);
506 }
507 return target;
508 }
509
InternalSerializeMessageSetWithCachedSizesToArray(uint8 * target) const510 uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
511 uint8* target) const {
512 ForEach([&target](int number, const Extension& ext) {
513 target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray(number,
514 target);
515 });
516 return target;
517 }
518
InternalSerializeFieldWithCachedSizesToArray(int number,uint8 * target) const519 uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
520 int number, uint8* target) const {
521 if (is_repeated) {
522 if (is_packed) {
523 if (cached_size == 0) return target;
524
525 target = WireFormatLite::WriteTagToArray(
526 number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
527 target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
528
529 switch (real_type(type)) {
530 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
531 case FieldDescriptor::TYPE_##UPPERCASE: \
532 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
533 target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
534 repeated_##LOWERCASE##_value->Get(i), target); \
535 } \
536 break
537
538 HANDLE_TYPE(INT32, Int32, int32);
539 HANDLE_TYPE(INT64, Int64, int64);
540 HANDLE_TYPE(UINT32, UInt32, uint32);
541 HANDLE_TYPE(UINT64, UInt64, uint64);
542 HANDLE_TYPE(SINT32, SInt32, int32);
543 HANDLE_TYPE(SINT64, SInt64, int64);
544 HANDLE_TYPE(FIXED32, Fixed32, uint32);
545 HANDLE_TYPE(FIXED64, Fixed64, uint64);
546 HANDLE_TYPE(SFIXED32, SFixed32, int32);
547 HANDLE_TYPE(SFIXED64, SFixed64, int64);
548 HANDLE_TYPE(FLOAT, Float, float);
549 HANDLE_TYPE(DOUBLE, Double, double);
550 HANDLE_TYPE(BOOL, Bool, bool);
551 HANDLE_TYPE(ENUM, Enum, enum);
552 #undef HANDLE_TYPE
553
554 case FieldDescriptor::TYPE_STRING:
555 case FieldDescriptor::TYPE_BYTES:
556 case FieldDescriptor::TYPE_GROUP:
557 case FieldDescriptor::TYPE_MESSAGE:
558 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
559 break;
560 }
561 } else {
562 switch (real_type(type)) {
563 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
564 case FieldDescriptor::TYPE_##UPPERCASE: \
565 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
566 target = WireFormatLite::Write##CAMELCASE##ToArray( \
567 number, repeated_##LOWERCASE##_value->Get(i), target); \
568 } \
569 break
570
571 HANDLE_TYPE(INT32, Int32, int32);
572 HANDLE_TYPE(INT64, Int64, int64);
573 HANDLE_TYPE(UINT32, UInt32, uint32);
574 HANDLE_TYPE(UINT64, UInt64, uint64);
575 HANDLE_TYPE(SINT32, SInt32, int32);
576 HANDLE_TYPE(SINT64, SInt64, int64);
577 HANDLE_TYPE(FIXED32, Fixed32, uint32);
578 HANDLE_TYPE(FIXED64, Fixed64, uint64);
579 HANDLE_TYPE(SFIXED32, SFixed32, int32);
580 HANDLE_TYPE(SFIXED64, SFixed64, int64);
581 HANDLE_TYPE(FLOAT, Float, float);
582 HANDLE_TYPE(DOUBLE, Double, double);
583 HANDLE_TYPE(BOOL, Bool, bool);
584 HANDLE_TYPE(STRING, String, string);
585 HANDLE_TYPE(BYTES, Bytes, string);
586 HANDLE_TYPE(ENUM, Enum, enum);
587 #undef HANDLE_TYPE
588 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
589 case FieldDescriptor::TYPE_##UPPERCASE: \
590 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
591 target = WireFormatLite::InternalWrite##CAMELCASE##ToArray( \
592 number, repeated_##LOWERCASE##_value->Get(i), target); \
593 } \
594 break
595
596 HANDLE_TYPE(GROUP, Group, message);
597 HANDLE_TYPE(MESSAGE, Message, message);
598 #undef HANDLE_TYPE
599 }
600 }
601 } else if (!is_cleared) {
602 switch (real_type(type)) {
603 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
604 case FieldDescriptor::TYPE_##UPPERCASE: \
605 target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \
606 break
607
608 HANDLE_TYPE(INT32, Int32, int32_value);
609 HANDLE_TYPE(INT64, Int64, int64_value);
610 HANDLE_TYPE(UINT32, UInt32, uint32_value);
611 HANDLE_TYPE(UINT64, UInt64, uint64_value);
612 HANDLE_TYPE(SINT32, SInt32, int32_value);
613 HANDLE_TYPE(SINT64, SInt64, int64_value);
614 HANDLE_TYPE(FIXED32, Fixed32, uint32_value);
615 HANDLE_TYPE(FIXED64, Fixed64, uint64_value);
616 HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
617 HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
618 HANDLE_TYPE(FLOAT, Float, float_value);
619 HANDLE_TYPE(DOUBLE, Double, double_value);
620 HANDLE_TYPE(BOOL, Bool, bool_value);
621 HANDLE_TYPE(STRING, String, *string_value);
622 HANDLE_TYPE(BYTES, Bytes, *string_value);
623 HANDLE_TYPE(ENUM, Enum, enum_value);
624 HANDLE_TYPE(GROUP, Group, *message_value);
625 #undef HANDLE_TYPE
626 case FieldDescriptor::TYPE_MESSAGE:
627 if (is_lazy) {
628 target = lazymessage_value->WriteMessageToArray(number, target);
629 } else {
630 target = WireFormatLite::InternalWriteMessageToArray(
631 number, *message_value, target);
632 }
633 break;
634 }
635 }
636 return target;
637 }
638
639 uint8*
InternalSerializeMessageSetItemWithCachedSizesToArray(int number,uint8 * target) const640 ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
641 int number, uint8* target) const {
642 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
643 // Not a valid MessageSet extension, but serialize it the normal way.
644 GOOGLE_LOG(WARNING) << "Invalid message set extension.";
645 return InternalSerializeFieldWithCachedSizesToArray(number, target);
646 }
647
648 if (is_cleared) return target;
649
650 // Start group.
651 target = io::CodedOutputStream::WriteTagToArray(
652 WireFormatLite::kMessageSetItemStartTag, target);
653 // Write type ID.
654 target = WireFormatLite::WriteUInt32ToArray(
655 WireFormatLite::kMessageSetTypeIdNumber, number, target);
656 // Write message.
657 if (is_lazy) {
658 target = lazymessage_value->WriteMessageToArray(
659 WireFormatLite::kMessageSetMessageNumber, target);
660 } else {
661 target = WireFormatLite::InternalWriteMessageToArray(
662 WireFormatLite::kMessageSetMessageNumber, *message_value, target);
663 }
664 // End group.
665 target = io::CodedOutputStream::WriteTagToArray(
666 WireFormatLite::kMessageSetItemEndTag, target);
667 return target;
668 }
669
ParseFieldMaybeLazily(int wire_type,int field_number,io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)670 bool ExtensionSet::ParseFieldMaybeLazily(
671 int wire_type, int field_number, io::CodedInputStream* input,
672 ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) {
673 return ParseField(
674 WireFormatLite::MakeTag(field_number,
675 static_cast<WireFormatLite::WireType>(wire_type)),
676 input, extension_finder, field_skipper);
677 }
678
ParseMessageSet(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)679 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
680 ExtensionFinder* extension_finder,
681 MessageSetFieldSkipper* field_skipper) {
682 while (true) {
683 const uint32 tag = input->ReadTag();
684 switch (tag) {
685 case 0:
686 return true;
687 case WireFormatLite::kMessageSetItemStartTag:
688 if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
689 return false;
690 }
691 break;
692 default:
693 if (!ParseField(tag, input, extension_finder, field_skipper)) {
694 return false;
695 }
696 break;
697 }
698 }
699 }
700
ParseMessageSetItem(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)701 bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
702 ExtensionFinder* extension_finder,
703 MessageSetFieldSkipper* field_skipper) {
704 struct MSFull {
705 bool ParseField(int type_id, io::CodedInputStream* input) {
706 return me->ParseFieldMaybeLazily(
707 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, type_id, input,
708 extension_finder, field_skipper);
709 }
710
711 bool SkipField(uint32 tag, io::CodedInputStream* input) {
712 return field_skipper->SkipField(input, tag);
713 }
714
715 ExtensionSet* me;
716 ExtensionFinder* extension_finder;
717 MessageSetFieldSkipper* field_skipper;
718 };
719
720 return ParseMessageSetItemImpl(input,
721 MSFull{this, extension_finder, field_skipper});
722 }
723
724 } // namespace internal
725 } // namespace protobuf
726 } // namespace google
727