1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 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 (at) 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 46 namespace google { 47 48 namespace protobuf { 49 namespace internal { 50 51 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 { 56 public: 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() {} 62 63 virtual bool Find(int number, ExtensionInfo* output); 64 65 private: 66 const DescriptorPool* pool_; 67 MessageFactory* factory_; 68 const Descriptor* containing_type_; 69 }; 70 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) { 76 bool has = false; 77 if (iter->second.is_repeated) { 78 has = iter->second.GetSize() > 0; 79 } else { 80 has = !iter->second.is_cleared; 81 } 82 83 if (has) { 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. 88 89 if (iter->second.descriptor == NULL) { 90 output->push_back(pool->FindExtensionByNumber( 91 containing_type, iter->first)); 92 } else { 93 output->push_back(iter->second.descriptor); 94 } 95 } 96 } 97 } 98 99 inline FieldDescriptor::Type real_type(FieldType type) { 100 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE); 101 return static_cast<FieldDescriptor::Type>(type); 102 } 103 104 inline FieldDescriptor::CppType cpp_type(FieldType type) { 105 return FieldDescriptor::TypeToCppType( 106 static_cast<FieldDescriptor::Type>(type)); 107 } 108 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); 112 } 113 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) 119 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); 127 } else { 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)); 132 } else { 133 return *iter->second.message_value; 134 } 135 } 136 } 137 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; 152 } else { 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())); 158 } else { 159 return extension->message_value; 160 } 161 } 162 } 163 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. 169 return NULL; 170 } else { 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; 177 } else { 178 ret = iter->second.message_value; 179 } 180 extensions_.erase(descriptor->number()); 181 return ret; 182 } 183 } 184 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>(); 194 } else { 195 GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); 196 } 197 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); 207 } else { 208 prototype = &extension->repeated_message_value->Get(0); 209 } 210 result = prototype->New(); 211 extension->repeated_message_value->AddAllocated(result); 212 } 213 return result; 214 } 215 216 static bool ValidateEnumUsingDescriptor(const void* arg, int number) { 217 return reinterpret_cast<const EnumDescriptor*>(arg) 218 ->FindValueByNumber(number) != NULL; 219 } 220 221 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { 222 const FieldDescriptor* extension = 223 pool_->FindExtensionByNumber(containing_type_, number); 224 if (extension == NULL) { 225 return false; 226 } else { 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(); 240 } 241 242 return true; 243 } 244 } 245 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); 253 } else { 254 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(), 255 input->GetExtensionFactory(), 256 containing_type->GetDescriptor()); 257 return ParseField(tag, input, &finder, &skipper); 258 } 259 } 260 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); 268 } else { 269 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(), 270 input->GetExtensionFactory(), 271 containing_type->GetDescriptor()); 272 return ParseMessageSet(input, &finder, &skipper); 273 } 274 } 275 276 int ExtensionSet::SpaceUsedExcludingSelf() const { 277 int total_size = 278 extensions_.size() * sizeof(map<int, Extension>::value_type); 279 for (map<int, Extension>::const_iterator iter = extensions_.begin(), 280 end = extensions_.end(); 281 iter != end; 282 ++iter) { 283 total_size += iter->second.SpaceUsedExcludingSelf(); 284 } 285 return total_size; 286 } 287 288 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf( 289 RepeatedPtrFieldBase* field) { 290 return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >(); 291 } 292 293 int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { 294 int total_size = 0; 295 if (is_repeated) { 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();\ 301 break 302 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); 312 #undef HANDLE_TYPE 313 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 318 // handler. 319 total_size += sizeof(*repeated_message_value) + 320 RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value); 321 break; 322 } 323 } else { 324 switch (cpp_type(type)) { 325 case FieldDescriptor::CPPTYPE_STRING: 326 total_size += sizeof(*string_value) + 327 StringSpaceUsedExcludingSelf(*string_value); 328 break; 329 case FieldDescriptor::CPPTYPE_MESSAGE: 330 if (is_lazy) { 331 total_size += lazymessage_value->SpaceUsed(); 332 } else { 333 total_size += down_cast<Message*>(message_value)->SpaceUsed(); 334 } 335 break; 336 default: 337 // No extra storage costs for primitive types. 338 break; 339 } 340 } 341 return total_size; 342 } 343 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; 352 ++iter) { 353 target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first, 354 target); 355 } 356 return target; 357 } 358 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); 365 } 366 return target; 367 } 368 369 uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( 370 int number, uint8* target) const { 371 if (is_repeated) { 372 if (is_packed) { 373 if (cached_size == 0) return target; 374 375 target = WireFormatLite::WriteTagToArray(number, 376 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); 377 target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); 378 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); \ 385 } \ 386 break 387 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); 402 #undef HANDLE_TYPE 403 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."; 409 break; 410 } 411 } else { 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); \ 418 } \ 419 break 420 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); 439 #undef HANDLE_TYPE 440 } 441 } 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); \ 448 break 449 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); 467 #undef HANDLE_TYPE 468 case FieldDescriptor::TYPE_MESSAGE: 469 if (is_lazy) { 470 target = lazymessage_value->WriteMessageToArray(number, target); 471 } else { 472 target = WireFormatLite::WriteMessageToArray( 473 number, *message_value, target); 474 } 475 break; 476 } 477 } 478 return target; 479 } 480 481 uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( 482 int number, 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); 488 } 489 490 if (is_cleared) return target; 491 492 // Start group. 493 target = io::CodedOutputStream::WriteTagToArray( 494 WireFormatLite::kMessageSetItemStartTag, target); 495 // Write type ID. 496 target = WireFormatLite::WriteUInt32ToArray( 497 WireFormatLite::kMessageSetTypeIdNumber, number, target); 498 // Write message. 499 if (is_lazy) { 500 target = lazymessage_value->WriteMessageToArray( 501 WireFormatLite::kMessageSetMessageNumber, target); 502 } else { 503 target = WireFormatLite::WriteMessageToArray( 504 WireFormatLite::kMessageSetMessageNumber, *message_value, target); 505 } 506 // End group. 507 target = io::CodedOutputStream::WriteTagToArray( 508 WireFormatLite::kMessageSetItemEndTag, target); 509 return target; 510 } 511 512 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); 518 } 519 520 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, 521 ExtensionFinder* extension_finder, 522 FieldSkipper* field_skipper) { 523 while (true) { 524 uint32 tag = input->ReadTag(); 525 switch (tag) { 526 case 0: 527 return true; 528 case WireFormatLite::kMessageSetItemStartTag: 529 if (!ParseMessageSetItem(input, extension_finder, field_skipper)) { 530 return false; 531 } 532 break; 533 default: 534 if (!ParseField(tag, input, extension_finder, field_skipper)) { 535 return false; 536 } 537 break; 538 } 539 } 540 } 541 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); 548 } 549 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. 556 557 // This method parses a group which should contain two fields: 558 // required int32 type_id = 2; 559 // required data message = 3; 560 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 563 // format. 564 uint32 fake_tag = 0; 565 566 // If we see message data before the type_id, we'll append it to this so 567 // we can parse it later. 568 string message_data; 569 570 while (true) { 571 uint32 tag = input->ReadTag(); 572 if (tag == 0) return false; 573 574 switch (tag) { 575 case WireFormatLite::kMessageSetTypeIdTag: { 576 uint32 type_id; 577 if (!input->ReadVarint32(&type_id)) return false; 578 fake_tag = WireFormatLite::MakeTag(type_id, 579 WireFormatLite::WIRETYPE_LENGTH_DELIMITED); 580 581 if (!message_data.empty()) { 582 // We saw some message data before the type_id. Have to parse it 583 // now. 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)) { 589 return false; 590 } 591 message_data.clear(); 592 } 593 594 break; 595 } 596 597 case WireFormatLite::kMessageSetMessageTag: { 598 if (fake_tag == 0) { 599 // We haven't seen a type_id yet. Append this data to message_data. 600 string temp; 601 uint32 length; 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); 608 } else { 609 // Already saw type_id, so we can parse this directly. 610 if (!ParseFieldMaybeLazily(fake_tag, input, 611 extension_finder, field_skipper)) { 612 return false; 613 } 614 } 615 616 break; 617 } 618 619 case WireFormatLite::kMessageSetItemEndTag: { 620 return true; 621 } 622 623 default: { 624 if (!field_skipper->SkipField(input, tag)) return false; 625 } 626 } 627 } 628 } 629 630 void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( 631 int number, 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); 636 return; 637 } 638 639 if (is_cleared) return; 640 641 // Start group. 642 output->WriteTag(WireFormatLite::kMessageSetItemStartTag); 643 644 // Write type ID. 645 WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, 646 number, 647 output); 648 // Write message. 649 if (is_lazy) { 650 lazymessage_value->WriteMessage( 651 WireFormatLite::kMessageSetMessageNumber, output); 652 } else { 653 WireFormatLite::WriteMessageMaybeToArray( 654 WireFormatLite::kMessageSetMessageNumber, 655 *message_value, 656 output); 657 } 658 659 // End group. 660 output->WriteTag(WireFormatLite::kMessageSetItemEndTag); 661 } 662 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 666 // normal way. 667 return ByteSize(number); 668 } 669 670 if (is_cleared) return 0; 671 672 int our_size = WireFormatLite::kMessageSetItemTagsSize; 673 674 // type_id 675 our_size += io::CodedOutputStream::VarintSize32(number); 676 677 // message 678 int message_size = 0; 679 if (is_lazy) { 680 message_size = lazymessage_value->ByteSize(); 681 } else { 682 message_size = message_value->ByteSize(); 683 } 684 685 our_size += io::CodedOutputStream::VarintSize32(message_size); 686 our_size += message_size; 687 688 return our_size; 689 } 690 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); 696 } 697 } 698 699 int ExtensionSet::MessageSetByteSize() const { 700 int total_size = 0; 701 702 for (map<int, Extension>::const_iterator iter = extensions_.begin(); 703 iter != extensions_.end(); ++iter) { 704 total_size += iter->second.MessageSetItemByteSize(iter->first); 705 } 706 707 return total_size; 708 } 709 710 } // namespace internal 711 } // namespace protobuf 712 } // namespace google 713