| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 using util::StatusOr; | 57 using util::StatusOr; |
| 58 | 58 |
| 59 | 59 |
| 60 ProtoWriter::ProtoWriter(TypeResolver* type_resolver, | 60 ProtoWriter::ProtoWriter(TypeResolver* type_resolver, |
| 61 const google::protobuf::Type& type, | 61 const google::protobuf::Type& type, |
| 62 strings::ByteSink* output, ErrorListener* listener) | 62 strings::ByteSink* output, ErrorListener* listener) |
| 63 : master_type_(type), | 63 : master_type_(type), |
| 64 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), | 64 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
| 65 own_typeinfo_(true), | 65 own_typeinfo_(true), |
| 66 done_(false), | 66 done_(false), |
| 67 ignore_unknown_fields_(false), | |
| 68 use_lower_camel_for_enums_(false), | |
| 69 element_(NULL), | 67 element_(NULL), |
| 70 size_insert_(), | 68 size_insert_(), |
| 71 output_(output), | 69 output_(output), |
| 72 buffer_(), | 70 buffer_(), |
| 73 adapter_(&buffer_), | 71 adapter_(&buffer_), |
| 74 stream_(new CodedOutputStream(&adapter_)), | 72 stream_(new CodedOutputStream(&adapter_)), |
| 75 listener_(listener), | 73 listener_(listener), |
| 76 invalid_depth_(0), | 74 invalid_depth_(0), |
| 77 tracker_(new ObjectLocationTracker()) {} | 75 tracker_(new ObjectLocationTracker()) {} |
| 78 | 76 |
| 79 ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, | 77 ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, |
| 80 const google::protobuf::Type& type, | 78 const google::protobuf::Type& type, |
| 81 strings::ByteSink* output, ErrorListener* listener) | 79 strings::ByteSink* output, ErrorListener* listener) |
| 82 : master_type_(type), | 80 : master_type_(type), |
| 83 typeinfo_(typeinfo), | 81 typeinfo_(typeinfo), |
| 84 own_typeinfo_(false), | 82 own_typeinfo_(false), |
| 85 done_(false), | 83 done_(false), |
| 86 ignore_unknown_fields_(false), | |
| 87 use_lower_camel_for_enums_(false), | |
| 88 element_(NULL), | 84 element_(NULL), |
| 89 size_insert_(), | 85 size_insert_(), |
| 90 output_(output), | 86 output_(output), |
| 91 buffer_(), | 87 buffer_(), |
| 92 adapter_(&buffer_), | 88 adapter_(&buffer_), |
| 93 stream_(new CodedOutputStream(&adapter_)), | 89 stream_(new CodedOutputStream(&adapter_)), |
| 94 listener_(listener), | 90 listener_(listener), |
| 95 invalid_depth_(0), | 91 invalid_depth_(0), |
| 96 tracker_(new ObjectLocationTracker()) {} | 92 tracker_(new ObjectLocationTracker()) {} |
| 97 | 93 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 StatusOr<string> s = data.ToString(); | 255 StatusOr<string> s = data.ToString(); |
| 260 if (s.ok()) { | 256 if (s.ok()) { |
| 261 WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); | 257 WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); |
| 262 } | 258 } |
| 263 return s.status(); | 259 return s.status(); |
| 264 } | 260 } |
| 265 | 261 |
| 266 // Writes an ENUM field, including tag, to the stream. | 262 // Writes an ENUM field, including tag, to the stream. |
| 267 inline Status WriteEnum(int field_number, const DataPiece& data, | 263 inline Status WriteEnum(int field_number, const DataPiece& data, |
| 268 const google::protobuf::Enum* enum_type, | 264 const google::protobuf::Enum* enum_type, |
| 269 CodedOutputStream* stream, | 265 CodedOutputStream* stream) { |
| 270 bool use_lower_camel_for_enums) { | 266 StatusOr<int> e = data.ToEnum(enum_type); |
| 271 StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums); | |
| 272 if (e.ok()) { | 267 if (e.ok()) { |
| 273 WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); | 268 WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); |
| 274 } | 269 } |
| 275 return e.status(); | 270 return e.status(); |
| 276 } | 271 } |
| 277 | 272 |
| 278 // Given a google::protobuf::Type, returns the set of all required fields. | 273 // Given a google::protobuf::Type, returns the set of all required fields. |
| 279 std::set<const google::protobuf::Field*> GetRequiredFields( | 274 std::set<const google::protobuf::Field*> GetRequiredFields( |
| 280 const google::protobuf::Type& type) { | 275 const google::protobuf::Type& type) { |
| 281 std::set<const google::protobuf::Field*> required; | 276 std::set<const google::protobuf::Field*> required; |
| 282 for (int i = 0; i < type.fields_size(); i++) { | 277 for (int i = 0; i < type.fields_size(); i++) { |
| 283 const google::protobuf::Field& field = type.fields(i); | 278 const google::protobuf::Field& field = type.fields(i); |
| 284 if (field.cardinality() == | 279 if (field.cardinality() == |
| 285 google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { | 280 google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { |
| 286 required.insert(&field); | 281 required.insert(&field); |
| 287 } | 282 } |
| 288 } | 283 } |
| 289 return required; | 284 return required; |
| 290 } | 285 } |
| 291 | 286 |
| 292 } // namespace | 287 } // namespace |
| 293 | 288 |
| 294 ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, | 289 ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, |
| 295 const google::protobuf::Type& type, | 290 const google::protobuf::Type& type, |
| 296 ProtoWriter* enclosing) | 291 ProtoWriter* enclosing) |
| 297 : BaseElement(NULL), | 292 : BaseElement(NULL), |
| 298 ow_(enclosing), | 293 ow_(enclosing), |
| 299 parent_field_(NULL), | 294 parent_field_(NULL), |
| 300 typeinfo_(typeinfo), | 295 typeinfo_(typeinfo), |
| 301 proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), | |
| 302 type_(type), | 296 type_(type), |
| 297 required_fields_(GetRequiredFields(type)), |
| 303 size_index_(-1), | 298 size_index_(-1), |
| 304 array_index_(-1), | 299 array_index_(-1) {} |
| 305 // oneof_indices_ values are 1-indexed (0 means not present). | |
| 306 oneof_indices_(type.oneofs_size() + 1) { | |
| 307 if (!proto3_) { | |
| 308 required_fields_ = GetRequiredFields(type_); | |
| 309 } | |
| 310 } | |
| 311 | 300 |
| 312 ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, | 301 ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, |
| 313 const google::protobuf::Field* field, | 302 const google::protobuf::Field* field, |
| 314 const google::protobuf::Type& type, | 303 const google::protobuf::Type& type, |
| 315 bool is_list) | 304 bool is_list) |
| 316 : BaseElement(parent), | 305 : BaseElement(parent), |
| 317 ow_(this->parent()->ow_), | 306 ow_(this->parent()->ow_), |
| 318 parent_field_(field), | 307 parent_field_(field), |
| 319 typeinfo_(this->parent()->typeinfo_), | 308 typeinfo_(this->parent()->typeinfo_), |
| 320 proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), | |
| 321 type_(type), | 309 type_(type), |
| 322 size_index_( | 310 size_index_( |
| 323 !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE | 311 !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE |
| 324 ? ow_->size_insert_.size() | 312 ? ow_->size_insert_.size() |
| 325 : -1), | 313 : -1), |
| 326 array_index_(is_list ? 0 : -1), | 314 array_index_(is_list ? 0 : -1) { |
| 327 // oneof_indices_ values are 1-indexed (0 means not present). | |
| 328 oneof_indices_(type_.oneofs_size() + 1) { | |
| 329 if (!is_list) { | 315 if (!is_list) { |
| 330 if (ow_->IsRepeated(*field)) { | 316 if (ow_->IsRepeated(*field)) { |
| 331 // Update array_index_ if it is an explicit list. | 317 // Update array_index_ if it is an explicit list. |
| 332 if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; | 318 if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; |
| 333 } else if (!proto3_) { | 319 } else { |
| 334 // For required fields tracking. | |
| 335 this->parent()->RegisterField(field); | 320 this->parent()->RegisterField(field); |
| 336 } | 321 } |
| 337 | 322 |
| 338 if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { | 323 if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
| 339 if (!proto3_) { | 324 required_fields_ = GetRequiredFields(type_); |
| 340 required_fields_ = GetRequiredFields(type_); | |
| 341 } | |
| 342 int start_pos = ow_->stream_->ByteCount(); | 325 int start_pos = ow_->stream_->ByteCount(); |
| 343 // length of serialized message is the final buffer position minus | 326 // length of serialized message is the final buffer position minus |
| 344 // starting buffer position, plus length adjustments for size fields | 327 // starting buffer position, plus length adjustments for size fields |
| 345 // of any nested messages. We start with -start_pos here, so we only | 328 // of any nested messages. We start with -start_pos here, so we only |
| 346 // need to add the final buffer position to it at the end. | 329 // need to add the final buffer position to it at the end. |
| 347 SizeInfo info = {start_pos, -start_pos}; | 330 SizeInfo info = {start_pos, -start_pos}; |
| 348 ow_->size_insert_.push_back(info); | 331 ow_->size_insert_.push_back(info); |
| 349 } | 332 } |
| 350 } | 333 } |
| 351 } | 334 } |
| 352 | 335 |
| 353 ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { | 336 ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { |
| 354 if (!proto3_) { | 337 // Calls the registered error listener for any required field(s) not yet |
| 355 // Calls the registered error listener for any required field(s) not yet | 338 // seen. |
| 356 // seen. | 339 for (set<const google::protobuf::Field*>::iterator it = |
| 357 for (std::set<const google::protobuf::Field*>::iterator it = | 340 required_fields_.begin(); |
| 358 required_fields_.begin(); | 341 it != required_fields_.end(); ++it) { |
| 359 it != required_fields_.end(); ++it) { | 342 ow_->MissingField((*it)->name()); |
| 360 ow_->MissingField((*it)->name()); | |
| 361 } | |
| 362 } | 343 } |
| 363 // Computes the total number of proto bytes used by a message, also adjusts | 344 // Computes the total number of proto bytes used by a message, also adjusts |
| 364 // the size of all parent messages by the length of this size field. | 345 // the size of all parent messages by the length of this size field. |
| 365 // If size_index_ < 0, this is not a message, so no size field is added. | 346 // If size_index_ < 0, this is not a message, so no size field is added. |
| 366 if (size_index_ >= 0) { | 347 if (size_index_ >= 0) { |
| 367 // Add the final buffer position to compute the total length of this | 348 // Add the final buffer position to compute the total length of this |
| 368 // serialized message. The stored value (before this addition) already | 349 // serialized message. The stored value (before this addition) already |
| 369 // contains the total length of the size fields of all nested messages | 350 // contains the total length of the size fields of all nested messages |
| 370 // minus the initial buffer position. | 351 // minus the initial buffer position. |
| 371 ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); | 352 ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 StrAppend(&loc, "[\"", CEscape(name), "\"]"); | 392 StrAppend(&loc, "[\"", CEscape(name), "\"]"); |
| 412 } | 393 } |
| 413 } | 394 } |
| 414 if (ow_->IsRepeated(*parent_field_) && array_index_ > 0) { | 395 if (ow_->IsRepeated(*parent_field_) && array_index_ > 0) { |
| 415 StrAppend(&loc, "[", array_index_ - 1, "]"); | 396 StrAppend(&loc, "[", array_index_ - 1, "]"); |
| 416 } | 397 } |
| 417 return loc.empty() ? "." : loc; | 398 return loc.empty() ? "." : loc; |
| 418 } | 399 } |
| 419 | 400 |
| 420 bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { | 401 bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { |
| 421 return oneof_indices_[index]; | 402 return ContainsKey(oneof_indices_, index); |
| 422 } | 403 } |
| 423 | 404 |
| 424 void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { | 405 void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { |
| 425 oneof_indices_[index] = true; | 406 InsertIfNotPresent(&oneof_indices_, index); |
| 426 } | 407 } |
| 427 | 408 |
| 428 void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { | 409 void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { |
| 429 listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); | 410 listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); |
| 430 } | 411 } |
| 431 | 412 |
| 432 void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) { | 413 void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) { |
| 433 listener_->InvalidValue(location(), type_name, value); | 414 listener_->InvalidValue(location(), type_name, value); |
| 434 } | 415 } |
| 435 | 416 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 return this; | 554 return this; |
| 574 } | 555 } |
| 575 | 556 |
| 576 ProtoWriter* ProtoWriter::RenderPrimitiveField( | 557 ProtoWriter* ProtoWriter::RenderPrimitiveField( |
| 577 const google::protobuf::Field& field, const google::protobuf::Type& type, | 558 const google::protobuf::Field& field, const google::protobuf::Type& type, |
| 578 const DataPiece& data) { | 559 const DataPiece& data) { |
| 579 Status status; | 560 Status status; |
| 580 | 561 |
| 581 // Pushing a ProtoElement and then pop it off at the end for 2 purposes: | 562 // Pushing a ProtoElement and then pop it off at the end for 2 purposes: |
| 582 // error location reporting and required field accounting. | 563 // error location reporting and required field accounting. |
| 583 // | 564 element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
| 584 // For proto3, since there is no required field tracking, we only need to push | |
| 585 // ProtoElement for error cases. | |
| 586 if (!element_->proto3()) { | |
| 587 element_.reset(new ProtoElement(element_.release(), &field, type, false)); | |
| 588 } | |
| 589 | 565 |
| 590 if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || | 566 if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || |
| 591 field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { | 567 field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
| 592 // Push a ProtoElement for location reporting purposes. | |
| 593 if (element_->proto3()) { | |
| 594 element_.reset(new ProtoElement(element_.release(), &field, type, false)); | |
| 595 } | |
| 596 InvalidValue(field.type_url().empty() | 568 InvalidValue(field.type_url().empty() |
| 597 ? google::protobuf::Field_Kind_Name(field.kind()) | 569 ? google::protobuf::Field_Kind_Name(field.kind()) |
| 598 : field.type_url(), | 570 : field.type_url(), |
| 599 data.ValueAsStringOrDefault("")); | 571 data.ValueAsStringOrDefault("")); |
| 600 element_.reset(element()->pop()); | 572 element_.reset(element()->pop()); |
| 601 return this; | 573 return this; |
| 602 } | 574 } |
| 603 | 575 |
| 604 switch (field.kind()) { | 576 switch (field.kind()) { |
| 605 case google::protobuf::Field_Kind_TYPE_INT32: { | 577 case google::protobuf::Field_Kind_TYPE_INT32: { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 status = WriteBytes(field.number(), data, stream_.get()); | 630 status = WriteBytes(field.number(), data, stream_.get()); |
| 659 break; | 631 break; |
| 660 } | 632 } |
| 661 case google::protobuf::Field_Kind_TYPE_STRING: { | 633 case google::protobuf::Field_Kind_TYPE_STRING: { |
| 662 status = WriteString(field.number(), data, stream_.get()); | 634 status = WriteString(field.number(), data, stream_.get()); |
| 663 break; | 635 break; |
| 664 } | 636 } |
| 665 case google::protobuf::Field_Kind_TYPE_ENUM: { | 637 case google::protobuf::Field_Kind_TYPE_ENUM: { |
| 666 status = WriteEnum(field.number(), data, | 638 status = WriteEnum(field.number(), data, |
| 667 typeinfo_->GetEnumByTypeUrl(field.type_url()), | 639 typeinfo_->GetEnumByTypeUrl(field.type_url()), |
| 668 stream_.get(), use_lower_camel_for_enums_); | 640 stream_.get()); |
| 669 break; | 641 break; |
| 670 } | 642 } |
| 671 default: // TYPE_GROUP or TYPE_MESSAGE | 643 default: // TYPE_GROUP or TYPE_MESSAGE |
| 672 status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); | 644 status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); |
| 673 } | 645 } |
| 674 | 646 |
| 675 if (!status.ok()) { | 647 if (!status.ok()) { |
| 676 // Push a ProtoElement for location reporting purposes. | |
| 677 if (element_->proto3()) { | |
| 678 element_.reset(new ProtoElement(element_.release(), &field, type, false)); | |
| 679 } | |
| 680 InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), | 648 InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), |
| 681 status.error_message()); | 649 status.error_message()); |
| 682 element_.reset(element()->pop()); | |
| 683 return this; | |
| 684 } | 650 } |
| 685 | 651 |
| 686 if (!element_->proto3()) element_.reset(element()->pop()); | 652 element_.reset(element()->pop()); |
| 687 | |
| 688 return this; | 653 return this; |
| 689 } | 654 } |
| 690 | 655 |
| 691 const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, | 656 const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, |
| 692 bool is_list) { | 657 bool is_list) { |
| 693 if (invalid_depth_ > 0) { | 658 if (invalid_depth_ > 0) { |
| 694 ++invalid_depth_; | 659 ++invalid_depth_; |
| 695 return NULL; | 660 return NULL; |
| 696 } | 661 } |
| 697 const google::protobuf::Field* field = Lookup(name); | 662 const google::protobuf::Field* field = Lookup(name); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 720 if (e->parent_field() == NULL) { | 685 if (e->parent_field() == NULL) { |
| 721 InvalidName(unnormalized_name, "Proto fields must have a name."); | 686 InvalidName(unnormalized_name, "Proto fields must have a name."); |
| 722 } else if (!IsRepeated(*e->parent_field())) { | 687 } else if (!IsRepeated(*e->parent_field())) { |
| 723 InvalidName(unnormalized_name, "Proto fields must have a name."); | 688 InvalidName(unnormalized_name, "Proto fields must have a name."); |
| 724 return NULL; | 689 return NULL; |
| 725 } | 690 } |
| 726 return e->parent_field(); | 691 return e->parent_field(); |
| 727 } | 692 } |
| 728 const google::protobuf::Field* field = | 693 const google::protobuf::Field* field = |
| 729 typeinfo_->FindField(&e->type(), unnormalized_name); | 694 typeinfo_->FindField(&e->type(), unnormalized_name); |
| 730 if (field == NULL && !ignore_unknown_fields_) { | 695 if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); |
| 731 InvalidName(unnormalized_name, "Cannot find field."); | |
| 732 } | |
| 733 return field; | 696 return field; |
| 734 } | 697 } |
| 735 | 698 |
| 736 const google::protobuf::Type* ProtoWriter::LookupType( | 699 const google::protobuf::Type* ProtoWriter::LookupType( |
| 737 const google::protobuf::Field* field) { | 700 const google::protobuf::Field* field) { |
| 738 return ((field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE || | 701 return ((field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE || |
| 739 field->kind() == google::protobuf::Field_Kind_TYPE_GROUP) | 702 field->kind() == google::protobuf::Field_Kind_TYPE_GROUP) |
| 740 ? typeinfo_->GetTypeByTypeUrl(field->type_url()) | 703 ? typeinfo_->GetTypeByTypeUrl(field->type_url()) |
| 741 : &element_->type()); | 704 : &element_->type()); |
| 742 } | 705 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( | 753 WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( |
| 791 static_cast<WireFormatLite::FieldType>(field.kind())); | 754 static_cast<WireFormatLite::FieldType>(field.kind())); |
| 792 stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); | 755 stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); |
| 793 } | 756 } |
| 794 | 757 |
| 795 | 758 |
| 796 } // namespace converter | 759 } // namespace converter |
| 797 } // namespace util | 760 } // namespace util |
| 798 } // namespace protobuf | 761 } // namespace protobuf |
| 799 } // namespace google | 762 } // namespace google |
| OLD | NEW |