diff options
Diffstat (limited to 'src/google')
7 files changed, 308 insertions, 21 deletions
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc new file mode 100644 index 00000000..ea74af9c --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: bduff@google.com (Brian Duff) + +#include <google/protobuf/compiler/javanano/javanano_extension.h> +#include <google/protobuf/compiler/javanano/javanano_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/wire_format.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace javanano { + +using internal::WireFormat; + +void SetVariables(const FieldDescriptor* descriptor, const Params params, + map<string, string>* variables) { + (*variables)["name"] = UnderscoresToCamelCase(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["extends"] = ClassName(params, descriptor->containing_type()); + + string type; + JavaType java_type = GetJavaType(descriptor->type()); + switch (java_type) { + case JAVATYPE_ENUM: + type = "java.lang.Integer"; + break; + case JAVATYPE_MESSAGE: + type = ClassName(params, descriptor->message_type()); + break; + default: + type = BoxedPrimitiveTypeName(java_type); + break; + } + (*variables)["type"] = type; +} + +ExtensionGenerator:: +ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params) + : params_(params), descriptor_(descriptor) { + SetVariables(descriptor, params, &variables_); +} + +ExtensionGenerator::~ExtensionGenerator() {} + +void ExtensionGenerator::Generate(io::Printer* printer) const { + if (descriptor_->is_repeated()) { + printer->Print(variables_, + "// Extends $extends$\n" + "public static final com.google.protobuf.nano.Extension<java.util.List<$type$>> $name$ = \n" + " com.google.protobuf.nano.Extension.createRepeated($number$,\n" + " new com.google.protobuf.nano.Extension.TypeLiteral<java.util.List<$type$>>(){});\n"); + } else { + printer->Print(variables_, + "// Extends $extends$\n" + "public static final com.google.protobuf.nano.Extension<$type$> $name$ =\n" + " com.google.protobuf.nano.Extension.create($number$,\n" + " new com.google.protobuf.nano.Extension.TypeLiteral<$type$>(){});\n"); + } +} + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google + diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/javanano/javanano_extension.h new file mode 100644 index 00000000..c6543ebd --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_extension.h @@ -0,0 +1,74 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: bduff@google.com (Brian Duff) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/compiler/javanano/javanano_params.h> +#include <google/protobuf/descriptor.pb.h> + + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace javanano { + +class ExtensionGenerator { + public: + explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params); + ~ExtensionGenerator(); + + void Generate(io::Printer* printer) const; + + private: + const Params& params_; + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_ diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc index 2f42fa0e..6efa2bf3 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.cc +++ b/src/google/protobuf/compiler/javanano/javanano_file.cc @@ -34,6 +34,7 @@ #include <google/protobuf/compiler/javanano/javanano_file.h> #include <google/protobuf/compiler/javanano/javanano_enum.h> +#include <google/protobuf/compiler/javanano/javanano_extension.h> #include <google/protobuf/compiler/javanano/javanano_helpers.h> #include <google/protobuf/compiler/javanano/javanano_message.h> #include <google/protobuf/compiler/code_generator.h> @@ -94,10 +95,11 @@ bool FileGenerator::Validate(string* error) { // Check for extensions FileDescriptorProto file_proto; file_->CopyTo(&file_proto); - if (UsesExtensions(file_proto)) { + if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) { error->assign(file_->name()); error->append( - ": Java NANO_RUNTIME does not support extensions\""); + ": Java NANO_RUNTIME only supports extensions when the " + "'store_unknown_fields' generator option is 'true'."); return false; } @@ -179,6 +181,11 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- + // Extensions. + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator(file_->extension(i), params_).Generate(printer); + } + if (!params_.java_multiple_files()) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator(file_->enum_type(i), params_).Generate(printer); diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 554f6d4d..19a3dccd 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -115,6 +115,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, return false; } params.set_java_outer_classname(parts[0], parts[1]); + } else if (options[i].first == "store_unknown_fields") { + params.set_store_unknown_fields(options[i].second == "true"); } else if (options[i].first == "java_multiple_files") { params.set_java_multiple_files(options[i].second == "true"); } else { diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index f8a4fe78..27407794 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -36,6 +36,7 @@ #include <google/protobuf/stubs/hash.h> #include <google/protobuf/compiler/javanano/javanano_message.h> #include <google/protobuf/compiler/javanano/javanano_enum.h> +#include <google/protobuf/compiler/javanano/javanano_extension.h> #include <google/protobuf/compiler/javanano/javanano_helpers.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/io/printer.h> @@ -117,10 +118,6 @@ void MessageGenerator::GenerateStaticVariableInitializers( MessageGenerator(descriptor_->nested_type(i), params_) .GenerateStaticVariableInitializers(printer); } - - if (descriptor_->extension_count() != 0) { - GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; - } } void MessageGenerator::Generate(io::Printer* printer) { @@ -135,9 +132,10 @@ void MessageGenerator::Generate(io::Printer* printer) { GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name()); #endif - if ((descriptor_->extension_count() != 0) - || (descriptor_->extension_range_count() != 0)) { - GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; + if (!params_.store_unknown_fields() && + (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) { + GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the " + "'store_unknown_fields' generator option is 'true'\n"; } // Note: Fields (which will be emitted in the loop, below) may have the same names as fields in @@ -156,7 +154,17 @@ void MessageGenerator::Generate(io::Printer* printer) { "\n", "classname", descriptor_->name()); + if (params_.store_unknown_fields()) { + printer->Print( + "private java.util.List<com.google.protobuf.nano.UnknownFieldData>\n" + " unknownFieldData;\n"); + } + // Nested types and extensions + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer); } @@ -173,6 +181,24 @@ void MessageGenerator::Generate(io::Printer* printer) { } GenerateClear(printer); + + // If we have an extension range, generate accessors for extensions. + if (params_.store_unknown_fields() + && descriptor_->extension_range_count() > 0) { + printer->Print( + "public <T> T getExtension(com.google.protobuf.nano.Extension<T> extension) {\n" + " return com.google.protobuf.nano.WireFormatNano.getExtension(\n" + " extension, unknownFieldData);\n" + "}\n\n" + "public <T> void setExtension(com.google.protobuf.nano.Extension<T> extension, T value) {\n" + " if (unknownFieldData == null) {\n" + " unknownFieldData = \n" + " new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n" + " }\n" + " com.google.protobuf.nano.WireFormatNano.setExtension(\n" + " extension, value, unknownFieldData);\n" + "}\n\n"); + } GenerateMessageSerializationMethods(printer); GenerateMergeFromMethods(printer); GenerateParseFromMethods(printer); @@ -188,12 +214,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) { scoped_array<const FieldDescriptor*> sorted_fields( SortFieldsByNumber(descriptor_)); - if (descriptor_->extension_range_count() != 0) { - GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; - } - // writeTo only throws an exception if it contains one or more fields to write - if (descriptor_->field_count() > 0) { + if (descriptor_->field_count() > 0 || params_.store_unknown_fields()) { printer->Print( "@Override\n" "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n" @@ -207,7 +229,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) { // Output the fields in sorted order for (int i = 0; i < descriptor_->field_count(); i++) { - GenerateSerializeOneField(printer, sorted_fields[i]); + GenerateSerializeOneField(printer, sorted_fields[i]); + } + + // Write unknown fields. + if (params_.store_unknown_fields()) { + printer->Print( + "com.google.protobuf.nano.WireFormatNano.writeUnknownFields(\n" + " unknownFieldData, output);\n"); } printer->Outdent(); @@ -233,6 +262,11 @@ GenerateMessageSerializationMethods(io::Printer* printer) { field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); } + if (params_.store_unknown_fields()) { + printer->Print( + "size += com.google.protobuf.nano.WireFormatNano.computeWireSize(unknownFieldData);\n"); + } + printer->Outdent(); printer->Print( " cachedSize = size;\n" @@ -266,12 +300,28 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { printer->Print( "case 0:\n" // zero signals EOF / limit reached " return this;\n" - "default: {\n" - " if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" - " return this;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); + "default: {\n"); + + printer->Indent(); + if (params_.store_unknown_fields()) { + printer->Print( + "if (unknownFieldData == null) {\n" + " unknownFieldData = \n" + " new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n" + "}\n" + "if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(unknownFieldData, \n" + " input, tag)) {\n" + " return this;\n" + "}\n"); + } else { + printer->Print( + "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" + " return this;\n" // it's an endgroup tag + "}\n"); + } + printer->Print("break;\n"); + printer->Outdent(); + printer->Print("}\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; @@ -356,6 +406,11 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { } } + // Clear unknown fields. + if (params_.store_unknown_fields()) { + printer->Print("unknownFieldData = null;\n"); + } + printer->Outdent(); printer->Print( " cachedSize = -1;\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index f6192eae..30eedff0 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -49,6 +49,7 @@ class Params { string empty_; string base_name_; bool java_multiple_files_; + bool store_unknown_fields_; NameMap java_packages_; NameMap java_outer_classnames_; @@ -56,6 +57,7 @@ class Params { Params(const string & base_name) : empty_(""), base_name_(base_name), + store_unknown_fields_(false), java_multiple_files_(false) { } @@ -107,6 +109,13 @@ class Params { return java_outer_classnames_; } + void set_store_unknown_fields(bool value) { + store_unknown_fields_ = value; + } + bool store_unknown_fields() const { + return store_unknown_fields_; + } + void set_java_multiple_files(bool value) { java_multiple_files_ = value; } diff --git a/src/google/protobuf/unittest_extension_nano.proto b/src/google/protobuf/unittest_extension_nano.proto new file mode 100644 index 00000000..f2906f00 --- /dev/null +++ b/src/google/protobuf/unittest_extension_nano.proto @@ -0,0 +1,44 @@ +syntax = "proto2"; + +option java_outer_classname = "Extensions"; +option java_package = "com.google.protobuf.nano"; + +message ExtendableMessage { + optional int32 field = 1; + extensions 10 to max; +} + +enum AnEnum { + FIRST_VALUE = 1; + SECOND_VALUE = 2; +} + +message AnotherMessage { + optional string string = 1; + optional bool value = 2; +} + +extend ExtendableMessage { + optional string some_string = 10; + optional int32 some_int = 11; + optional int64 some_long = 12; + optional float some_float = 13; + optional double some_double = 14; + optional bool some_bool = 15; + optional AnEnum some_enum = 16; + optional AnotherMessage some_message = 17; + repeated string some_repeated_string = 18; + repeated int32 some_repeated_int = 19; + repeated int64 some_repeated_long = 20; + repeated float some_repeated_float = 21; + repeated double some_repeated_double = 22; + repeated bool some_repeated_bool = 23; + repeated AnEnum some_repeated_enum = 24; + repeated AnotherMessage some_repeated_message = 25; +} + +message ContainerMessage { + extend ExtendableMessage { + optional bool another_thing = 100; + } +} |