aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/cpp/cpp_extension.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_extension.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc81
1 files changed, 72 insertions, 9 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 3f212b93..61ebda73 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
@@ -55,7 +56,9 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
case FieldDescriptor::CPPTYPE_ENUM:
type_traits_.append("EnumTypeTraits< ");
type_traits_.append(ClassName(descriptor_->enum_type(), true));
- type_traits_.append(" >");
+ type_traits_.append(", ");
+ type_traits_.append(ClassName(descriptor_->enum_type(), true));
+ type_traits_.append("_IsValid>");
break;
case FieldDescriptor::CPPTYPE_STRING:
type_traits_.append("StringTypeTraits");
@@ -81,6 +84,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
vars["name" ] = descriptor_->name();
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
vars["constant_name"] = FieldConstantName(descriptor_);
// If this is a class member, it needs to be declared "static". Otherwise,
@@ -95,19 +100,39 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
printer->Print(vars,
"static const int $constant_name$ = $number$;\n"
"$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
- " ::google::protobuf::internal::$type_traits$ > $name$;\n");
+ " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " $name$;\n"
+ );
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
+ // If this is a class member, it needs to be declared in its class scope.
+ string scope = (descriptor_->extension_scope() == NULL) ? "" :
+ ClassName(descriptor_->extension_scope(), false) + "::";
+ string name = scope + descriptor_->name();
+
map<string, string> vars;
vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
vars["type_traits" ] = type_traits_;
- vars["name" ] = descriptor_->name();
+ vars["name" ] = name;
vars["constant_name"] = FieldConstantName(descriptor_);
-
- // If this is a class member, it needs to be declared in its class scope.
- vars["scope"] = (descriptor_->extension_scope() == NULL) ? "" :
- ClassName(descriptor_->extension_scope(), false) + "::";
+ vars["default" ] = DefaultValue(descriptor_);
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
+ vars["scope" ] = scope;
+
+ if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ // We need to declare a global string which will contain the default value.
+ // We cannot declare it at class scope because that would require exposing
+ // it in the header which would be annoying for other reasons. So we
+ // replace :: with _ in the name and declare it as a global.
+ string global_name = StringReplace(name, "::", "_", true);
+ vars["global_name"] = global_name;
+ printer->Print(vars,
+ "const ::std::string $global_name$_default($default$);\n");
+ // Update the default to refer to the string global.
+ vars["default"] = global_name + "_default";
+ }
// Likewise, class members need to declare the field constant variable.
if (descriptor_->extension_scope() != NULL) {
@@ -119,8 +144,46 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
printer->Print(vars,
"::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
- " ::google::protobuf::internal::$type_traits$ > $scope$$name$("
- "$constant_name$);\n");
+ " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " $name$($constant_name$, $default$);\n");
+}
+
+void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
+ map<string, string> vars;
+ vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["number" ] = SimpleItoa(descriptor_->number());
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
+ vars["is_packed" ] = (descriptor_->is_repeated() &&
+ descriptor_->options().packed())
+ ? "true" : "false";
+
+ switch (descriptor_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(
+ " &$type$_IsValid);\n",
+ "type", ClassName(descriptor_->enum_type(), true));
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(
+ " &$type$::default_instance());\n",
+ "type", ClassName(descriptor_->message_type(), true));
+ break;
+ default:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
+ break;
+ }
}
} // namespace cpp