diff options
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_map_field.cc')
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_map_field.cc | 345 |
1 files changed, 166 insertions, 179 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 0e485cac..3114bbf7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -32,9 +32,9 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> - #include <google/protobuf/stubs/strutil.h> + namespace google { namespace protobuf { namespace compiler { @@ -50,8 +50,6 @@ void SetMessageVariables(const FieldDescriptor* descriptor, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = ClassName(descriptor->message_type(), false); - (*variables)["file_namespace"] = - FileLevelNamespace(descriptor->file()->name()); (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file(), options) @@ -63,7 +61,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, descriptor->message_type()->FindFieldByName("key"); const FieldDescriptor* val = descriptor->message_type()->FindFieldByName("value"); - (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type()); + (*variables)["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: (*variables)["val_cpp"] = FieldMessageTypeName(val); @@ -74,18 +72,17 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["wrapper"] = "EnumEntryWrapper"; break; default: - (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type()); + (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); (*variables)["wrapper"] = "EntryWrapper"; } (*variables)["key_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(key->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); (*variables)["val_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(val->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["tag"] = + SimpleItoa(internal::WireFormat::MakeTag(descriptor)); if (HasDescriptorMethods(descriptor->file(), options)) { (*variables)["lite"] = ""; @@ -104,7 +101,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetMessageVariables(descriptor, &variables_, options); } @@ -112,37 +109,37 @@ MapFieldGenerator::~MapFieldGenerator() {} void MapFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ > $name$_;\n"); + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::MapField$lite$<\n" + " $map_classname$,\n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" + " $default_enum_value$ > $name$_;\n"); } void MapFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" + " ${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); } void MapFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" + Formatter format(printer, variables_); + format( + "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_map:$full_name$)\n" " return $name$_.GetMap();\n" "}\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n" " return $name$_.MutableMap();\n" @@ -151,17 +148,20 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { void MapFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } void MapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } void MapFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.Swap(&other->$name$_);\n"); } void MapFieldGenerator:: @@ -172,147 +172,138 @@ GenerateCopyConstructorCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - const FieldDescriptor* key_field = - descriptor_->message_type()->FindFieldByName("key"); + Formatter format(printer, variables_); + const FieldDescriptor* key_field = + descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = descriptor_->message_type()->FindFieldByName("value"); - bool using_entry = false; string key; string value; + format( + "$map_classname$::Parser< ::$proto_ns$::internal::MapField$lite$<\n" + " $map_classname$,\n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" + " $default_enum_value$ >,\n" + " ::$proto_ns$::Map< $key_cpp$, $val_cpp$ > >" + " parser(&$name$_);\n"); if (IsProto3Field(descriptor_) || value_field->type() != FieldDescriptor::TYPE_ENUM) { - printer->Print( - variables_, - "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\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" + format( + "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessageNoVirtual(\n" " input, &parser));\n"); key = "parser.key()"; value = "parser.value()"; } else { - using_entry = true; key = "entry->key()"; value = "entry->value()"; - printer->Print(variables_, - "::std::unique_ptr<$map_classname$> entry($name$_.NewEntry());\n"); - printer->Print(variables_, - "{\n" - " ::std::string data;\n" - " DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n" - " DO_(entry->ParseFromString(data));\n" - " if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" - " (*mutable_$name$())[entry->key()] =\n" - " static_cast< $val_cpp$ >(*entry->mutable_value());\n" - " } else {\n"); + format("auto entry = parser.NewEntry();\n"); + format( + "::std::string data;\n" + "DO_(::$proto_ns$::internal::WireFormatLite::ReadString(input, " + "&data));\n" + "DO_(entry->ParseFromString(data));\n" + "if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" + " (*mutable_$name$())[entry->key()] =\n" + " static_cast< $val_cpp$ >(*entry->mutable_value());\n" + "} else {\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - " mutable_unknown_fields()" + format( + " mutable_unknown_fields()" "->AddLengthDelimited($number$, data);\n"); } else { - printer->Print(variables_, - " unknown_fields_stream.WriteVarint32($tag$u);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(data.size()));\n" - " unknown_fields_stream.WriteString(data);\n"); + format( + " unknown_fields_stream.WriteVarint32($tag$u);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast< ::google::protobuf::uint32>(data.size()));\n" + " unknown_fields_stream.WriteString(data);\n"); } - - printer->Print(variables_, - " }\n" - "}\n"); + format("}\n"); } if (key_field->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - key_field, options_, true, variables_, - StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(), - printer); + key_field, options_, true, + StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n") + .data(), + format); } if (value_field->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - value_field, options_, true, variables_, - StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n") + value_field, options_, true, + StrCat(value, ".data(), static_cast<int>(", value, + ".length()),\n") .data(), - printer); - } - - // If entry is allocated by arena, its desctructor should be avoided. - if (using_entry && SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (entry->GetArena() != NULL) entry.release();\n"); + format); } } -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("::std::unique_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()); +static void GenerateSerializationLoop(const Formatter& format, + bool supports_arenas, bool string_key, + bool string_value, bool to_array, + bool is_deterministic) { + format("::std::unique_ptr<$map_classname$> entry;\n"); + string ptr; + if (is_deterministic) { + format("for (size_type i = 0; i < n; i++) {\n"); + ptr = string_key ? "items[static_cast<ptrdiff_t>(i)]" + : "items[static_cast<ptrdiff_t>(i)].second"; + } else { + format( + "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it) {\n"); + ptr = "it"; + } + format.Indent(); + + format("entry.reset($name$_.New$wrapper$($1$->first, $1$->second));\n", ptr); + if (to_array) { + format( + "target = ::$proto_ns$::internal::WireFormatLite::InternalWrite" + "$declared_type$NoVirtualToArray($number$, *entry, deterministic, " + "target);\n"); + } else { + format( + "::$proto_ns$::internal::WireFormatLite::Write$stream_writer$($number$," + " " + "*entry, output);\n"); + } // If entry is allocated by arena, its desctructor should be avoided. if (supports_arenas) { - printer->Print( + format( "if (entry->GetArena() != NULL) {\n" " entry.release();\n" "}\n"); } - 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()); + if (string_key || string_value) { + // ptr is either an actual pointer or an iterator, either way we can + // create a pointer by taking the address after de-referencing it. + format("Utf8Check::Check(&(*$1$));\n", ptr); } - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\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); + GenerateSerializeWithCachedSizes(printer, false); } void MapFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - 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); + GenerateSerializeWithCachedSizes(printer, true); } -void MapFieldGenerator::GenerateSerializeWithCachedSizes( - io::Printer* printer, const std::map<string, string>& variables) const { - printer->Print(variables, - "if (!this->$name$().empty()) {\n"); - printer->Indent(); +void MapFieldGenerator::GenerateSerializeWithCachedSizes(io::Printer* printer, + bool to_array) const { + Formatter format(printer, variables_); + format("if (!this->$name$().empty()) {\n"); + format.Indent(); const FieldDescriptor* key_field = descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = @@ -320,114 +311,110 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizes( 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" + format( + "typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" " ConstPtr;\n"); if (string_key) { - printer->Print(variables, + format( "typedef ConstPtr SortItem;\n" - "typedef ::google::protobuf::internal::" + "typedef ::$proto_ns$::internal::" "CompareByDerefFirst<SortItem> Less;\n"); } else { - printer->Print(variables, - "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > " + format( + "typedef ::$proto_ns$::internal::SortItem< $key_cpp$, ConstPtr > " "SortItem;\n" - "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n"); + "typedef ::$proto_ns$::internal::CompareByFirstField<SortItem> " + "Less;\n"); } - string utf8_check; - if (string_key || string_value) { - printer->Print( + bool utf8_check = string_key || string_value; + if (utf8_check) { + format( "struct Utf8Check {\n" " static void Check(ConstPtr p) {\n"); - printer->Indent(); - printer->Indent(); + format.Indent(); + format.Indent(); if (string_key) { GenerateUtf8CheckCodeForString( - key_field, options_, false, variables, - "p->first.data(), static_cast<int>(p->first.length()),\n", printer); + key_field, options_, false, + "p->first.data(), static_cast<int>(p->first.length()),\n", format); } if (string_value) { GenerateUtf8CheckCodeForString( - value_field, options_, false, variables, - "p->second.data(), static_cast<int>(p->second.length()),\n", printer); + value_field, options_, false, + "p->second.data(), static_cast<int>(p->second.length()),\n", format); } - printer->Outdent(); - printer->Outdent(); - printer->Print( + format.Outdent(); + format.Outdent(); + format( " }\n" "};\n"); - utf8_check = "Utf8Check::Check"; } - printer->Print(variables, + format( "\n" - "if ($deterministic$ &&\n" + "if ($1$ &&\n" " this->$name$().size() > 1) {\n" " ::std::unique_ptr<SortItem[]> items(\n" " new SortItem[this->$name$().size()]);\n" - " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n" + " typedef ::$proto_ns$::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" + " for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" " it = this->$name$().begin();\n" " it != this->$name$().end(); ++it, ++n) {\n" " items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n" " }\n" - " ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n"); - printer->Indent(); - GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_), - utf8_check, "for (size_type i = 0; i < n; i++)", - string_key ? "items[static_cast<ptrdiff_t>(i)]" : - "items[static_cast<ptrdiff_t>(i)].second", false); - printer->Outdent(); - printer->Print( - "} 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"); + " ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n", + to_array ? "deterministic" : "output->IsSerializationDeterministic()"); + format.Indent(); + GenerateSerializationLoop(format, SupportsArenas(descriptor_), string_key, + string_value, to_array, true); + format.Outdent(); + format("} else {\n"); + format.Indent(); + GenerateSerializationLoop(format, SupportsArenas(descriptor_), string_key, + string_value, to_array, false); + format.Outdent(); + format("}\n"); + format.Outdent(); + format("}\n"); } void MapFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, + Formatter format(printer, variables_); + format( "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" + " ::$proto_ns$::internal::FromIntSize(this->$name$_size());\n" "{\n" " ::std::unique_ptr<$map_classname$> entry;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " for (::$proto_ns$::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_, + format( " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" " entry.release();\n" " }\n"); } - printer->Print(variables_, + format( " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" - " total_size += ::google::protobuf::internal::WireFormatLite::\n" + " total_size += ::$proto_ns$::internal::WireFormatLite::\n" " $declared_type$SizeNoVirtual(*entry);\n" " }\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { - printer->Print(variables_, + format( " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" " entry.release();\n" " }\n"); } - printer->Print("}\n"); + format("}\n"); } } // namespace cpp |