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 (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 // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet. 52 class 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 }; 62 bool 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. 78 class 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 94 void 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 123 inline FieldDescriptor::Type real_type(FieldType type) { 124 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE); 125 return static_cast<FieldDescriptor::Type>(type); 126 } 127 128 inline FieldDescriptor::CppType cpp_type(FieldType type) { 129 return FieldDescriptor::TypeToCppType( 130 static_cast<FieldDescriptor::Type>(type)); 131 } 132 133 inline 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 144 const 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 162 MessageLite* 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 188 MessageLite* 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 216 ExtensionSet::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 230 MessageLite* 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 252 void 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 259 static bool ValidateEnumUsingDescriptor(const void* arg, int number) { 260 return reinterpret_cast<const EnumDescriptor*>(arg) 261 ->FindValueByNumber(number) != NULL; 262 } 263 264 bool 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 289 bool 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 304 bool 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 319 int 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 331 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf( 332 RepeatedPtrFieldBase* field) { 333 return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >(); 334 } 335 336 int 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. 389 uint8* 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 402 uint8* 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 412 uint8* 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 524 uint8* 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 556 bool 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 565 bool 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 587 bool 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 594 bool 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 672 void 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 705 int 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 733 void 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 741 int 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 755