diff options
author | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-04-18 00:02:12 +0000 |
---|---|---|
committer | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-04-18 00:02:12 +0000 |
commit | cfa2d8aa87cc0b22b5092a5fb3bf7e394f85cbf1 (patch) | |
tree | 77ee2f4d02dfb43187511f3eb5a37a00c2f6f5de /src/google/protobuf/compiler | |
parent | eb26a1efdef3f1f5e77807d456a08f3c76cc5207 (diff) |
Generate field number constants. Patch from Michael Poole.
Diffstat (limited to 'src/google/protobuf/compiler')
10 files changed, 94 insertions, 11 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index 0dd8420d..3f212b93 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -77,9 +77,11 @@ ExtensionGenerator::~ExtensionGenerator() {} void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { map<string, string> vars; - vars["extendee" ] = ClassName(descriptor_->containing_type(), true); - vars["type_traits"] = type_traits_; - vars["name" ] = descriptor_->name(); + vars["extendee" ] = ClassName(descriptor_->containing_type(), true); + vars["number" ] = SimpleItoa(descriptor_->number()); + vars["type_traits" ] = type_traits_; + vars["name" ] = descriptor_->name(); + vars["constant_name"] = FieldConstantName(descriptor_); // If this is a class member, it needs to be declared "static". Otherwise, // it needs to be "extern". @@ -91,24 +93,34 @@ 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"); } void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { map<string, string> vars; - vars["extendee" ] = ClassName(descriptor_->containing_type(), true); - vars["number" ] = SimpleItoa(descriptor_->number()); - vars["type_traits"] = type_traits_; - vars["name" ] = descriptor_->name(); + vars["extendee" ] = ClassName(descriptor_->containing_type(), true); + vars["type_traits" ] = type_traits_; + vars["name" ] = descriptor_->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) + "::"; + // Likewise, class members need to declare the field constant variable. + if (descriptor_->extension_scope() != NULL) { + printer->Print(vars, + "#ifndef _MSC_VER\n" + "const int $scope$$constant_name$;\n" + "#endif\n"); + } + printer->Print(vars, "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" - " ::google::protobuf::internal::$type_traits$ > $scope$$name$($number$);\n"); + " ::google::protobuf::internal::$type_traits$ > $scope$$name$(" + "$constant_name$);\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 11122883..d536bea4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -77,6 +77,31 @@ hash_set<string> MakeKeywordsMap() { hash_set<string> kKeywords = MakeKeywordsMap(); +string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { + string result; + // Note: I distrust ctype.h due to locales. + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + if (cap_next_letter) { + result += input[i] + ('A' - 'a'); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if ('A' <= input[i] && input[i] <= 'Z') { + // Capital letters are left as-is. + result += input[i]; + cap_next_letter = false; + } else if ('0' <= input[i] && input[i] <= '9') { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + } + } + return result; +} + } // namespace const char kThickSeparator[] = @@ -124,6 +149,11 @@ string FieldName(const FieldDescriptor* field) { return result; } +string FieldConstantName(const FieldDescriptor *field) { + string field_name = UnderscoresToCamelCase(field->name(), true); + return "k" + field_name + "FieldNumber"; +} + string StripProto(const string& filename) { if (HasSuffixString(filename, ".protodevel")) { return StripSuffixString(filename, ".protodevel"); diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 80c2f2ee..30c6e7d0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -65,6 +65,10 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified); // anyway, so normally this just returns field->name(). string FieldName(const FieldDescriptor* field); +// Get the unqualified name that should be used for a field's field +// number constant. +string FieldConstantName(const FieldDescriptor *field); + // Returns the scope where the field was defined (for extensions, this is // different from the message type to which the field applies). inline const Descriptor* FieldScope(const FieldDescriptor* field) { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index d2f76803..2ec49234 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -204,6 +204,8 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { map<string, string> vars; vars["name"] = FieldName(field); + vars["constant_name"] = FieldConstantName(field); + vars["number"] = SimpleItoa(field->number()); if (field->is_repeated()) { printer->Print(vars, "inline int $name$_size() const;\n"); @@ -212,6 +214,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { } printer->Print(vars, "inline void clear_$name$();\n"); + printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); @@ -665,9 +668,21 @@ GenerateClassMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) .GenerateNonInlineAccessorDefinitions(printer); - printer->Print("\n"); } + // Generate field number constants. + printer->Print("#ifndef _MSC_VER\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = descriptor_->field(i); + printer->Print( + "const int $classname$::$constant_name$;\n", + "classname", ClassName(FieldScope(field), false), + "constant_name", FieldConstantName(field)); + } + printer->Print( + "#endif // !_MSC_VER\n" + "\n"); + // Define extension identifiers. for (int i = 0; i < descriptor_->extension_count(); i++) { extension_generators_[i]->GenerateDefinition(printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 51c5c6f5..8e10e9b0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -180,10 +180,10 @@ void StringFieldGenerator:: GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { if (descriptor_->default_value_string().empty()) { printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_;"); + "const ::std::string $classname$::_default_$name$_;\n"); } else { printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_($default$);"); + "const ::std::string $classname$::_default_$name$_($default$);\n"); } } diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 8f6500b5..302dcea4 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -57,6 +57,8 @@ void ExtensionGenerator::Generate(io::Printer* printer) { map<string, string> vars; vars["name"] = UnderscoresToCamelCase(descriptor_); vars["containing_type"] = ClassName(descriptor_->containing_type()); + vars["number"] = SimpleItoa(descriptor_->number()); + vars["constant_name"] = FieldConstantName(descriptor_); JavaType java_type = GetJavaType(descriptor_); string singular_type; @@ -72,6 +74,8 @@ void ExtensionGenerator::Generate(io::Printer* printer) { break; } + printer->Print(vars, + "public static final int $constant_name$ = $number$;\n"); if (descriptor_->is_repeated()) { printer->Print(vars, "public static\n" diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index c1994352..6a107650 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -171,6 +171,12 @@ string ClassName(const FileDescriptor* descriptor) { return result; } +string FieldConstantName(const FieldDescriptor *field) { + string name = field->name() + "_FIELD_NUMBER"; + UpperString(&name); + return name; +} + JavaType GetJavaType(FieldDescriptor::Type field_type) { switch (field_type) { case FieldDescriptor::TYPE_INT32: diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 43f2add0..de3f883b 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -88,6 +88,10 @@ inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) { } string ClassName(const FileDescriptor* descriptor); +// Get the unqualified name that should be used for a field's field +// number constant. +string FieldConstantName(const FieldDescriptor *field); + enum JavaType { JAVATYPE_INT, JAVATYPE_LONG, diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 9a4b2f79..c2e0c115 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -311,6 +311,9 @@ void MessageGenerator::Generate(io::Printer* printer) { // Fields for (int i = 0; i < descriptor_->field_count(); i++) { PrintFieldComment(printer, descriptor_->field(i)); + printer->Print("public static final int $constant_name$ = $number$;\n", + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", SimpleItoa(descriptor_->field(i)->number())); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index ca69fd4c..d301f015 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -319,6 +319,11 @@ void Generator::PrintTopLevelExtensions() const { const bool is_extension = true; for (int i = 0; i < file_->extension_count(); ++i) { const FieldDescriptor& extension_field = *file_->extension(i); + string constant_name = extension_field.name() + "_FIELD_NUMBER"; + UpperString(&constant_name); + printer_->Print("$constant_name$ = $number$\n", + "constant_name", constant_name, + "number", SimpleItoa(extension_field.number())); printer_->Print("$name$ = ", "name", extension_field.name()); PrintFieldDescriptor(extension_field, is_extension); printer_->Print("\n"); |