1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
35 // Contains methods defined in extension_set.h which cannot be part of the
36 // lite library because they use descriptors or reflection.
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>
52 // Implementation of ExtensionFinder which finds extensions in a given
53 // DescriptorPool, using the given MessageFactory to construct sub-objects.
54 // This class is implemented in extension_set_heavy.cc.
55 class DescriptorPoolExtensionFinder : public ExtensionFinder {
57 DescriptorPoolExtensionFinder(const DescriptorPool* pool,
58 MessageFactory* factory,
59 const Descriptor* containing_type)
60 : pool_(pool), factory_(factory), containing_type_(containing_type) {}
61 virtual ~DescriptorPoolExtensionFinder() {}
63 virtual bool Find(int number, ExtensionInfo* output);
66 const DescriptorPool* pool_;
67 MessageFactory* factory_;
68 const Descriptor* containing_type_;
71 void ExtensionSet::AppendToList(const Descriptor* containing_type,
72 const DescriptorPool* pool,
73 vector<const FieldDescriptor*>* output) const {
74 for (map<int, Extension>::const_iterator iter = extensions_.begin();
75 iter != extensions_.end(); ++iter) {
77 if (iter->second.is_repeated) {
78 has = iter->second.GetSize() > 0;
80 has = !iter->second.is_cleared;
84 // TODO(kenton): Looking up each field by number is somewhat unfortunate.
85 // Is there a better way? The problem is that descriptors are lazily-
86 // initialized, so they might not even be constructed until
87 // AppendToList() is called.
89 if (iter->second.descriptor == NULL) {
90 output->push_back(pool->FindExtensionByNumber(
91 containing_type, iter->first));
93 output->push_back(iter->second.descriptor);
99 inline FieldDescriptor::Type real_type(FieldType type) {
100 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
101 return static_cast<FieldDescriptor::Type>(type);
104 inline FieldDescriptor::CppType cpp_type(FieldType type) {
105 return FieldDescriptor::TypeToCppType(
106 static_cast<FieldDescriptor::Type>(type));
109 inline WireFormatLite::FieldType field_type(FieldType type) {
110 GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
111 return static_cast<WireFormatLite::FieldType>(type);
114 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
115 GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
116 : FieldDescriptor::LABEL_OPTIONAL, \
117 FieldDescriptor::LABEL_##LABEL); \
118 GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
120 const MessageLite& ExtensionSet::GetMessage(int number,
121 const Descriptor* message_type,
122 MessageFactory* factory) const {
123 map<int, Extension>::const_iterator iter = extensions_.find(number);
124 if (iter == extensions_.end() || iter->second.is_cleared) {
125 // Not present. Return the default value.
126 return *factory->GetPrototype(message_type);
128 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
129 if (iter->second.is_lazy) {
130 return iter->second.lazymessage_value->GetMessage(
131 *factory->GetPrototype(message_type));
133 return *iter->second.message_value;
138 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
139 MessageFactory* factory) {
140 Extension* extension;
141 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
142 extension->type = descriptor->type();
143 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
144 extension->is_repeated = false;
145 extension->is_packed = false;
146 const MessageLite* prototype =
147 factory->GetPrototype(descriptor->message_type());
148 extension->is_lazy = false;
149 extension->message_value = prototype->New();
150 extension->is_cleared = false;
151 return extension->message_value;
153 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
154 extension->is_cleared = false;
155 if (extension->is_lazy) {
156 return extension->lazymessage_value->MutableMessage(
157 *factory->GetPrototype(descriptor->message_type()));
159 return extension->message_value;
164 MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
165 MessageFactory* factory) {
166 map<int, Extension>::iterator iter = extensions_.find(descriptor->number());
167 if (iter == extensions_.end()) {
168 // Not present. Return NULL.
171 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
172 MessageLite* ret = NULL;
173 if (iter->second.is_lazy) {
174 ret = iter->second.lazymessage_value->ReleaseMessage(
175 *factory->GetPrototype(descriptor->message_type()));
176 delete iter->second.lazymessage_value;
178 ret = iter->second.message_value;
180 extensions_.erase(descriptor->number());
185 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
186 MessageFactory* factory) {
187 Extension* extension;
188 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
189 extension->type = descriptor->type();
190 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
191 extension->is_repeated = true;
192 extension->repeated_message_value =
193 new RepeatedPtrField<MessageLite>();
195 GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
198 // RepeatedPtrField<Message> does not know how to Add() since it cannot
199 // allocate an abstract object, so we have to be tricky.
200 MessageLite* result = extension->repeated_message_value
201 ->AddFromCleared<GenericTypeHandler<MessageLite> >();
202 if (result == NULL) {
203 const MessageLite* prototype;
204 if (extension->repeated_message_value->size() == 0) {
205 prototype = factory->GetPrototype(descriptor->message_type());
206 GOOGLE_CHECK(prototype != NULL);
208 prototype = &extension->repeated_message_value->Get(0);
210 result = prototype->New();
211 extension->repeated_message_value->AddAllocated(result);
216 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
217 return reinterpret_cast<const EnumDescriptor*>(arg)
218 ->FindValueByNumber(number) != NULL;
221 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
222 const FieldDescriptor* extension =
223 pool_->FindExtensionByNumber(containing_type_, number);
224 if (extension == NULL) {
227 output->type = extension->type();
228 output->is_repeated = extension->is_repeated();
229 output->is_packed = extension->options().packed();
230 output->descriptor = extension;
231 if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
232 output->message_prototype =
233 factory_->GetPrototype(extension->message_type());
234 GOOGLE_CHECK(output->message_prototype != NULL)
235 << "Extension factory's GetPrototype() returned NULL for extension: "
236 << extension->full_name();
237 } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
238 output->enum_validity_check.func = ValidateEnumUsingDescriptor;
239 output->enum_validity_check.arg = extension->enum_type();
246 bool ExtensionSet::ParseFieldHeavy(uint32 tag, io::CodedInputStream* input,
247 const Message* containing_type,
248 UnknownFieldSet* unknown_fields) {
249 FieldSkipper skipper(unknown_fields);
250 if (input->GetExtensionPool() == NULL) {
251 GeneratedExtensionFinder finder(containing_type);
252 return ParseField(tag, input, &finder, &skipper);
254 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
255 input->GetExtensionFactory(),
256 containing_type->GetDescriptor());
257 return ParseField(tag, input, &finder, &skipper);
261 bool ExtensionSet::ParseMessageSetHeavy(io::CodedInputStream* input,
262 const Message* containing_type,
263 UnknownFieldSet* unknown_fields) {
264 FieldSkipper skipper(unknown_fields);
265 if (input->GetExtensionPool() == NULL) {
266 GeneratedExtensionFinder finder(containing_type);
267 return ParseMessageSet(input, &finder, &skipper);
269 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
270 input->GetExtensionFactory(),
271 containing_type->GetDescriptor());
272 return ParseMessageSet(input, &finder, &skipper);
276 int ExtensionSet::SpaceUsedExcludingSelf() const {
278 extensions_.size() * sizeof(map<int, Extension>::value_type);
279 for (map<int, Extension>::const_iterator iter = extensions_.begin(),
280 end = extensions_.end();
283 total_size += iter->second.SpaceUsedExcludingSelf();
288 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
289 RepeatedPtrFieldBase* field) {
290 return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
293 int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
296 switch (cpp_type(type)) {
297 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
298 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
299 total_size += sizeof(*repeated_##LOWERCASE##_value) + \
300 repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
303 HANDLE_TYPE( INT32, int32);
304 HANDLE_TYPE( INT64, int64);
305 HANDLE_TYPE( UINT32, uint32);
306 HANDLE_TYPE( UINT64, uint64);
307 HANDLE_TYPE( FLOAT, float);
308 HANDLE_TYPE( DOUBLE, double);
309 HANDLE_TYPE( BOOL, bool);
310 HANDLE_TYPE( ENUM, enum);
311 HANDLE_TYPE( STRING, string);
314 case FieldDescriptor::CPPTYPE_MESSAGE:
315 // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
316 // but MessageLite has no SpaceUsed(), so we must directly call
317 // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
319 total_size += sizeof(*repeated_message_value) +
320 RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
324 switch (cpp_type(type)) {
325 case FieldDescriptor::CPPTYPE_STRING:
326 total_size += sizeof(*string_value) +
327 StringSpaceUsedExcludingSelf(*string_value);
329 case FieldDescriptor::CPPTYPE_MESSAGE:
331 total_size += lazymessage_value->SpaceUsed();
333 total_size += down_cast<Message*>(message_value)->SpaceUsed();
337 // No extra storage costs for primitive types.
344 // The Serialize*ToArray methods are only needed in the heavy library, as
345 // the lite library only generates SerializeWithCachedSizes.
346 uint8* ExtensionSet::SerializeWithCachedSizesToArray(
347 int start_field_number, int end_field_number,
348 uint8* target) const {
349 map<int, Extension>::const_iterator iter;
350 for (iter = extensions_.lower_bound(start_field_number);
351 iter != extensions_.end() && iter->first < end_field_number;
353 target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
359 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
360 uint8* target) const {
361 map<int, Extension>::const_iterator iter;
362 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
363 target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
364 iter->first, target);
369 uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
370 int number, uint8* target) const {
373 if (cached_size == 0) return target;
375 target = WireFormatLite::WriteTagToArray(number,
376 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
377 target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
379 switch (real_type(type)) {
380 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
381 case FieldDescriptor::TYPE_##UPPERCASE: \
382 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
383 target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
384 repeated_##LOWERCASE##_value->Get(i), target); \
388 HANDLE_TYPE( INT32, Int32, int32);
389 HANDLE_TYPE( INT64, Int64, int64);
390 HANDLE_TYPE( UINT32, UInt32, uint32);
391 HANDLE_TYPE( UINT64, UInt64, uint64);
392 HANDLE_TYPE( SINT32, SInt32, int32);
393 HANDLE_TYPE( SINT64, SInt64, int64);
394 HANDLE_TYPE( FIXED32, Fixed32, uint32);
395 HANDLE_TYPE( FIXED64, Fixed64, uint64);
396 HANDLE_TYPE(SFIXED32, SFixed32, int32);
397 HANDLE_TYPE(SFIXED64, SFixed64, int64);
398 HANDLE_TYPE( FLOAT, Float, float);
399 HANDLE_TYPE( DOUBLE, Double, double);
400 HANDLE_TYPE( BOOL, Bool, bool);
401 HANDLE_TYPE( ENUM, Enum, enum);
404 case WireFormatLite::TYPE_STRING:
405 case WireFormatLite::TYPE_BYTES:
406 case WireFormatLite::TYPE_GROUP:
407 case WireFormatLite::TYPE_MESSAGE:
408 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
412 switch (real_type(type)) {
413 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
414 case FieldDescriptor::TYPE_##UPPERCASE: \
415 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
416 target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
417 repeated_##LOWERCASE##_value->Get(i), target); \
421 HANDLE_TYPE( INT32, Int32, int32);
422 HANDLE_TYPE( INT64, Int64, int64);
423 HANDLE_TYPE( UINT32, UInt32, uint32);
424 HANDLE_TYPE( UINT64, UInt64, uint64);
425 HANDLE_TYPE( SINT32, SInt32, int32);
426 HANDLE_TYPE( SINT64, SInt64, int64);
427 HANDLE_TYPE( FIXED32, Fixed32, uint32);
428 HANDLE_TYPE( FIXED64, Fixed64, uint64);
429 HANDLE_TYPE(SFIXED32, SFixed32, int32);
430 HANDLE_TYPE(SFIXED64, SFixed64, int64);
431 HANDLE_TYPE( FLOAT, Float, float);
432 HANDLE_TYPE( DOUBLE, Double, double);
433 HANDLE_TYPE( BOOL, Bool, bool);
434 HANDLE_TYPE( STRING, String, string);
435 HANDLE_TYPE( BYTES, Bytes, string);
436 HANDLE_TYPE( ENUM, Enum, enum);
437 HANDLE_TYPE( GROUP, Group, message);
438 HANDLE_TYPE( MESSAGE, Message, message);
442 } else if (!is_cleared) {
443 switch (real_type(type)) {
444 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
445 case FieldDescriptor::TYPE_##UPPERCASE: \
446 target = WireFormatLite::Write##CAMELCASE##ToArray( \
447 number, VALUE, target); \
450 HANDLE_TYPE( INT32, Int32, int32_value);
451 HANDLE_TYPE( INT64, Int64, int64_value);
452 HANDLE_TYPE( UINT32, UInt32, uint32_value);
453 HANDLE_TYPE( UINT64, UInt64, uint64_value);
454 HANDLE_TYPE( SINT32, SInt32, int32_value);
455 HANDLE_TYPE( SINT64, SInt64, int64_value);
456 HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
457 HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
458 HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
459 HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
460 HANDLE_TYPE( FLOAT, Float, float_value);
461 HANDLE_TYPE( DOUBLE, Double, double_value);
462 HANDLE_TYPE( BOOL, Bool, bool_value);
463 HANDLE_TYPE( STRING, String, *string_value);
464 HANDLE_TYPE( BYTES, Bytes, *string_value);
465 HANDLE_TYPE( ENUM, Enum, enum_value);
466 HANDLE_TYPE( GROUP, Group, *message_value);
468 case FieldDescriptor::TYPE_MESSAGE:
470 target = lazymessage_value->WriteMessageToArray(number, target);
472 target = WireFormatLite::WriteMessageToArray(
473 number, *message_value, target);
481 uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
483 uint8* target) const {
484 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
485 // Not a valid MessageSet extension, but serialize it the normal way.
486 GOOGLE_LOG(WARNING) << "Invalid message set extension.";
487 return SerializeFieldWithCachedSizesToArray(number, target);
490 if (is_cleared) return target;
493 target = io::CodedOutputStream::WriteTagToArray(
494 WireFormatLite::kMessageSetItemStartTag, target);
496 target = WireFormatLite::WriteUInt32ToArray(
497 WireFormatLite::kMessageSetTypeIdNumber, number, target);
500 target = lazymessage_value->WriteMessageToArray(
501 WireFormatLite::kMessageSetMessageNumber, target);
503 target = WireFormatLite::WriteMessageToArray(
504 WireFormatLite::kMessageSetMessageNumber, *message_value, target);
507 target = io::CodedOutputStream::WriteTagToArray(
508 WireFormatLite::kMessageSetItemEndTag, target);
513 bool ExtensionSet::ParseFieldMaybeLazily(
514 uint32 tag, io::CodedInputStream* input,
515 ExtensionFinder* extension_finder,
516 FieldSkipper* field_skipper) {
517 return ParseField(tag, input, extension_finder, field_skipper);
520 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
521 ExtensionFinder* extension_finder,
522 FieldSkipper* field_skipper) {
524 uint32 tag = input->ReadTag();
528 case WireFormatLite::kMessageSetItemStartTag:
529 if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
534 if (!ParseField(tag, input, extension_finder, field_skipper)) {
542 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
543 const MessageLite* containing_type,
544 UnknownFieldSet* unknown_fields) {
545 FieldSkipper skipper(unknown_fields);
546 GeneratedExtensionFinder finder(containing_type);
547 return ParseMessageSet(input, &finder, &skipper);
550 bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
551 ExtensionFinder* extension_finder,
552 FieldSkipper* field_skipper) {
553 // TODO(kenton): It would be nice to share code between this and
554 // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
555 // differences would be hard to factor out.
557 // This method parses a group which should contain two fields:
558 // required int32 type_id = 2;
559 // required data message = 3;
561 // Once we see a type_id, we'll construct a fake tag for this extension
562 // which is the tag it would have had under the proto2 extensions wire
566 // If we see message data before the type_id, we'll append it to this so
567 // we can parse it later.
571 uint32 tag = input->ReadTag();
572 if (tag == 0) return false;
575 case WireFormatLite::kMessageSetTypeIdTag: {
577 if (!input->ReadVarint32(&type_id)) return false;
578 fake_tag = WireFormatLite::MakeTag(type_id,
579 WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
581 if (!message_data.empty()) {
582 // We saw some message data before the type_id. Have to parse it
584 io::CodedInputStream sub_input(
585 reinterpret_cast<const uint8*>(message_data.data()),
586 message_data.size());
587 if (!ParseFieldMaybeLazily(fake_tag, &sub_input,
588 extension_finder, field_skipper)) {
591 message_data.clear();
597 case WireFormatLite::kMessageSetMessageTag: {
599 // We haven't seen a type_id yet. Append this data to message_data.
602 if (!input->ReadVarint32(&length)) return false;
603 if (!input->ReadString(&temp, length)) return false;
604 io::StringOutputStream output_stream(&message_data);
605 io::CodedOutputStream coded_output(&output_stream);
606 coded_output.WriteVarint32(length);
607 coded_output.WriteString(temp);
609 // Already saw type_id, so we can parse this directly.
610 if (!ParseFieldMaybeLazily(fake_tag, input,
611 extension_finder, field_skipper)) {
619 case WireFormatLite::kMessageSetItemEndTag: {
624 if (!field_skipper->SkipField(input, tag)) return false;
630 void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
632 io::CodedOutputStream* output) const {
633 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
634 // Not a valid MessageSet extension, but serialize it the normal way.
635 SerializeFieldWithCachedSizes(number, output);
639 if (is_cleared) return;
642 output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
645 WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
650 lazymessage_value->WriteMessage(
651 WireFormatLite::kMessageSetMessageNumber, output);
653 WireFormatLite::WriteMessageMaybeToArray(
654 WireFormatLite::kMessageSetMessageNumber,
660 output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
663 int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
664 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
665 // Not a valid MessageSet extension, but compute the byte size for it the
667 return ByteSize(number);
670 if (is_cleared) return 0;
672 int our_size = WireFormatLite::kMessageSetItemTagsSize;
675 our_size += io::CodedOutputStream::VarintSize32(number);
678 int message_size = 0;
680 message_size = lazymessage_value->ByteSize();
682 message_size = message_value->ByteSize();
685 our_size += io::CodedOutputStream::VarintSize32(message_size);
686 our_size += message_size;
691 void ExtensionSet::SerializeMessageSetWithCachedSizes(
692 io::CodedOutputStream* output) const {
693 map<int, Extension>::const_iterator iter;
694 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
695 iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
699 int ExtensionSet::MessageSetByteSize() const {
702 for (map<int, Extension>::const_iterator iter = extensions_.begin();
703 iter != extensions_.end(); ++iter) {
704 total_size += iter->second.MessageSetItemByteSize(iter->first);
710 } // namespace internal
711 } // namespace protobuf
712 } // namespace google