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@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <stack> 36#include <string> 37#include <vector> 38 39#include <google/protobuf/wire_format.h> 40 41#include <google/protobuf/stubs/common.h> 42#include <google/protobuf/descriptor.h> 43#include <google/protobuf/wire_format_lite_inl.h> 44#include <google/protobuf/descriptor.pb.h> 45#include <google/protobuf/io/coded_stream.h> 46#include <google/protobuf/io/zero_copy_stream.h> 47#include <google/protobuf/io/zero_copy_stream_impl.h> 48#include <google/protobuf/unknown_field_set.h> 49 50 51 52namespace google { 53namespace protobuf { 54namespace internal { 55 56namespace { 57 58// This function turns out to be convenient when using some macros later. 59inline int GetEnumNumber(const EnumValueDescriptor* descriptor) { 60 return descriptor->number(); 61} 62 63} // anonymous namespace 64 65bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, 66 Message* message) { 67 const Descriptor* descriptor = message->GetDescriptor(); 68 const Reflection* message_reflection = message->GetReflection(); 69 70 while(true) { 71 uint32 tag = input->ReadTag(); 72 if (tag == 0) { 73 // End of input. This is a valid place to end, so return true. 74 return true; 75 } 76 77 if (WireFormatLite::GetTagWireType(tag) == 78 WireFormatLite::WIRETYPE_END_GROUP) { 79 // Must be the end of the message. 80 return true; 81 } 82 83 const FieldDescriptor* field = NULL; 84 85 if (descriptor != NULL) { 86 int field_number = WireFormatLite::GetTagFieldNumber(tag); 87 field = descriptor->FindFieldByNumber(field_number); 88 89 // If that failed, check if the field is an extension. 90 if (field == NULL && descriptor->IsExtensionNumber(field_number)) { 91 if (input->GetExtensionPool() == NULL) { 92 field = message_reflection->FindKnownExtensionByNumber(field_number); 93 } else { 94 field = input->GetExtensionPool() 95 ->FindExtensionByNumber(descriptor, field_number); 96 } 97 } 98 99 // If that failed, but we're a MessageSet, and this is the tag for a 100 // MessageSet item, then parse that. 101 if (field == NULL && 102 descriptor->options().message_set_wire_format() && 103 tag == WireFormatLite::kMessageSetItemStartTag) { 104 if (!ParseAndMergeMessageSetItem(input, message)) { 105 return false; 106 } 107 continue; // Skip ParseAndMergeField(); already taken care of. 108 } 109 } 110 111 if (!ParseAndMergeField(tag, field, message, input)) { 112 return false; 113 } 114 } 115} 116 117bool WireFormat::ParseAndMergeField( 118 uint32 tag, 119 const FieldDescriptor* field, // May be NULL for unknown 120 Message* message, 121 io::CodedInputStream* input) { 122 const Reflection* message_reflection = message->GetReflection(); 123 124 enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format; 125 126 if (field == NULL) { 127 value_format = UNKNOWN; 128 } else if (WireFormatLite::GetTagWireType(tag) == 129 WireTypeForFieldType(field->type())) { 130 value_format = NORMAL_FORMAT; 131 } else if (field->is_packable() && 132 WireFormatLite::GetTagWireType(tag) == 133 WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { 134 value_format = PACKED_FORMAT; 135 } else { 136 // We don't recognize this field. Either the field number is unknown 137 // or the wire type doesn't match. Put it in our unknown field set. 138 value_format = UNKNOWN; 139 } 140 141 if (value_format == UNKNOWN) { 142 return WireFormatLite::SkipField( 143 input, tag, message_reflection->MutableUnknownFields(message)); 144 } else if (value_format == PACKED_FORMAT) { 145 uint32 length; 146 if (!input->ReadVarint32(&length)) return false; 147 io::CodedInputStream::Limit limit = input->PushLimit(length); 148 149 switch (field->type()) { 150#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ 151 case FieldDescriptor::TYPE_##TYPE: { \ 152 while (input->BytesUntilLimit() > 0) { \ 153 CPPTYPE value; \ 154 if (!WireFormatLite::ReadPrimitive< \ 155 CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \ 156 return false; \ 157 message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ 158 } \ 159 break; \ 160 } 161 162 HANDLE_PACKED_TYPE( INT32, int32, Int32) 163 HANDLE_PACKED_TYPE( INT64, int64, Int64) 164 HANDLE_PACKED_TYPE(SINT32, int32, Int32) 165 HANDLE_PACKED_TYPE(SINT64, int64, Int64) 166 HANDLE_PACKED_TYPE(UINT32, uint32, UInt32) 167 HANDLE_PACKED_TYPE(UINT64, uint64, UInt64) 168 169 HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32) 170 HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64) 171 HANDLE_PACKED_TYPE(SFIXED32, int32, Int32) 172 HANDLE_PACKED_TYPE(SFIXED64, int64, Int64) 173 174 HANDLE_PACKED_TYPE(FLOAT , float , Float ) 175 HANDLE_PACKED_TYPE(DOUBLE, double, Double) 176 177 HANDLE_PACKED_TYPE(BOOL, bool, Bool) 178#undef HANDLE_PACKED_TYPE 179 180 case FieldDescriptor::TYPE_ENUM: { 181 while (input->BytesUntilLimit() > 0) { 182 int value; 183 if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( 184 input, &value)) return false; 185 const EnumValueDescriptor* enum_value = 186 field->enum_type()->FindValueByNumber(value); 187 if (enum_value != NULL) { 188 message_reflection->AddEnum(message, field, enum_value); 189 } 190 } 191 192 break; 193 } 194 195 case FieldDescriptor::TYPE_STRING: 196 case FieldDescriptor::TYPE_GROUP: 197 case FieldDescriptor::TYPE_MESSAGE: 198 case FieldDescriptor::TYPE_BYTES: 199 // Can't have packed fields of these types: these should be caught by 200 // the protocol compiler. 201 return false; 202 break; 203 } 204 205 input->PopLimit(limit); 206 } else { 207 // Non-packed value (value_format == NORMAL_FORMAT) 208 switch (field->type()) { 209#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ 210 case FieldDescriptor::TYPE_##TYPE: { \ 211 CPPTYPE value; \ 212 if (!WireFormatLite::ReadPrimitive< \ 213 CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \ 214 return false; \ 215 if (field->is_repeated()) { \ 216 message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ 217 } else { \ 218 message_reflection->Set##CPPTYPE_METHOD(message, field, value); \ 219 } \ 220 break; \ 221 } 222 223 HANDLE_TYPE( INT32, int32, Int32) 224 HANDLE_TYPE( INT64, int64, Int64) 225 HANDLE_TYPE(SINT32, int32, Int32) 226 HANDLE_TYPE(SINT64, int64, Int64) 227 HANDLE_TYPE(UINT32, uint32, UInt32) 228 HANDLE_TYPE(UINT64, uint64, UInt64) 229 230 HANDLE_TYPE( FIXED32, uint32, UInt32) 231 HANDLE_TYPE( FIXED64, uint64, UInt64) 232 HANDLE_TYPE(SFIXED32, int32, Int32) 233 HANDLE_TYPE(SFIXED64, int64, Int64) 234 235 HANDLE_TYPE(FLOAT , float , Float ) 236 HANDLE_TYPE(DOUBLE, double, Double) 237 238 HANDLE_TYPE(BOOL, bool, Bool) 239#undef HANDLE_TYPE 240 241 case FieldDescriptor::TYPE_ENUM: { 242 int value; 243 if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( 244 input, &value)) return false; 245 const EnumValueDescriptor* enum_value = 246 field->enum_type()->FindValueByNumber(value); 247 if (enum_value != NULL) { 248 if (field->is_repeated()) { 249 message_reflection->AddEnum(message, field, enum_value); 250 } else { 251 message_reflection->SetEnum(message, field, enum_value); 252 } 253 } else { 254 // The enum value is not one of the known values. Add it to the 255 // UnknownFieldSet. 256 int64 sign_extended_value = static_cast<int64>(value); 257 message_reflection->MutableUnknownFields(message) 258 ->AddVarint(WireFormatLite::GetTagFieldNumber(tag), 259 sign_extended_value); 260 } 261 break; 262 } 263 264 // Handle strings separately so that we can optimize the ctype=CORD case. 265 case FieldDescriptor::TYPE_STRING: { 266 string value; 267 if (!WireFormatLite::ReadString(input, &value)) return false; 268 VerifyUTF8String(value.data(), value.length(), PARSE); 269 if (field->is_repeated()) { 270 message_reflection->AddString(message, field, value); 271 } else { 272 message_reflection->SetString(message, field, value); 273 } 274 break; 275 } 276 277 case FieldDescriptor::TYPE_BYTES: { 278 string value; 279 if (!WireFormatLite::ReadBytes(input, &value)) return false; 280 if (field->is_repeated()) { 281 message_reflection->AddString(message, field, value); 282 } else { 283 message_reflection->SetString(message, field, value); 284 } 285 break; 286 } 287 288 case FieldDescriptor::TYPE_GROUP: { 289 Message* sub_message; 290 if (field->is_repeated()) { 291 sub_message = message_reflection->AddMessage( 292 message, field, input->GetExtensionFactory()); 293 } else { 294 sub_message = message_reflection->MutableMessage( 295 message, field, input->GetExtensionFactory()); 296 } 297 298 if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag), 299 input, sub_message)) 300 return false; 301 break; 302 } 303 304 case FieldDescriptor::TYPE_MESSAGE: { 305 Message* sub_message; 306 if (field->is_repeated()) { 307 sub_message = message_reflection->AddMessage( 308 message, field, input->GetExtensionFactory()); 309 } else { 310 sub_message = message_reflection->MutableMessage( 311 message, field, input->GetExtensionFactory()); 312 } 313 314 if (!WireFormatLite::ReadMessage(input, sub_message)) return false; 315 break; 316 } 317 } 318 } 319 320 return true; 321} 322 323bool WireFormat::ParseAndMergeMessageSetItem( 324 io::CodedInputStream* input, 325 Message* message) { 326 const Reflection* message_reflection = message->GetReflection(); 327 328 // This method parses a group which should contain two fields: 329 // required int32 type_id = 2; 330 // required data message = 3; 331 332 // Once we see a type_id, we'll construct a fake tag for this extension 333 // which is the tag it would have had under the proto2 extensions wire 334 // format. 335 uint32 fake_tag = 0; 336 337 // Once we see a type_id, we'll look up the FieldDescriptor for the 338 // extension. 339 const FieldDescriptor* field = NULL; 340 341 // If we see message data before the type_id, we'll append it to this so 342 // we can parse it later. 343 string message_data; 344 345 while (true) { 346 uint32 tag = input->ReadTag(); 347 if (tag == 0) return false; 348 349 switch (tag) { 350 case WireFormatLite::kMessageSetTypeIdTag: { 351 uint32 type_id; 352 if (!input->ReadVarint32(&type_id)) return false; 353 fake_tag = WireFormatLite::MakeTag( 354 type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); 355 field = message_reflection->FindKnownExtensionByNumber(type_id); 356 357 if (!message_data.empty()) { 358 // We saw some message data before the type_id. Have to parse it 359 // now. 360 io::ArrayInputStream raw_input(message_data.data(), 361 message_data.size()); 362 io::CodedInputStream sub_input(&raw_input); 363 if (!ParseAndMergeField(fake_tag, field, message, 364 &sub_input)) { 365 return false; 366 } 367 message_data.clear(); 368 } 369 370 break; 371 } 372 373 case WireFormatLite::kMessageSetMessageTag: { 374 if (fake_tag == 0) { 375 // We haven't seen a type_id yet. Append this data to message_data. 376 string temp; 377 uint32 length; 378 if (!input->ReadVarint32(&length)) return false; 379 if (!input->ReadString(&temp, length)) return false; 380 io::StringOutputStream output_stream(&message_data); 381 io::CodedOutputStream coded_output(&output_stream); 382 coded_output.WriteVarint32(length); 383 coded_output.WriteString(temp); 384 } else { 385 // Already saw type_id, so we can parse this directly. 386 if (!ParseAndMergeField(fake_tag, field, message, input)) { 387 return false; 388 } 389 } 390 391 break; 392 } 393 394 case WireFormatLite::kMessageSetItemEndTag: { 395 return true; 396 } 397 398 default: { 399 if (!WireFormatLite::SkipField(input, tag, NULL)) return false; 400 } 401 } 402 } 403} 404 405// =================================================================== 406 407void WireFormat::SerializeWithCachedSizes( 408 const Message& message, 409 int size, io::CodedOutputStream* output) { 410 const Descriptor* descriptor = message.GetDescriptor(); 411 const Reflection* message_reflection = message.GetReflection(); 412 int expected_endpoint = output->ByteCount() + size; 413 414 vector<const FieldDescriptor*> fields; 415 message_reflection->ListFields(message, &fields); 416 for (int i = 0; i < fields.size(); i++) { 417 SerializeFieldWithCachedSizes(fields[i], message, output); 418 } 419 420 if (descriptor->options().message_set_wire_format()) { 421 WireFormatLite::SerializeUnknownMessageSetItems( 422 message_reflection->GetUnknownFields(message), output); 423 } else { 424 WireFormatLite::SerializeUnknownFields( 425 message_reflection->GetUnknownFields(message), output); 426 } 427 428 GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint) 429 << ": Protocol message serialized to a size different from what was " 430 "originally expected. Perhaps it was modified by another thread " 431 "during serialization?"; 432} 433 434void WireFormat::SerializeFieldWithCachedSizes( 435 const FieldDescriptor* field, 436 const Message& message, 437 io::CodedOutputStream* output) { 438 const Reflection* message_reflection = message.GetReflection(); 439 440 if (field->is_extension() && 441 field->containing_type()->options().message_set_wire_format() && 442 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && 443 !field->is_repeated()) { 444 SerializeMessageSetItemWithCachedSizes(field, message, output); 445 return; 446 } 447 448 int count = 0; 449 450 if (field->is_repeated()) { 451 count = message_reflection->FieldSize(message, field); 452 } else if (message_reflection->HasField(message, field)) { 453 count = 1; 454 } 455 456 const bool is_packed = field->options().packed(); 457 if (is_packed && count > 0) { 458 WireFormatLite::WriteTag(field->number(), 459 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); 460 const int data_size = FieldDataOnlyByteSize(field, message); 461 output->WriteVarint32(data_size); 462 } 463 464 for (int j = 0; j < count; j++) { 465 switch (field->type()) { 466#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \ 467 case FieldDescriptor::TYPE_##TYPE: { \ 468 const CPPTYPE value = field->is_repeated() ? \ 469 message_reflection->GetRepeated##CPPTYPE_METHOD( \ 470 message, field, j) : \ 471 message_reflection->Get##CPPTYPE_METHOD( \ 472 message, field); \ 473 if (is_packed) { \ 474 WireFormatLite::Write##TYPE_METHOD##NoTag(value, output); \ 475 } else { \ 476 WireFormatLite::Write##TYPE_METHOD(field->number(), value, output); \ 477 } \ 478 break; \ 479 } 480 481 HANDLE_PRIMITIVE_TYPE( INT32, int32, Int32, Int32) 482 HANDLE_PRIMITIVE_TYPE( INT64, int64, Int64, Int64) 483 HANDLE_PRIMITIVE_TYPE(SINT32, int32, SInt32, Int32) 484 HANDLE_PRIMITIVE_TYPE(SINT64, int64, SInt64, Int64) 485 HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32) 486 HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64) 487 488 HANDLE_PRIMITIVE_TYPE( FIXED32, uint32, Fixed32, UInt32) 489 HANDLE_PRIMITIVE_TYPE( FIXED64, uint64, Fixed64, UInt64) 490 HANDLE_PRIMITIVE_TYPE(SFIXED32, int32, SFixed32, Int32) 491 HANDLE_PRIMITIVE_TYPE(SFIXED64, int64, SFixed64, Int64) 492 493 HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float ) 494 HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double) 495 496 HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool) 497#undef HANDLE_PRIMITIVE_TYPE 498 499#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ 500 case FieldDescriptor::TYPE_##TYPE: \ 501 WireFormatLite::Write##TYPE_METHOD( \ 502 field->number(), \ 503 field->is_repeated() ? \ 504 message_reflection->GetRepeated##CPPTYPE_METHOD( \ 505 message, field, j) : \ 506 message_reflection->Get##CPPTYPE_METHOD(message, field), \ 507 output); \ 508 break; 509 510 HANDLE_TYPE(GROUP , Group , Message) 511 HANDLE_TYPE(MESSAGE, Message, Message) 512#undef HANDLE_TYPE 513 514 case FieldDescriptor::TYPE_ENUM: { 515 const EnumValueDescriptor* value = field->is_repeated() ? 516 message_reflection->GetRepeatedEnum(message, field, j) : 517 message_reflection->GetEnum(message, field); 518 if (is_packed) { 519 WireFormatLite::WriteEnumNoTag(value->number(), output); 520 } else { 521 WireFormatLite::WriteEnum(field->number(), value->number(), output); 522 } 523 break; 524 } 525 526 // Handle strings separately so that we can get string references 527 // instead of copying. 528 case FieldDescriptor::TYPE_STRING: { 529 string scratch; 530 const string& value = field->is_repeated() ? 531 message_reflection->GetRepeatedStringReference( 532 message, field, j, &scratch) : 533 message_reflection->GetStringReference(message, field, &scratch); 534 VerifyUTF8String(value.data(), value.length(), SERIALIZE); 535 WireFormatLite::WriteString(field->number(), value, output); 536 break; 537 } 538 539 case FieldDescriptor::TYPE_BYTES: { 540 string scratch; 541 const string& value = field->is_repeated() ? 542 message_reflection->GetRepeatedStringReference( 543 message, field, j, &scratch) : 544 message_reflection->GetStringReference(message, field, &scratch); 545 WireFormatLite::WriteBytes(field->number(), value, output); 546 break; 547 } 548 } 549 } 550} 551 552void WireFormat::SerializeMessageSetItemWithCachedSizes( 553 const FieldDescriptor* field, 554 const Message& message, 555 io::CodedOutputStream* output) { 556 const Reflection* message_reflection = message.GetReflection(); 557 558 // Start group. 559 output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); 560 561 // Write type ID. 562 output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); 563 output->WriteVarint32(field->number()); 564 565 // Write message. 566 output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); 567 568 const Message& sub_message = message_reflection->GetMessage(message, field); 569 output->WriteVarint32(sub_message.GetCachedSize()); 570 sub_message.SerializeWithCachedSizes(output); 571 572 // End group. 573 output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); 574} 575 576// =================================================================== 577 578int WireFormat::ByteSize(const Message& message) { 579 const Descriptor* descriptor = message.GetDescriptor(); 580 const Reflection* message_reflection = message.GetReflection(); 581 582 int our_size = 0; 583 584 vector<const FieldDescriptor*> fields; 585 message_reflection->ListFields(message, &fields); 586 for (int i = 0; i < fields.size(); i++) { 587 our_size += FieldByteSize(fields[i], message); 588 } 589 590 if (descriptor->options().message_set_wire_format()) { 591 our_size += WireFormatLite::ComputeUnknownMessageSetItemsSize( 592 message_reflection->GetUnknownFields(message)); 593 } else { 594 our_size += WireFormatLite::ComputeUnknownFieldsSize( 595 message_reflection->GetUnknownFields(message)); 596 } 597 598 return our_size; 599} 600 601int WireFormat::FieldByteSize( 602 const FieldDescriptor* field, 603 const Message& message) { 604 const Reflection* message_reflection = message.GetReflection(); 605 606 if (field->is_extension() && 607 field->containing_type()->options().message_set_wire_format() && 608 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && 609 !field->is_repeated()) { 610 return MessageSetItemByteSize(field, message); 611 } 612 613 int count = 0; 614 if (field->is_repeated()) { 615 count = message_reflection->FieldSize(message, field); 616 } else if (message_reflection->HasField(message, field)) { 617 count = 1; 618 } 619 620 const int data_size = FieldDataOnlyByteSize(field, message); 621 int our_size = data_size; 622 if (field->options().packed()) { 623 if (data_size > 0) { 624 // Packed fields get serialized like a string, not their native type. 625 // Technically this doesn't really matter; the size only changes if it's 626 // a GROUP 627 our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING); 628 our_size += io::CodedOutputStream::VarintSize32(data_size); 629 } 630 } else { 631 our_size += count * TagSize(field->number(), field->type()); 632 } 633 return our_size; 634} 635 636int WireFormat::FieldDataOnlyByteSize( 637 const FieldDescriptor* field, 638 const Message& message) { 639 const Reflection* message_reflection = message.GetReflection(); 640 641 int count = 0; 642 if (field->is_repeated()) { 643 count = message_reflection->FieldSize(message, field); 644 } else if (message_reflection->HasField(message, field)) { 645 count = 1; 646 } 647 648 int data_size = 0; 649 switch (field->type()) { 650#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ 651 case FieldDescriptor::TYPE_##TYPE: \ 652 if (field->is_repeated()) { \ 653 for (int j = 0; j < count; j++) { \ 654 data_size += WireFormatLite::TYPE_METHOD##Size( \ 655 message_reflection->GetRepeated##CPPTYPE_METHOD( \ 656 message, field, j)); \ 657 } \ 658 } else { \ 659 data_size += WireFormatLite::TYPE_METHOD##Size( \ 660 message_reflection->Get##CPPTYPE_METHOD(message, field)); \ 661 } \ 662 break; 663 664#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \ 665 case FieldDescriptor::TYPE_##TYPE: \ 666 data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \ 667 break; 668 669 HANDLE_TYPE( INT32, Int32, Int32) 670 HANDLE_TYPE( INT64, Int64, Int64) 671 HANDLE_TYPE(SINT32, SInt32, Int32) 672 HANDLE_TYPE(SINT64, SInt64, Int64) 673 HANDLE_TYPE(UINT32, UInt32, UInt32) 674 HANDLE_TYPE(UINT64, UInt64, UInt64) 675 676 HANDLE_FIXED_TYPE( FIXED32, Fixed32) 677 HANDLE_FIXED_TYPE( FIXED64, Fixed64) 678 HANDLE_FIXED_TYPE(SFIXED32, SFixed32) 679 HANDLE_FIXED_TYPE(SFIXED64, SFixed64) 680 681 HANDLE_FIXED_TYPE(FLOAT , Float ) 682 HANDLE_FIXED_TYPE(DOUBLE, Double) 683 684 HANDLE_FIXED_TYPE(BOOL, Bool) 685 686 HANDLE_TYPE(GROUP , Group , Message) 687 HANDLE_TYPE(MESSAGE, Message, Message) 688#undef HANDLE_TYPE 689#undef HANDLE_FIXED_TYPE 690 691 case FieldDescriptor::TYPE_ENUM: { 692 if (field->is_repeated()) { 693 for (int j = 0; j < count; j++) { 694 data_size += WireFormatLite::EnumSize( 695 message_reflection->GetRepeatedEnum(message, field, j)->number()); 696 } 697 } else { 698 data_size += WireFormatLite::EnumSize( 699 message_reflection->GetEnum(message, field)->number()); 700 } 701 break; 702 } 703 704 // Handle strings separately so that we can get string references 705 // instead of copying. 706 case FieldDescriptor::TYPE_STRING: 707 case FieldDescriptor::TYPE_BYTES: { 708 for (int j = 0; j < count; j++) { 709 string scratch; 710 const string& value = field->is_repeated() ? 711 message_reflection->GetRepeatedStringReference( 712 message, field, j, &scratch) : 713 message_reflection->GetStringReference(message, field, &scratch); 714 data_size += WireFormatLite::StringSize(value); 715 } 716 break; 717 } 718 } 719 return data_size; 720} 721 722int WireFormat::MessageSetItemByteSize( 723 const FieldDescriptor* field, 724 const Message& message) { 725 const Reflection* message_reflection = message.GetReflection(); 726 727 int our_size = WireFormatLite::kMessageSetItemTagsSize; 728 729 // type_id 730 our_size += io::CodedOutputStream::VarintSize32(field->number()); 731 732 // message 733 const Message& sub_message = message_reflection->GetMessage(message, field); 734 int message_size = sub_message.ByteSize(); 735 736 our_size += io::CodedOutputStream::VarintSize32(message_size); 737 our_size += message_size; 738 739 return our_size; 740} 741 742void WireFormat::VerifyUTF8StringFallback(const char* data, 743 int size, 744 Operation op) { 745 if (!IsStructurallyValidUTF8(data, size)) { 746 const char* operation_str = NULL; 747 switch (op) { 748 case PARSE: 749 operation_str = "parsing"; 750 break; 751 case SERIALIZE: 752 operation_str = "serializing"; 753 break; 754 // no default case: have the compiler warn if a case is not covered. 755 } 756 GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when " 757 << operation_str 758 << " a protocol buffer. Use the 'bytes' type if you intend to " 759 "send raw bytes."; 760 } 761} 762 763 764} // namespace internal 765} // namespace protobuf 766} // namespace google 767