| Index: third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc
|
| index f585c31b4bf8ebfb9a2bb5d96968bf63f9c6d470..5c4b56f7eda2433385d66b9759a32d37400577b2 100644
|
| --- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc
|
| @@ -45,10 +45,10 @@ bool IsProto3Field(const FieldDescriptor* field_descriptor) {
|
| }
|
|
|
| void SetMessageVariables(const FieldDescriptor* descriptor,
|
| - map<string, string>* variables,
|
| + std::map<string, string>* variables,
|
| const Options& options) {
|
| SetCommonFieldVariables(descriptor, variables, options);
|
| - (*variables)["type"] = FieldMessageTypeName(descriptor);
|
| + (*variables)["type"] = ClassName(descriptor->message_type(), false);
|
| (*variables)["stream_writer"] =
|
| (*variables)["declared_type"] +
|
| (HasFastArraySerialization(descriptor->message_type()->file(), options)
|
| @@ -137,7 +137,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
| void MapFieldGenerator::
|
| GenerateInlineAccessorDefinitions(io::Printer* printer,
|
| bool is_inline) const {
|
| - map<string, string> variables(variables_);
|
| + std::map<string, string> variables(variables_);
|
| variables["inline"] = is_inline ? "inline" : "";
|
| printer->Print(variables,
|
| "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
| @@ -154,7 +154,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
|
|
|
| void MapFieldGenerator::
|
| GenerateClearingCode(io::Printer* printer) const {
|
| - map<string, string> variables(variables_);
|
| + std::map<string, string> variables(variables_);
|
| variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
|
| printer->Print(variables, "$this_message$$name$_.Clear();\n");
|
| }
|
| @@ -173,42 +173,48 @@ void MapFieldGenerator::
|
| GenerateConstructorCode(io::Printer* printer) const {
|
| if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
| printer->Print(variables_,
|
| - "$name$_.SetAssignDescriptorCallback(\n"
|
| - " protobuf_AssignDescriptorsOnce);\n"
|
| - "$name$_.SetEntryDescriptor(\n"
|
| - " &$type$_descriptor_);\n");
|
| + "$name$_.SetAssignDescriptorCallback(\n"
|
| + " protobuf_AssignDescriptorsOnce);\n"
|
| + "$name$_.SetEntryDescriptor(\n"
|
| + " &$type$_descriptor);\n");
|
| }
|
| }
|
|
|
| void MapFieldGenerator::
|
| +GenerateCopyConstructorCode(io::Printer* printer) const {
|
| + GenerateConstructorCode(printer);
|
| + GenerateMergingCode(printer);
|
| +}
|
| +
|
| +void MapFieldGenerator::
|
| GenerateMergeFromCodedStream(io::Printer* printer) const {
|
| + const FieldDescriptor* key_field =
|
| + descriptor_->message_type()->FindFieldByName("key");
|
| const FieldDescriptor* value_field =
|
| descriptor_->message_type()->FindFieldByName("value");
|
| - printer->Print(variables_,
|
| - "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
|
| -
|
| + bool using_entry = false;
|
| + string key;
|
| + string value;
|
| if (IsProto3Field(descriptor_) ||
|
| value_field->type() != FieldDescriptor::TYPE_ENUM) {
|
| printer->Print(variables_,
|
| + "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n"
|
| + " $key_cpp$, $val_cpp$,\n"
|
| + " $key_wire_type$,\n"
|
| + " $val_wire_type$,\n"
|
| + " $default_enum_value$ >,\n"
|
| + " ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >"
|
| + " parser(&$name$_);\n"
|
| "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
| - " input, entry.get()));\n");
|
| - switch (value_field->cpp_type()) {
|
| - case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - printer->Print(variables_,
|
| - "(*mutable_$name$())[entry->key()].Swap("
|
| - "entry->mutable_value());\n");
|
| - break;
|
| - case FieldDescriptor::CPPTYPE_ENUM:
|
| - printer->Print(variables_,
|
| - "(*mutable_$name$())[entry->key()] =\n"
|
| - " static_cast< $val_cpp$ >(*entry->mutable_value());\n");
|
| - break;
|
| - default:
|
| - printer->Print(variables_,
|
| - "(*mutable_$name$())[entry->key()] = *entry->mutable_value();\n");
|
| - break;
|
| - }
|
| + " input, &parser));\n");
|
| + key = "parser.key()";
|
| + value = "parser.value()";
|
| } else {
|
| + using_entry = true;
|
| + key = "entry->key()";
|
| + value = "entry->value()";
|
| + printer->Print(variables_,
|
| + "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
|
| printer->Print(variables_,
|
| "{\n"
|
| " ::std::string data;\n"
|
| @@ -224,156 +230,183 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
| "->AddLengthDelimited($number$, data);\n");
|
| } else {
|
| printer->Print(variables_,
|
| - " unknown_fields_stream.WriteVarint32($tag$);\n"
|
| + " unknown_fields_stream.WriteVarint32($tag$u);\n"
|
| " unknown_fields_stream.WriteVarint32(data.size());\n"
|
| " unknown_fields_stream.WriteString(data);\n");
|
| }
|
|
|
| -
|
| printer->Print(variables_,
|
| " }\n"
|
| "}\n");
|
| }
|
|
|
| - const FieldDescriptor* key_field =
|
| - descriptor_->message_type()->FindFieldByName("key");
|
| if (key_field->type() == FieldDescriptor::TYPE_STRING) {
|
| GenerateUtf8CheckCodeForString(
|
| - key_field, options_, true, variables_,
|
| - "entry->key().data(), entry->key().length(),\n", printer);
|
| + key_field, options_, true, variables_,
|
| + StrCat(key, ".data(), ", key, ".length(),\n").data(), printer);
|
| }
|
| if (value_field->type() == FieldDescriptor::TYPE_STRING) {
|
| GenerateUtf8CheckCodeForString(value_field, options_, true, variables_,
|
| - "entry->mutable_value()->data(),\n"
|
| - "entry->mutable_value()->length(),\n",
|
| - printer);
|
| + StrCat(value, ".data(), ", value, ".length(),\n").data(), printer);
|
| }
|
|
|
| // If entry is allocated by arena, its desctructor should be avoided.
|
| - if (SupportsArenas(descriptor_)) {
|
| + if (using_entry && SupportsArenas(descriptor_)) {
|
| printer->Print(variables_,
|
| "if (entry->GetArena() != NULL) entry.release();\n");
|
| }
|
| }
|
|
|
| -void MapFieldGenerator::
|
| -GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
| - printer->Print(variables_,
|
| - "{\n"
|
| - " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
| - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
| - " it = this->$name$().begin();\n"
|
| - " it != this->$name$().end(); ++it) {\n");
|
| +static void GenerateSerializationLoop(io::Printer* printer,
|
| + const std::map<string, string>& variables,
|
| + bool supports_arenas,
|
| + const string& utf8_check,
|
| + const string& loop_header,
|
| + const string& ptr,
|
| + bool loop_via_iterators) {
|
| + printer->Print(variables,
|
| + StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n",
|
| + loop_header, " {\n").c_str());
|
| + printer->Indent();
|
| +
|
| + printer->Print(variables, StrCat(
|
| + "entry.reset($name$_.New$wrapper$(\n"
|
| + " ", ptr, "->first, ", ptr, "->second));\n"
|
| + "$write_entry$;\n").c_str());
|
|
|
| // If entry is allocated by arena, its desctructor should be avoided.
|
| - if (SupportsArenas(descriptor_)) {
|
| - printer->Print(variables_,
|
| - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
| - " entry.release();\n"
|
| - " }\n");
|
| + if (supports_arenas) {
|
| + printer->Print(
|
| + "if (entry->GetArena() != NULL) {\n"
|
| + " entry.release();\n"
|
| + "}\n");
|
| }
|
|
|
| - printer->Print(variables_,
|
| - " entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
| - " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
| - " $number$, *entry, output);\n");
|
| -
|
| - printer->Indent();
|
| - printer->Indent();
|
| -
|
| - const FieldDescriptor* key_field =
|
| - descriptor_->message_type()->FindFieldByName("key");
|
| - const FieldDescriptor* value_field =
|
| - descriptor_->message_type()->FindFieldByName("value");
|
| - if (key_field->type() == FieldDescriptor::TYPE_STRING) {
|
| - GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
|
| - "it->first.data(), it->first.length(),\n",
|
| - printer);
|
| - }
|
| - if (value_field->type() == FieldDescriptor::TYPE_STRING) {
|
| - GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
|
| - "it->second.data(), it->second.length(),\n",
|
| - printer);
|
| + if (!utf8_check.empty()) {
|
| + // If loop_via_iterators is true then ptr is actually an iterator, and we
|
| + // create a pointer by prefixing it with "&*".
|
| + printer->Print(
|
| + StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
|
| + .c_str());
|
| }
|
|
|
| printer->Outdent();
|
| - printer->Outdent();
|
| -
|
| printer->Print(
|
| - " }\n");
|
| -
|
| - // If entry is allocated by arena, its desctructor should be avoided.
|
| - if (SupportsArenas(descriptor_)) {
|
| - printer->Print(variables_,
|
| - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
| - " entry.release();\n"
|
| - " }\n");
|
| - }
|
| + "}\n");
|
| +}
|
|
|
| - printer->Print("}\n");
|
| +void MapFieldGenerator::
|
| +GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
| + std::map<string, string> variables(variables_);
|
| + variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
|
| + variables["stream_writer"] + "(\n " +
|
| + variables["number"] + ", *entry, output)";
|
| + variables["deterministic"] = "output->IsSerializationDeterministic()";
|
| + GenerateSerializeWithCachedSizes(printer, variables);
|
| }
|
|
|
| void MapFieldGenerator::
|
| GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
| - printer->Print(variables_,
|
| - "{\n"
|
| - " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
| - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
| - " it = this->$name$().begin();\n"
|
| - " it != this->$name$().end(); ++it) {\n");
|
| -
|
| - // If entry is allocated by arena, its desctructor should be avoided.
|
| - if (SupportsArenas(descriptor_)) {
|
| - printer->Print(variables_,
|
| - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
| - " entry.release();\n"
|
| - " }\n");
|
| - }
|
| -
|
| - printer->Print(variables_,
|
| - " entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
| - " target = ::google::protobuf::internal::WireFormatLite::\n"
|
| - " Write$declared_type$NoVirtualToArray(\n"
|
| - " $number$, *entry, target);\n");
|
| + std::map<string, string> variables(variables_);
|
| + variables["write_entry"] =
|
| + "target = ::google::protobuf::internal::WireFormatLite::\n"
|
| + " InternalWrite" + variables["declared_type"] +
|
| + "NoVirtualToArray(\n " + variables["number"] +
|
| + ", *entry, deterministic, target);\n";
|
| + variables["deterministic"] = "deterministic";
|
| + GenerateSerializeWithCachedSizes(printer, variables);
|
| +}
|
|
|
| +void MapFieldGenerator::GenerateSerializeWithCachedSizes(
|
| + io::Printer* printer, const std::map<string, string>& variables) const {
|
| + printer->Print(variables,
|
| + "if (!this->$name$().empty()) {\n");
|
| printer->Indent();
|
| - printer->Indent();
|
| -
|
| const FieldDescriptor* key_field =
|
| descriptor_->message_type()->FindFieldByName("key");
|
| const FieldDescriptor* value_field =
|
| descriptor_->message_type()->FindFieldByName("value");
|
| - if (key_field->type() == FieldDescriptor::TYPE_STRING) {
|
| - GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
|
| - "it->first.data(), it->first.length(),\n",
|
| - printer);
|
| + const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
|
| + const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
|
| +
|
| + printer->Print(variables,
|
| + "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
|
| + " ConstPtr;\n");
|
| + if (string_key) {
|
| + printer->Print(variables,
|
| + "typedef ConstPtr SortItem;\n"
|
| + "typedef ::google::protobuf::internal::"
|
| + "CompareByDerefFirst<SortItem> Less;\n");
|
| + } else {
|
| + printer->Print(variables,
|
| + "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
|
| + "SortItem;\n"
|
| + "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
|
| }
|
| - if (value_field->type() == FieldDescriptor::TYPE_STRING) {
|
| - GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
|
| - "it->second.data(), it->second.length(),\n",
|
| - printer);
|
| + string utf8_check;
|
| + if (string_key || string_value) {
|
| + printer->Print(
|
| + "struct Utf8Check {\n"
|
| + " static void Check(ConstPtr p) {\n");
|
| + printer->Indent();
|
| + printer->Indent();
|
| + if (string_key) {
|
| + GenerateUtf8CheckCodeForString(key_field, options_, false, variables,
|
| + "p->first.data(), p->first.length(),\n",
|
| + printer);
|
| + }
|
| + if (string_value) {
|
| + GenerateUtf8CheckCodeForString(value_field, options_, false, variables,
|
| + "p->second.data(), p->second.length(),\n",
|
| + printer);
|
| + }
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Print(
|
| + " }\n"
|
| + "};\n");
|
| + utf8_check = "Utf8Check::Check";
|
| }
|
|
|
| - printer->Outdent();
|
| + printer->Print(variables,
|
| + "\n"
|
| + "if ($deterministic$ &&\n"
|
| + " this->$name$().size() > 1) {\n"
|
| + " ::google::protobuf::scoped_array<SortItem> items(\n"
|
| + " new SortItem[this->$name$().size()]);\n"
|
| + " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
|
| + " size_type n = 0;\n"
|
| + " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
| + " it = this->$name$().begin();\n"
|
| + " it != this->$name$().end(); ++it, ++n) {\n"
|
| + " items[n] = SortItem(&*it);\n"
|
| + " }\n"
|
| + " ::std::sort(&items[0], &items[n], Less());\n");
|
| + printer->Indent();
|
| + GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
|
| + utf8_check, "for (size_type i = 0; i < n; i++)",
|
| + string_key ? "items[i]" : "items[i].second", false);
|
| printer->Outdent();
|
| printer->Print(
|
| - " }\n");
|
| -
|
| - // If entry is allocated by arena, its desctructor should be avoided.
|
| - if (SupportsArenas(descriptor_)) {
|
| - printer->Print(variables_,
|
| - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
|
| - " entry.release();\n"
|
| - " }\n");
|
| - }
|
| -
|
| + "} else {\n");
|
| + printer->Indent();
|
| + GenerateSerializationLoop(
|
| + printer, variables, SupportsArenas(descriptor_), utf8_check,
|
| + "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
| + " it = this->$name$().begin();\n"
|
| + " it != this->$name$().end(); ++it)",
|
| + "it", true);
|
| + printer->Outdent();
|
| + printer->Print("}\n");
|
| + printer->Outdent();
|
| printer->Print("}\n");
|
| }
|
|
|
| void MapFieldGenerator::
|
| GenerateByteSize(io::Printer* printer) const {
|
| printer->Print(variables_,
|
| - "total_size += $tag_size$ * this->$name$_size();\n"
|
| + "total_size += $tag_size$ *\n"
|
| + " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
| "{\n"
|
| " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
| " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
|
|