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