diff options
Diffstat (limited to 'src')
116 files changed, 4320 insertions, 4096 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5b28579f..584bcd21 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,16 +71,24 @@ nobase_include_HEADERS = \ google/protobuf/stubs/atomicops_internals_tsan.h \ google/protobuf/stubs/atomicops_internals_x86_gcc.h \ google/protobuf/stubs/atomicops_internals_x86_msvc.h \ + google/protobuf/stubs/callback.h \ + google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/casts.h \ google/protobuf/stubs/common.h \ google/protobuf/stubs/fastmem.h \ google/protobuf/stubs/hash.h \ + google/protobuf/stubs/logging.h \ + google/protobuf/stubs/macros.h \ + google/protobuf/stubs/mutex.h \ google/protobuf/stubs/once.h \ - google/protobuf/stubs/pbconfig.h \ google/protobuf/stubs/platform_macros.h \ + google/protobuf/stubs/port.h \ + google/protobuf/stubs/scoped_ptr.h \ google/protobuf/stubs/shared_ptr.h \ google/protobuf/stubs/singleton.h \ + google/protobuf/stubs/status.h \ google/protobuf/stubs/stl_util.h \ + google/protobuf/stubs/stringpiece.h \ google/protobuf/stubs/template_util.h \ google/protobuf/stubs/type_traits.h \ google/protobuf/any.pb.h \ @@ -148,6 +156,7 @@ nobase_include_HEADERS = \ google/protobuf/compiler/python/python_generator.h \ google/protobuf/compiler/ruby/ruby_generator.h \ google/protobuf/compiler/csharp/csharp_generator.h \ + google/protobuf/compiler/csharp/csharp_names.h \ google/protobuf/util/type_resolver.h \ google/protobuf/util/type_resolver_util.h \ google/protobuf/util/json_util.h \ @@ -420,13 +429,13 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/csharp/csharp_enum.h \ google/protobuf/compiler/csharp/csharp_enum_field.cc \ google/protobuf/compiler/csharp/csharp_enum_field.h \ - google/protobuf/compiler/csharp/csharp_extension.cc \ - google/protobuf/compiler/csharp/csharp_extension.h \ google/protobuf/compiler/csharp/csharp_field_base.cc \ google/protobuf/compiler/csharp/csharp_field_base.h \ google/protobuf/compiler/csharp/csharp_generator.cc \ google/protobuf/compiler/csharp/csharp_helpers.cc \ google/protobuf/compiler/csharp/csharp_helpers.h \ + google/protobuf/compiler/csharp/csharp_map_field.cc \ + google/protobuf/compiler/csharp/csharp_map_field.h \ google/protobuf/compiler/csharp/csharp_message.cc \ google/protobuf/compiler/csharp/csharp_message.h \ google/protobuf/compiler/csharp/csharp_message_field.cc \ @@ -443,8 +452,8 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/csharp/csharp_source_generator_base.h \ google/protobuf/compiler/csharp/csharp_umbrella_class.cc \ google/protobuf/compiler/csharp/csharp_umbrella_class.h \ - google/protobuf/compiler/csharp/csharp_writer.cc \ - google/protobuf/compiler/csharp/csharp_writer.h + google/protobuf/compiler/csharp/csharp_wrapper_field.cc \ + google/protobuf/compiler/csharp/csharp_wrapper_field.h bin_PROGRAMS = protoc protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 2c492b04..c2e58131 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\031google/protobuf/any.proto\022\017google.prot" "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" - " \001(\014BC\n\023com.google.protobufB\010AnyProtoP\001\240" - "\001\001\242\002\003GPB\252\002\026Google.ProtocolBuffersb\006proto" - "3", 161); + " \001(\014BK\n\023com.google.protobufB\010AnyProtoP\001\240" + "\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownType" + "sb\006proto3", 169); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/any.proto", &protobuf_RegisterTypes); Any::default_instance_ = new Any(); diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index e1780fe5..d3ad3acc 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "AnyProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 434320dc..0feddb31 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -123,8 +123,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() { "quest_type_url\030\002 \001(\t\022\031\n\021request_streamin" "g\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022re" "sponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\0132" - "\027.google.protobuf.OptionB\'\n\023com.google.p" - "rotobufB\010ApiProtoP\001\242\002\003GPBb\006proto3", 513); + "\027.google.protobuf.OptionBH\n\023com.google.p" + "rotobufB\010ApiProtoP\001\242\002\003GPB\252\002\036Google.Proto" + "buf.WellKnownTypesb\006proto3", 546); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/api.proto", &protobuf_RegisterTypes); Api::default_instance_ = new Api(); diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto index f368c24d..d6c2a8b3 100644 --- a/src/google/protobuf/api.proto +++ b/src/google/protobuf/api.proto @@ -37,6 +37,7 @@ import "google/protobuf/type.proto"; option java_multiple_files = true; option java_outer_classname = "ApiProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index c57cfd3d..e8871861 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -189,7 +189,7 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { bool GetProtocAbsolutePath(string* path) { #ifdef _WIN32 char buffer[MAX_PATH]; - int len = GetModuleFileName(NULL, buffer, MAX_PATH); + int len = GetModuleFileNameA(NULL, buffer, MAX_PATH); #elif __APPLE__ char buffer[PATH_MAX]; int len = 0; diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 51a95b9f..d38fb1ed 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -55,36 +55,29 @@ EnumFieldGenerator::~EnumFieldGenerator() { void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "object unknown;\n" - "if(input.ReadEnum(ref result.$name$_, out unknown)) {\n"); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print("} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print(variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "$name$_ = ($type_name$) input.ReadEnum();\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, - "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" + "}\n"); } void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( - variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" - "}\n"); + variables_, + "if ($has_property_check$) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" + "}\n"); +} + +void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -96,30 +89,19 @@ EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "object unknown;\n" - "$type_name$ enumValue = $default_value$;\n" - "if(input.ReadEnum(ref enumValue, out unknown)) {\n" - " result.$oneof_name$_ = enumValue;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "$oneof_name$_ = input.ReadEnum();\n" + "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" "}\n"); } @@ -127,7 +109,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index e627b7cc..08364157 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -46,6 +46,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator { EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc deleted file mode 100644 index 8b665ae4..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// 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. - -#include <sstream> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/plugin.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> - -#include <google/protobuf/compiler/csharp/csharp_extension.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> - -using google::protobuf::internal::scoped_ptr; - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) - : FieldGeneratorBase(descriptor, 0) { - if (descriptor_->extension_scope()) { - variables_["scope"] = GetClassName(descriptor_->extension_scope()); - } else { - variables_["scope"] = GetFullUmbrellaClassName(descriptor_->file()); - } - variables_["extends"] = GetClassName(descriptor_->containing_type()); - variables_["capitalized_type_name"] = capitalized_type_name(); - variables_["full_name"] = descriptor_->full_name(); - variables_["access_level"] = class_access_level(); - variables_["index"] = SimpleItoa(descriptor_->index()); - variables_["property_name"] = property_name(); - variables_["type_name"] = type_name(); - if (use_lite_runtime()) { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"; - } else { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtension" : "GeneratedExtension"; - } -} - -ExtensionGenerator::~ExtensionGenerator() { -} - -void ExtensionGenerator::Generate(io::Printer* printer) { - printer->Print( - "public const int $constant_name$ = $number$;\n", - "constant_name", GetFieldConstantName(descriptor_), - "number", SimpleItoa(descriptor_->number())); - - if (use_lite_runtime()) { - // TODO(jtattermusch): include the following check - //if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) - //{ - // throw new ArgumentException( - // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); - //} - - printer->Print( - variables_, - "$access_level$ static pb::$generated_extension$<$extends$, $type_name$> $property_name$;\n"); - } else if (descriptor_->is_repeated()) { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase<scg::IList<$type_name$>> $property_name$;\n"); - } else { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase<$type_name$> $property_name$;\n"); - } -} - -void ExtensionGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - if (use_lite_runtime()) { - printer->Print( - variables_, - "$scope$.$property_name$ = \n"); - printer->Indent(); - printer->Print( - variables_, - "new pb::$generated_extension$<$extends$, $type_name$>(\n"); - printer->Indent(); - printer->Print( - variables_, - "\"$full_name$\",\n" - "$extends$.DefaultInstance,\n"); - if (!descriptor_->is_repeated()) { - std::string default_val; - if (descriptor_->has_default_value()) { - default_val = default_value(); - } else { - default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); - } - printer->Print("$default_val$,\n", "default_val", default_val); - } - printer->Print( - "$message_val$,\n", - "message_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? - type_name() + ".DefaultInstance" : "null"); - printer->Print( - "$enum_val$,\n", - "enum_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? - "new EnumLiteMap<" + type_name() + ">()" : "null"); - printer->Print( - variables_, - "$scope$.$property_name$FieldNumber,\n" - "pbd::FieldType.$capitalized_type_name$"); - if (descriptor_->is_repeated()) { - printer->Print( - ",\n" - "$is_packed$", - "is_packed", descriptor_->is_packed() ? "true" : "false"); - } - printer->Outdent(); - printer->Print(");\n"); - printer->Outdent(); - } - else if (descriptor_->is_repeated()) - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedRepeatExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } - else - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedSingleExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } -} - -void ExtensionGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - printer->Print( - variables_, - "registry.Add($scope$.$property_name$);\n"); -} - -void ExtensionGenerator::WriteHash(io::Printer* printer) { -} - -void ExtensionGenerator::WriteEquals(io::Printer* printer) { -} - -void ExtensionGenerator::WriteToString(io::Printer* printer) { -} - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 4c6a3d72..5df43d3f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -35,13 +35,16 @@ #include <google/protobuf/compiler/plugin.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/mathlimits.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> using google::protobuf::internal::scoped_ptr; @@ -52,6 +55,23 @@ namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( map<string, string>* variables) { + // Note: this will be valid even though the tag emitted for packed and unpacked versions of + // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which + // never effects the tag size. + int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + uint tag = internal::WireFormat::MakeTag(descriptor_); + uint8 tag_array[5]; + io::CodedOutputStream::WriteTagToArray(tag, tag_array); + string tag_bytes = SimpleItoa(tag_array[0]); + for (int i = 1; i < tag_size; i++) { + tag_bytes += ", " + SimpleItoa(tag_array[i]); + } + + (*variables)["access_level"] = "public"; + (*variables)["tag"] = SimpleItoa(tag); + (*variables)["tag_size"] = SimpleItoa(tag_size); + (*variables)["tag_bytes"] = tag_bytes; + (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); (*variables)["name"] = name(); @@ -65,16 +85,10 @@ void FieldGeneratorBase::SetCommonFieldVariables( } (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); - (*variables)["field_ordinal"] = field_ordinal(); - if (SupportFieldPresence(descriptor_->file())) { - (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; - (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; - } else { - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - } + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; } void FieldGeneratorBase::SetCommonOneofFieldVariables( @@ -96,21 +110,20 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, FieldGeneratorBase::~FieldGeneratorBase() { } -void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { - if (descriptor_->options().deprecated()) - { - printer->Print("[global::System.ObsoleteAttribute()]\n"); - } +void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) { + // No-op: only message fields and repeated fields need + // special handling for freezing, so default to not generating any code. } -void FieldGeneratorBase::AddNullCheck(io::Printer* printer) { - AddNullCheck(printer, "value"); +void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) { + // No-op: expect this to be overridden by appropriate types. + // Could fail if we get called here though... } -void FieldGeneratorBase::AddNullCheck(io::Printer* printer, const std::string& name) { - if (is_nullable_type()) { - printer->Print(" pb::ThrowHelper.ThrowIfNull($name$, \"$name$\");\n", - "name", name); +void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { + if (descriptor_->options().deprecated()) + { + printer->Print("[global::System.ObsoleteAttribute()]\n"); } } @@ -135,12 +148,28 @@ std::string FieldGeneratorBase::name() { } std::string FieldGeneratorBase::type_name() { - switch (descriptor_->type()) { + return type_name(descriptor_); +} + +std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) { + switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return GetClassName(descriptor_->enum_type()); + return GetClassName(descriptor->enum_type()); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: - return GetClassName(descriptor_->message_type()); + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + string wrapped_field_type_name = type_name(wrapped_field); + // String and ByteString go to the same type; other wrapped types go to the + // nullable equivalent. + if (wrapped_field->type() == FieldDescriptor::TYPE_STRING || + wrapped_field->type() == FieldDescriptor::TYPE_BYTES) { + return wrapped_field_type_name; + } else { + return wrapped_field_type_name + "?"; + } + } + return GetClassName(descriptor->message_type()); case FieldDescriptor::TYPE_DOUBLE: return "double"; case FieldDescriptor::TYPE_FLOAT: @@ -259,48 +288,33 @@ bool AllPrintableAscii(const std::string& text) { } std::string FieldGeneratorBase::GetStringDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "\"\""; - } - if (AllPrintableAscii(descriptor_->default_value_string())) { - // All chars are ASCII and printable. In this case we only - // need to escape quotes and backslashes. - std::string temp = descriptor_->default_value_string(); - temp = StringReplace(temp, "\\", "\\\\", true); - temp = StringReplace(temp, "'", "\\'", true); - temp = StringReplace(temp, "\"", "\\\"", true); - return "\"" + temp + "\""; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" - + StringToBase64(descriptor_->default_value_string()) - + "\").ToStringUtf8()"; - } - return "(string) " + GetClassName(descriptor_->containing_type()) - + ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) - + "].DefaultValue"; + // No other default values needed for proto3... + return "\"\""; } std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "pb::ByteString.Empty"; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor_->default_value_string()) + "\")"; - } - return "(pb::ByteString) "+ GetClassName(descriptor_->containing_type()) + - ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) + "].DefaultValue"; + // No other default values needed for proto3... + return "pb::ByteString.Empty"; } std::string FieldGeneratorBase::default_value() { - switch (descriptor_->type()) { + return default_value(descriptor_); +} + +std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { + switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return type_name() + "." + descriptor_->default_value_enum()->name(); + return type_name() + "." + descriptor->default_value_enum()->name(); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: - return type_name() + ".DefaultInstance"; + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + return default_value(wrapped_field); + } else { + return "null"; + } case FieldDescriptor::TYPE_DOUBLE: { - double value = descriptor_->default_value_double(); + double value = descriptor->default_value_double(); if (value == numeric_limits<double>::infinity()) { return "double.PositiveInfinity"; } else if (value == -numeric_limits<double>::infinity()) { @@ -311,7 +325,7 @@ std::string FieldGeneratorBase::default_value() { return SimpleDtoa(value) + "D"; } case FieldDescriptor::TYPE_FLOAT: { - float value = descriptor_->default_value_float(); + float value = descriptor->default_value_float(); if (value == numeric_limits<float>::infinity()) { return "float.PositiveInfinity"; } else if (value == -numeric_limits<float>::infinity()) { @@ -322,17 +336,17 @@ std::string FieldGeneratorBase::default_value() { return SimpleFtoa(value) + "F"; } case FieldDescriptor::TYPE_INT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_UINT64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_INT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_FIXED64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_FIXED32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_BOOL: - if (descriptor_->default_value_bool()) { + if (descriptor->default_value_bool()) { return "true"; } else { return "false"; @@ -342,15 +356,15 @@ std::string FieldGeneratorBase::default_value() { case FieldDescriptor::TYPE_BYTES: return GetBytesDefaultValueInternal(); case FieldDescriptor::TYPE_UINT32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SFIXED64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_SINT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SINT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; default: GOOGLE_LOG(FATAL)<< "Unknown field type."; return ""; @@ -361,11 +375,6 @@ std::string FieldGeneratorBase::number() { return SimpleItoa(descriptor_->number()); } -std::string FieldGeneratorBase::message_or_group() { - return - (descriptor_->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; -} - std::string FieldGeneratorBase::capitalized_type_name() { switch (descriptor_->type()) { case FieldDescriptor::TYPE_ENUM: @@ -410,10 +419,6 @@ std::string FieldGeneratorBase::capitalized_type_name() { } } -std::string FieldGeneratorBase::field_ordinal() { - return SimpleItoa(fieldOrdinal_); -} - } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index b1570587..d83543bd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -42,23 +42,23 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class FieldGeneratorBase : public SourceGeneratorBase { public: FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); ~FieldGeneratorBase(); + virtual void GenerateCloningCode(io::Printer* printer) = 0; + virtual void GenerateFreezingCode(io::Printer* printer); + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer) = 0; - virtual void GenerateBuilderMembers(io::Printer* printer) = 0; virtual void GenerateMergingCode(io::Printer* printer) = 0; - virtual void GenerateBuildingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer) = 0; virtual void GenerateSerializationCode(io::Printer* printer) = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; virtual void WriteHash(io::Printer* printer) = 0; virtual void WriteEquals(io::Printer* printer) = 0; + // Currently unused, as we use reflection to generate JSON virtual void WriteToString(io::Printer* printer) = 0; protected: @@ -78,13 +78,13 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string property_name(); std::string name(); std::string type_name(); + std::string type_name(const FieldDescriptor* descriptor); bool has_default_value(); bool is_nullable_type(); std::string default_value(); + std::string default_value(const FieldDescriptor* descriptor); std::string number(); - std::string message_or_group(); std::string capitalized_type_name(); - std::string field_ordinal(); private: void SetCommonFieldVariables(map<string, string>* variables); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 2a416fac..e0a6c83a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -50,7 +50,7 @@ namespace csharp { std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension) { - return GetFileUmbrellaClassname(file) + file_extension; + return GetUmbrellaClassUnqualifiedName(file) + file_extension; } void GenerateFile(const google::protobuf::FileDescriptor* file, @@ -68,6 +68,12 @@ bool Generator::Generate( vector<pair<string, string> > options; ParseGeneratorParameter(parameter, &options); + // We only support proto3 - but we make an exception for descriptor.proto. + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) { + *error = "C# code generation only supports proto3 syntax"; + return false; + } + std::string file_extension = ".cs"; for (int i = 0; i < options.size(); i++) { if (options[i].first == "file_extension") { diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 76e2c850..d25dcba9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -46,11 +46,13 @@ #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_enum_field.h> +#include <google/protobuf/compiler/csharp/csharp_map_field.h> #include <google/protobuf/compiler/csharp/csharp_message_field.h> #include <google/protobuf/compiler/csharp/csharp_primitive_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -112,24 +114,21 @@ std::string GetFileNamespace(const FileDescriptor* descriptor) { if (descriptor->options().has_csharp_namespace()) { return descriptor->options().csharp_namespace(); } - return descriptor->package(); + return UnderscoresToCamelCase(descriptor->package(), true, true); } -std::string GetUmbrellaClassNameInternal(const std::string& proto_file) { +std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor) { + // umbrella_classname can no longer be set using message option. + std::string proto_file = descriptor->name(); int lastslash = proto_file.find_last_of("/"); std::string base = proto_file.substr(lastslash + 1); return UnderscoresToPascalCase(StripDotProto(base)); } -std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { - // umbrella_classname can no longer be set using message option. - return GetUmbrellaClassNameInternal(descriptor->name()); -} - -std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { +std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor) { // TODO(jtattermusch): reintroduce csharp_umbrella_namespace option bool collision = false; - std::string umbrella_classname = GetFileUmbrellaClassname(descriptor); + std::string umbrella_classname = GetUmbrellaClassUnqualifiedName(descriptor); for(int i = 0; i < descriptor->message_type_count(); i++) { if (descriptor->message_type(i)->name() == umbrella_classname) { collision = true; @@ -153,7 +152,8 @@ std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { // TODO(jtattermusch): can we reuse a utility function? std::string UnderscoresToCamelCase(const std::string& input, - bool cap_next_letter) { + bool cap_next_letter, + bool preserve_period) { string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -179,6 +179,9 @@ std::string UnderscoresToCamelCase(const std::string& input, cap_next_letter = true; } else { cap_next_letter = true; + if (input[i] == '.' && preserve_period) { + result += '.'; + } } } // Add a trailing "_" if the name should be altered. @@ -205,30 +208,21 @@ std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { // the C# namespace. classname = name.substr(file->package().size() + 1); } - result += StringReplace(classname, ".", ".Types.", false); + result += StringReplace(classname, ".", ".Types.", true); return "global::" + result; } - - -std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor) { +std::string GetUmbrellaClassName(const FileDescriptor* descriptor) { std::string result = GetFileNamespace(descriptor); if (!result.empty()) { result += '.'; } - result += GetQualifiedUmbrellaClassName(descriptor); - return "global::" + result; -} - -std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor) { - std::string umbrellaNamespace = GetFileUmbrellaNamespace(descriptor); - std::string umbrellaClassname = GetFileUmbrellaClassname(descriptor); - - std::string fullName = umbrellaClassname; + std::string umbrellaNamespace = GetUmbrellaClassNestedNamespace(descriptor); if (!umbrellaNamespace.empty()) { - fullName = umbrellaNamespace + "." + umbrellaClassname; + result += umbrellaNamespace + "."; } - return fullName; + result += GetUmbrellaClassUnqualifiedName(descriptor); + return "global::" + result; } std::string GetClassName(const Descriptor* descriptor) { @@ -257,7 +251,13 @@ std::string GetFieldConstantName(const FieldDescriptor* field) { std::string GetPropertyName(const FieldDescriptor* descriptor) { // TODO(jtattermusch): consider introducing csharp_property_name field option std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); - if (property_name == descriptor->containing_type()->name()) { + // Avoid either our own type name or reserved names. Note that not all names + // are reserved - a field called to_string, write_to etc would still cause a problem. + // There are various ways of ending up with naming collisions, but we try to avoid obvious + // ones. + if (property_name == descriptor->containing_type()->name() + || property_name == "Types" + || property_name == "Descriptor") { property_name += "_"; } return property_name; @@ -344,78 +344,50 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: if (descriptor->is_repeated()) { - return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); + if (descriptor->is_map()) { + return new MapFieldGenerator(descriptor, fieldOrdinal); + } else { + return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); + } } else { - if (descriptor->containing_oneof()) { - return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal); - } + if (IsWrapperType(descriptor)) { + if (descriptor->containing_oneof()) { + return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new WrapperFieldGenerator(descriptor, fieldOrdinal); + } + } else { + if (descriptor->containing_oneof()) { + return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new MessageFieldGenerator(descriptor, fieldOrdinal); + } + } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new EnumFieldGenerator(descriptor, fieldOrdinal); + } } default: if (descriptor->is_repeated()) { return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + } } } } -bool HasRequiredFields(const Descriptor* descriptor, std::set<const Descriptor*>* already_seen) { - if (already_seen->find(descriptor) != already_seen->end()) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(descriptor); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (descriptor->extension_count() > 0) { - return true; - } - - for (int i = 0; i < descriptor->field_count(); i++) { - const FieldDescriptor* field = descriptor->field(i); - if (field->is_required()) { - return true; - } - if (GetCSharpType(field->type()) == CSHARPTYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - return false; -} - -bool HasRequiredFields(const Descriptor* descriptor) { - std::set<const Descriptor*> already_seen; - return HasRequiredFields(descriptor, &already_seen); -} - -} // namespace java +} // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index bc77f43a..278e05f3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -69,15 +69,15 @@ CSharpType GetCSharpType(FieldDescriptor::Type type); std::string StripDotProto(const std::string& proto_file); -std::string GetFileNamespace(const FileDescriptor* descriptor); -std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor); -std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor); +// Gets unqualified name of the umbrella class +std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor); -std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor); - -std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor); +// Gets name of the nested for umbrella class (just the nested part, +// not including the GetFileNamespace part). +std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor); std::string GetClassName(const Descriptor* descriptor); + std::string GetClassName(const EnumDescriptor* descriptor); std::string GetFieldName(const FieldDescriptor* descriptor); @@ -88,7 +88,11 @@ std::string GetPropertyName(const FieldDescriptor* descriptor); int GetFixedSize(FieldDescriptor::Type type); -std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter); +std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period); + +inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) { + return UnderscoresToCamelCase(input, cap_next_letter, false); +} std::string UnderscoresToPascalCase(const std::string& input); @@ -97,12 +101,31 @@ std::string StringToBase64(const std::string& input); std::string FileDescriptorToBase64(const FileDescriptor* descriptor); +uint FixedMakeTag(const FieldDescriptor* descriptor); + FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); -bool HasRequiredFields(const Descriptor* descriptor); +// Determines whether the given message is a map entry message, i.e. one implicitly created +// by protoc due to a map<key, value> field. +inline bool IsMapEntryMessage(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +// Determines whether we're generating code for the proto representation of descriptors etc, +// for use in the runtime. This is the only type which is allowed to use proto2 syntax, +// and it generates internal classes. +inline bool IsDescriptorProto(const FileDescriptor* descriptor) { + // TODO: Do this better! (Currently this depends on a hack in generate_protos.sh to rename + // the file...) + // We need to be able to detect the "normal" name as well, for times that we're just + // depending on descriptor.proto instead of generating it. + return descriptor->name() == "google/protobuf/descriptor_proto_file.proto" + || descriptor->name() == "google/protobuf/descriptor.proto"; +} -inline bool SupportFieldPresence(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; +inline bool IsWrapperType(const FieldDescriptor* descriptor) { + return descriptor->type() == FieldDescriptor::TYPE_MESSAGE && + descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc new file mode 100644 index 00000000..f84ad6f7 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#include <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/strutil.h> + +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_map_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +MapFieldGenerator::~MapFieldGenerator() { +} + +void MapFieldGenerator::GenerateMembers(io::Printer* printer) { + const FieldDescriptor* key_descriptor = + descriptor_->message_type()->FindFieldByName("key"); + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + variables_["key_type_name"] = type_name(key_descriptor); + variables_["value_type_name"] = type_name(value_descriptor); + variables_["true_for_wrappers"] = IsWrapperType(value_descriptor) ? "true" : ""; + scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1)); + scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2)); + + printer->Print( + variables_, + "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n" + " = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec("); + key_generator->GenerateCodecCode(printer); + printer->Print(", "); + value_generator->GenerateCodecCode(printer); + printer->Print( + variables_, + ", $tag$);\n" + "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>($true_for_wrappers$);\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n" + " get { return $name$_; }\n" + "}\n"); +} + +void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.Add(other.$name$_);\n"); +} + +void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n"); +} + +void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.WriteTo(output, _map_$name$_codec);\n"); +} + +void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "size += $name$_.CalculateSize(_map_$name$_codec);\n"); +} + +void MapFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "hash ^= $property_name$.GetHashCode();\n"); +} +void MapFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); +} + +void MapFieldGenerator::WriteToString(io::Printer* printer) { + // TODO: If we ever actually use ToString, we'll need to impleme this... +} + +void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h index f251a21c..f33fe1c3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.h +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -28,8 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ #include <string> @@ -41,32 +41,25 @@ namespace protobuf { namespace compiler { namespace csharp { -class ExtensionGenerator : public FieldGeneratorBase { +class MapFieldGenerator : public FieldGeneratorBase { public: - ExtensionGenerator(const FieldDescriptor* descriptor); - ~ExtensionGenerator(); + MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~MapFieldGenerator(); - void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); - void Generate(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - virtual void GenerateMembers(io::Printer* printer) {}; - virtual void GenerateBuilderMembers(io::Printer* printer) {}; - virtual void GenerateMergingCode(io::Printer* printer) {}; - virtual void GenerateBuildingCode(io::Printer* printer) {}; - virtual void GenerateParsingCode(io::Printer* printer) {}; - virtual void GenerateSerializationCode(io::Printer* printer) {}; - virtual void GenerateSerializedSizeCode(io::Printer* printer) {}; - private: - std::string scope_; - std::string extends_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; } // namespace csharp @@ -74,5 +67,5 @@ class ExtensionGenerator : public FieldGeneratorBase { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 66b87110..a71a7909 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -43,10 +43,10 @@ #include <google/protobuf/wire_format_lite.h> #include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_extension.h> -#include <google/protobuf/compiler/csharp/csharp_message.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_message.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> using google::protobuf::internal::scoped_ptr; @@ -96,197 +96,88 @@ const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() return fields_by_number_; } -/// Get an identifier that uniquely identifies this type within the file. -/// This is used to declare static variables related to this type at the -/// outermost file scope. -std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { - std::string result = descriptor->full_name(); - std::replace(result.begin(), result.end(), '.', '_'); - return "static_" + result; -} - -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the proto-descriptor class. This way, they will be initialized in - // a deterministic order. - - std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - - if (!use_lite_runtime()) { - // The descriptor for this type. - printer->Print( - "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" - "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder> internal__$identifier$__FieldAccessorTable;\n", - "identifier", GetUniqueFileScopeIdentifier(descriptor_), - "full_class_name", full_class_name()); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariables(printer); - } -} - -void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - map<string, string> vars; - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["full_class_name"] = full_class_name(); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = GetUniqueFileScopeIdentifier( - descriptor_->containing_type()); - } - if (!use_lite_runtime()) { - printer->Print(vars, "internal__$identifier$__Descriptor = "); - - if (!descriptor_->containing_type()) { - printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); - } else { - printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); - } - - printer->Print( - vars, - "internal__$identifier$__FieldAccessorTable = \n" - " new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n"); - printer->Print(" new string[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\"$property_name$\", ", - "property_name", GetPropertyName(descriptor_->field(i))); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\"$oneof_name$\", ", - "oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - printer->Print("});\n"); - } - - // Generate static member initializers for all nested types. - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } -} - void MessageGenerator::Generate(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); - vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); printer->Print( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); WriteGeneratedCodeAttributes(printer); printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::$extendable_or_generated$Message$suffix$<$class_name$, $class_name$.Builder> {\n"); + "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); printer->Indent(); + + // All static fields and properties printer->Print( - vars, - "private $class_name$() { }\n" // Private ctor. - // Must call MakeReadOnly() to make sure all lists are made read-only - "private static readonly $class_name$ defaultInstance = new $class_name$().MakeReadOnly();\n"); + vars, + "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n" + "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); - if (optimize_speed()) { - printer->Print( - "private static readonly string[] _$name$FieldNames = " - "new string[] { $slash$$field_names$$slash$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "field_names", JoinStrings(field_names(), "\", \""), - "slash", field_names().size() > 0 ? "\"" : ""); - std::vector<std::string> tags; - for (int i = 0; i < field_names().size(); i++) { - uint32 tag = internal::WireFormat::MakeTag( - descriptor_->FindFieldByName(field_names()[i])); - tags.push_back(SimpleItoa(tag)); - } - printer->Print( - "private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "tags", JoinStrings(tags, ", ")); + // Access the message descriptor via the relevant file descriptor or containing message descriptor. + if (!descriptor_->containing_type()) { + vars["descriptor_accessor"] = GetUmbrellaClassName(descriptor_->file()) + + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]"; + } else { + vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type()) + + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]"; } + printer->Print( vars, - "public static $class_name$ DefaultInstance {\n" - " get { return defaultInstance; }\n" + "public static pbr::MessageDescriptor Descriptor {\n" + " get { return $descriptor_accessor$; }\n" "}\n" "\n" - "public override $class_name$ DefaultInstanceForType {\n" - " get { return DefaultInstance; }\n" + "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" + " get { return Descriptor; }\n" "}\n" - "\n" - "protected override $class_name$ ThisMessage {\n" - " get { return this; }\n" - "}\n\n"); + "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public static pbd::MessageDescriptor Descriptor {\n" - " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" - "}\n" - "\n" - "protected override pb::FieldAccess.FieldAccessorTable<$class_name$, $class_name$.Builder> InternalFieldAccessors {\n" - " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" - "}\n" - "\n"); - } + // Parameterless constructor and partial OnConstruction method. + printer->Print( + vars, + "public $class_name$() {\n" + " OnConstruction();\n" + "}\n\n" + "partial void OnConstruction();\n\n"); - // Extensions don't need to go in an extra nested type - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.Generate(printer); - } + GenerateCloningCode(printer); + GenerateFreezingCode(printer); - if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { - printer->Print("#region Nested types\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print("public static partial class Types {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator enumGenerator(descriptor_->enum_type(i)); - enumGenerator.Generate(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.Generate(printer); - } - printer->Outdent(); - printer->Print("}\n" - "#endregion\n" - "\n"); + // Fields/properties + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + + // Rats: we lose the debug comment here :( + printer->Print( + "public const int $field_constant_name$ = $index$;\n", + "field_constant_name", GetFieldConstantName(fieldDescriptor), + "index", SimpleItoa(fieldDescriptor->number())); + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(fieldDescriptor)); + generator->GenerateMembers(printer); + printer->Print("\n"); } - // oneof + // oneof properties for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + vars["original_name"] = descriptor_->oneof_decl(i)->name(); printer->Print( vars, "private object $name$_;\n" "public enum $property_name$OneofCase {\n"); printer->Indent(); + printer->Print("None = 0,\n"); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print("$field_property_name$ = $index$,\n", "field_property_name", GetPropertyName(field), "index", SimpleItoa(field->number())); } - printer->Print("None = 0,\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( @@ -294,243 +185,192 @@ void MessageGenerator::Generate(io::Printer* printer) { "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" + "}\n\n" + "public void Clear$property_name$() {\n" + " $name$Case_ = $property_name$OneofCase.None;\n" + " $name$_ = null;\n" "}\n\n"); } - // Fields - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + // Standard methods + GenerateFrameworkMethods(printer); + GenerateMessageSerializationMethods(printer); + GenerateMergingMethods(printer); - // Rats: we lose the debug comment here :( - printer->Print( - "public const int $field_constant_name$ = $index$;\n", - "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", SimpleItoa(fieldDescriptor->number())); - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateMembers(printer); - printer->Print("\n"); - } - - if (optimize_speed()) { - if (SupportFieldPresence(descriptor_->file())) { - GenerateIsInitialized(printer); + // Nested messages and enums + if (HasNestedGeneratedTypes()) { + printer->Print("#region Nested types\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Types {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator enumGenerator(descriptor_->enum_type(i)); + enumGenerator.Generate(printer); } - GenerateMessageSerializationMethods(printer); - } - if (use_lite_runtime()) { - GenerateLiteRuntimeMethods(printer); + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // Don't generate nested types for maps... + if (!IsMapEntryMessage(descriptor_->nested_type(i))) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.Generate(printer); + } + } + printer->Outdent(); + printer->Print("}\n" + "#endregion\n" + "\n"); } - GenerateParseFromMethods(printer); - GenerateBuilder(printer); - - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print(vars, "static $class_name$() {\n"); - // We call object.ReferenceEquals() just to make it a valid statement on its own. - // Another option would be GetType(), but that causes problems in DescriptorProtoFile, - // where the bootstrapping is somewhat recursive - type initializers call - // each other, effectively. We temporarily see Descriptor as null. - printer->Print( - vars, - " object.ReferenceEquals($umbrella_class_name$.Descriptor, null);\n" - "}\n"); - printer->Outdent(); printer->Print("}\n"); printer->Print("\n"); +} +// Helper to work out whether we need to generate a class to hold nested types/enums. +// Only tricky because we don't want to generate map entry types. +bool MessageGenerator::HasNestedGeneratedTypes() +{ + if (descriptor_->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (!IsMapEntryMessage(descriptor_->nested_type(i))) { + return true; + } + } + return false; } -void MessageGenerator::GenerateLiteRuntimeMethods(io::Printer* printer) { +void MessageGenerator::GenerateCloningCode(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); - - bool callbase = descriptor_->extension_range_count() > 0; - printer->Print("#region Lite runtime methods\n" - "public override int GetHashCode() {\n"); + printer->Print( + vars, + "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); - printer->Print("int hash = GetType().GetHashCode();\n"); + // Clone non-oneof fields first for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { + if (!descriptor_->field(i)->containing_oneof()) { scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(field)); - generator->WriteHash(printer); + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateCloningCode(printer); } } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "if ($name$Case_ != $property_name$OneofCase.None) {\n" - " hash ^= $name$_.GetHashCode();\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - if (callbase) { - printer->Print("hash ^= base.GetHashCode();\n"); + // Clone just the right field for each oneof + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field)); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$:\n"); + printer->Indent(); + generator->GenerateCloningCode(printer); + printer->Print("break;\n"); + printer->Outdent(); + } + printer->Outdent(); + printer->Print("}\n\n"); } - printer->Print("return hash;\n"); + printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); + printer->Print("}\n\n"); - printer->Print("public override bool Equals(object obj) {\n"); - printer->Indent(); printer->Print( vars, - "$class_name$ other = obj as $class_name$;\n" - "if (other == null) return false;\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(printer); - } - if (callbase) { - printer->Print("if (!base.Equals(other)) return false;\n"); - } - printer->Print("return true;\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); + "public $class_name$ Clone() {\n" + " return new $class_name$(this);\n" + "}\n\n"); +} - printer->Print( - "public override void PrintTo(global::System.IO.TextWriter writer) {\n"); - printer->Indent(); +void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { +} - for (int i = 0; i < fields_by_number().size(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->WriteToString(printer); - } +void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); - if (callbase) { - printer->Print("base.PrintTo(writer);\n"); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n"); - printer->Print("\n"); -} + // Equality + printer->Print( + vars, + "public override bool Equals(object other) {\n" + " return Equals(other as $class_name$);\n" + "}\n\n" + "public bool Equals($class_name$ other) {\n" + " if (ReferenceEquals(other, null)) {\n" + " return false;\n" + " }\n" + " if (ReferenceEquals(other, this)) {\n" + " return true;\n" + " }\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(printer); + } + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n\n"); + + // GetHashCode + // Start with a non-zero value to easily distinguish between null and "empty" messages. + printer->Print( + "public override int GetHashCode() {\n" + " int hash = 1;\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(printer); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n\n"); -bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, - const Descriptor::ExtensionRange* r2) { - return r1->start < r2->start; + printer->Print( + "public override string ToString() {\n" + " return pb::JsonFormatter.Default.Format(this);\n" + "}\n\n"); } void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { - std::vector<const Descriptor::ExtensionRange*> extension_ranges_sorted; - for (int i = 0; i < descriptor_->extension_range_count(); i++) { - extension_ranges_sorted.push_back(descriptor_->extension_range(i)); - } - std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), - CompareExtensionRangesStart); - printer->Print( - "public override void WriteTo(pb::ICodedOutputStream output) {\n"); + "public void WriteTo(pb::CodedOutputStream output) {\n"); printer->Indent(); - // Make sure we've computed the serialized length, so that packed fields are generated correctly. - printer->Print("CalcSerializedSize();\n" - "string[] field_names = _$class_name$FieldNames;\n", - "class_name", UnderscoresToCamelCase(class_name(), false)); - if (descriptor_->extension_range_count()) { - printer->Print( - "pb::ExtendableMessage$runtime_suffix$<$class_name$, $class_name$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\n", - "class_name", class_name(), - "runtime_suffix", runtime_suffix()); - } - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0, j = 0; - i < fields_by_number().size() || j < extension_ranges_sorted.size();) { - if (i == fields_by_number().size()) { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } else if (j == extension_ranges_sorted.size()) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else if (fields_by_number()[i]->number() - < extension_ranges_sorted[j]->start) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } - } - - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) - { - printer->Print("UnknownFields.WriteAsMessageSetTo(output);\n"); - } else { - printer->Print("UnknownFields.WriteTo(output);\n"); - } + // Serialize all the fields + for (int i = 0; i < fields_by_number().size(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->GenerateSerializationCode(printer); } + // TODO(jonskeet): Memoize size of frozen messages? printer->Outdent(); printer->Print( "}\n" "\n" - "private int memoizedSerializedSize = -1;\n" - "public override int SerializedSize {\n"); + "public int CalculateSize() {\n"); printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "return CalcSerializedSize();\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - - printer->Print("private int CalcSerializedSize() {\n"); - printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "\n" - "size = 0;\n"); + printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->GenerateSerializedSizeCode(printer); } - if (descriptor_->extension_range_count() > 0) { - printer->Print("size += ExtensionsSerializedSize;\n"); - } - - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print("size += UnknownFields.SerializedSizeAsMessageSet;\n"); - } else { - printer->Print("size += UnknownFields.SerializedSize;\n"); - } - } - printer->Print( - "memoizedSerializedSize = size;\n" - "return size;\n"); + printer->Print("return size;\n"); printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* fieldDescriptor) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateSerializationCode(printer); -} - -void MessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extensionRange) { - printer->Print("extensionWriter.WriteUntil($range_end$, output);\n", - "range_end", SimpleItoa(extensionRange->end)); + printer->Print("}\n\n"); } -void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { +void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. @@ -539,346 +379,65 @@ void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { printer->Print( vars, - "public static $class_name$ ParseFrom(pb::ByteString data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input) {\n" - " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n"); -} - -void MessageGenerator::GenerateBuilder(io::Printer* printer) { - map<string, string> vars; - vars["class_name"] = class_name(); - vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); - - printer->Print(vars, "private $class_name$ MakeReadOnly() {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateBuildingCode(printer); - } - printer->Print("return this;\n"); - printer->Outdent(); - printer->Print("}\n\n"); - - printer->Print( - vars, - "public static Builder CreateBuilder() { return new Builder(); }\n" - "public override Builder ToBuilder() { return CreateBuilder(this); }\n" - "public override Builder CreateBuilderForType() { return new Builder(); }\n" - "public static Builder CreateBuilder($class_name$ prototype) {\n" - " return new Builder(prototype);\n" - "}\n" - "\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "$access_level$ sealed partial class Builder : pb::$extendable_or_generated$Builder$suffix$<$class_name$, Builder> {\n"); + "public void MergeFrom($class_name$ other) {\n"); printer->Indent(); printer->Print( - "protected override Builder ThisBuilder {\n" - " get { return this; }\n" + "if (other == null) {\n" + " return;\n" "}\n"); - GenerateCommonBuilderMethods(printer); - if (optimize_speed()) { - GenerateBuilderParsingMethods(printer); - } + // Merge non-oneof fields for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - printer->Print("\n"); - // No field comment :( - generator->GenerateBuilderMembers(printer); - } - - // oneof - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\n"); - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "public $property_name$OneofCase $property_name$Case {\n" - " get { return result.$name$Case_; }\n" - "}\n" - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_ = null;\n" - " result.$name$Case_ = $property_name$OneofCase.None;\n" - " return this;\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { - map<string, string> vars; - vars["class_name"] = class_name(); - vars["full_class_name"] = full_class_name(); - vars["suffix"] = runtime_suffix(); - - printer->Print( - vars, - //default constructor - "public Builder() {\n" - //Durring static initialization of message, DefaultInstance is expected to return null. - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - "}\n" - //clone constructor - "internal Builder($class_name$ cloneFrom) {\n" - " result = cloneFrom;\n" - " resultIsReadOnly = true;\n" - "}\n" - "\n" - "private bool resultIsReadOnly;\n" - "private $class_name$ result;\n" - "\n" - "private $class_name$ PrepareBuilder() {\n" - " if (resultIsReadOnly) {\n" - " $class_name$ original = result;\n" - " result = new $class_name$();\n" - " resultIsReadOnly = false;\n" - " MergeFrom(original);\n" - " }\n" - " return result;\n" - "}\n" - "\n" - "public override bool IsInitialized {\n" - " get { return result.IsInitialized; }\n" - "}\n" - "\n" - "protected override $class_name$ MessageBeingBuilt {\n" - " get { return PrepareBuilder(); }\n" - "}\n" - "\n"); - //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break - printer->Print( - "public override Builder Clear() {\n" - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - " return this;\n" - "}\n" - "\n" - "public override Builder Clone() {\n" - " if (resultIsReadOnly) {\n" - " return new Builder(result);\n" - " } else {\n" - " return new Builder().MergeFrom(result);\n" - " }\n" - "}\n" - "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public override pbd::MessageDescriptor DescriptorForType {\n" - " get { return $full_class_name$.Descriptor; }\n" - "}\n\n"); + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateMergingCode(printer); + } } - printer->Print( - vars, - "public override $class_name$ DefaultInstanceForType {\n" - " get { return $full_class_name$.DefaultInstance; }\n" - "}\n\n"); - - printer->Print( - vars, - "public override $class_name$ BuildPartial() {\n" - " if (resultIsReadOnly) {\n" - " return result;\n" - " }\n" - " resultIsReadOnly = true;\n" - " return result.MakeReadOnly();\n" - "}\n\n"); - - if (optimize_speed()) { - printer->Print( - vars, - "public override Builder MergeFrom(pb::IMessage$suffix$ other) {\n" - " if (other is $class_name$) {\n" - " return MergeFrom(($class_name$) other);\n" - " } else {\n" - " base.MergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n\n"); - - printer->Print(vars,"public override Builder MergeFrom($class_name$ other) {\n"); - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. + // Merge oneof fields + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - printer->Print( - vars, - "if (other == $full_class_name$.DefaultInstance) return this;\n" - "PrepareBuilder();\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(printer); - } - } - - // Merge oneof fields - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print(vars, "switch (other.$property_name$Case) {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - vars["field_property_name"] = GetPropertyName(field); - printer->Print( - vars, - "case $property_name$OneofCase.$field_property_name$: {\n"); - if (field->type() == FieldDescriptor::TYPE_GROUP || - field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print( - vars, - " Merge$field_property_name$(other.$field_property_name$);\n"); - } else { - printer->Print( - vars, - " Set$field_property_name$(other.$field_property_name$);\n"); - } - printer->Print(" break;\n"); - printer->Print("}\n"); - } - printer->Print(vars, "case $property_name$OneofCase.None: { break; }\n"); - printer->Outdent(); - printer->Print("}\n"); - } - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print(" this.MergeExtensionFields(other);\n"); - } - if (!use_lite_runtime()) { - printer->Print("this.MergeUnknownFields(other.UnknownFields);\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$:\n" + " $field_property_name$ = other.$field_property_name$;\n" + " break;\n"); } - printer->Print("return this;\n"); printer->Outdent(); printer->Print("}\n\n"); } - -} - -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input) {\n" - " return MergeFrom(input, pb::ExtensionRegistry.Empty);\n" - "}\n\n"); - - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n"); + printer->Outdent(); + printer->Print("}\n\n"); + printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n"); printer->Indent(); - printer->Print("PrepareBuilder();\n"); - if (!use_lite_runtime()) { - printer->Print("pb::UnknownFieldSet.Builder unknownFields = null;\n"); - } printer->Print( "uint tag;\n" - "string field_name;\n" - "while (input.ReadTag(out tag, out field_name)) {\n"); + "while ((tag = input.ReadTag()) != 0) {\n" + " switch(tag) {\n"); printer->Indent(); - printer->Print("if(tag == 0 && field_name != null) {\n"); printer->Indent(); - //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change printer->Print( - "int field_ordinal = global::System.Array.BinarySearch(_$camel_class_name$FieldNames, field_name, global::System.StringComparer.Ordinal);\n" - "if(field_ordinal >= 0)\n" - " tag = _$camel_class_name$FieldTags[field_ordinal];\n" - "else {\n", - "camel_class_name", UnderscoresToCamelCase(class_name(), false)); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } - printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" continue;\n"); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - - printer->Print("switch (tag) {\n"); - printer->Indent(); - printer->Print( - "case 0: {\n" // 0 signals EOF / limit reached - " throw pb::InvalidProtocolBufferException.InvalidTag();\n" - "}\n" - "default: {\n" - " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - " }\n"); - } - printer->Print( - " return this;\n" // it's an endgroup tag - " }\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } - printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" break;\n"); - printer->Print("}\n"); - + "default:\n" + " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it. + " break;\n"); for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); - if (field->is_repeated() - && (wt == internal::WireFormatLite::WIRETYPE_VARINT - || wt == internal::WireFormatLite::WIRETYPE_FIXED32 - || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { + // Handle both packed and unpacked repeated fields with the same Read*Array call; + // the two generated cases are the packed and unpacked tags. + // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }. + // It looks like it is... + if (field->is_packable()) { printer->Print( - "case $number$:\n", - "number", + "case $packed_tag$:\n", + "packed_tag", SimpleItoa( internal::WireFormatLite::MakeTag( field->number(), @@ -894,95 +453,12 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); } - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - if (!use_lite_runtime()) { - printer->Print( - "if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - "}\n"); - } - printer->Print("return this;\n"); - printer->Outdent(); - printer->Print("}\n\n"); -} - -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { - printer->Print("public override bool IsInitialized {\n"); - printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - if (descriptor_->field(i)->is_required()) { - printer->Print("if (!has$property_name$) return false;\n", - "property_name", GetPropertyName(descriptor_->field(i))); - } - } - - // Now check that all embedded messages are initialized. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (field->type() != FieldDescriptor::TYPE_MESSAGE || - !HasRequiredFields(field->message_type())) - { - continue; - } - // TODO(jtattermusch): shouldn't we use GetPropertyName here? - string propertyName = UnderscoresToPascalCase(GetFieldName(field)); - if (field->is_repeated()) - { - printer->Print( - "foreach ($class_name$ element in $property_name$List) {\n" - " if (!element.IsInitialized) return false;\n" - "}\n", - "class_name", GetClassName(field->message_type()), - "property_name", propertyName); - } - else if (field->is_optional()) - { - printer->Print( - "if (Has$property_name$) {\n" - " if (!$property_name$.IsInitialized) return false;\n" - "}\n", - "property_name", propertyName); - } - else - { - printer->Print( - "if (!$property_name$.IsInitialized) return false;\n", - "property_name", propertyName); - } - } - - if (descriptor_->extension_range_count() > 0) { - printer->Print("if (!ExtensionsAreInitialized) return false;\n"); - } - printer->Print("return true;\n"); + printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n"); + printer->Print("}\n"); // while printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); -} - -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } + printer->Print("}\n\n"); // method } int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index ebe58618..f0c49ac9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -43,7 +43,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; class FieldGeneratorBase; class MessageGenerator : public SourceGeneratorBase { @@ -51,9 +50,9 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariables(io::Printer* printer); - void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); + void GenerateCloningCode(io::Printer* printer); + void GenerateFreezingCode(io::Printer* printer); + void GenerateFrameworkMethods(io::Printer* printer); void Generate(io::Printer* printer); private: @@ -61,22 +60,15 @@ class MessageGenerator : public SourceGeneratorBase { std::vector<std::string> field_names_; std::vector<const FieldDescriptor*> fields_by_number_; - void GenerateLiteRuntimeMethods(io::Printer* printer); void GenerateMessageSerializationMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* fieldDescriptor); - void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extendsionRange); - void GenerateParseFromMethods(io::Printer* printer); - void GenerateBuilder(io::Printer* printer); - void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateMergingMethods(io::Printer* printer); int GetFieldOrdinal(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( const FieldDescriptor* descriptor); + bool HasNestedGeneratedTypes(); + std::string class_name(); std::string full_class_name(); @@ -95,4 +87,3 @@ class MessageGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 50eb9df6..4f576cd1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,8 +49,8 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["has_property_check"] = "has" + property_name(); - variables_["message_or_group"] = message_or_group(); + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; } MessageFieldGenerator::~MessageFieldGenerator() { @@ -60,125 +60,45 @@ MessageFieldGenerator::~MessageFieldGenerator() { void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private bool has$property_name$;\n" "private $type_name$ $name$_;\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return $name$_ ?? $default_value$; }\n" - "}\n"); -} - -void MessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.has$property_name$ &&\n" - " result.$name$_ != $default_value$) {\n" - " result.$name$_ = $type_name$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$name$_ = value;\n" + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n" + " $name$_ = value;\n" " }\n" - " result.has$property_name$ = true;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.has$property_name$ = false;\n" - " result.$name$_ = null;\n" - " return this;\n" "}\n"); } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.Has$property_name$) {\n" - " Merge$property_name$(other.$property_name$);\n" + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check$) {\n" + " $name$_ = new $type_name$();\n" + " }\n" + " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); } -void MessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do for singular fields -} - void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.has$property_name$) {\n" - " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "$property_name$ = subBuilder.BuildPartial();\n"); + "if ($has_not_property_check$) {\n" + " $name$_ = new $type_name$();\n" + "}\n" + // TODO(jonskeet): Do we really need merging behaviour like this? + "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteMessage($property_name$);\n" "}\n"); } @@ -186,19 +106,19 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" "}\n"); } void MessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$) hash ^= $name$_.GetHashCode();\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); + "if (!object.Equals($property_name$, other.$property_name$)) return false;\n"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -207,6 +127,20 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } +void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); +} + +void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + +void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); +} + MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : MessageFieldGenerator(descriptor, fieldOrdinal) { @@ -218,124 +152,41 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { } void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void MessageOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" - "}\n"); - } AddDeprecatedFlag(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.$has_property_check$ &&\n" - " result.$property_name$ != $default_value$) {\n" - " result.$oneof_name$_ = $type_name$.CreateBuilder(result.$property_name$).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$oneof_name$_ = value;\n" - " }\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " if (result.$has_property_check$) {\n" - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " result.$oneof_name$_ = null;\n" + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" - " return this;\n" "}\n"); } void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): We may be able to do better than this printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.$has_property_check$) {\n" + "$type_name$ subBuilder = new $type_name$();\n" + "if ($has_property_check$) {\n" " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "result.$oneof_name$_ = subBuilder.BuildPartial();\n" - "result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); + "}\n" + "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP + "$property_name$ = subBuilder;\n"); } -void MessageOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } +void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$.Clone();\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index d820908c..dc6e4dc5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -41,17 +41,16 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class MessageFieldGenerator : public FieldGeneratorBase { public: MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -69,9 +68,8 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageOneofFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.h b/src/google/protobuf/compiler/csharp/csharp_names.h index 26c59b31..ccd2e720 100644 --- a/src/google/protobuf/compiler/csharp/csharp_writer.h +++ b/src/google/protobuf/compiler/csharp/csharp_names.h @@ -31,63 +31,52 @@ // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +// +// Provides a mechanism for mapping a descriptor to the +// fully-qualified name of the corresponding C# class. -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ #include <string> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { -namespace compiler { -namespace csharp { - -// Simple wrapper around Printer that supports customizable line endings -// and number-based variables (e.g. $0$). -class Writer { - public: - Writer(io::Printer* printer); - ~Writer(); - - void Indent(); - void Outdent(); - - void Write(const char* text); - - void Write(const char* text, const string& value0); - - void Write(const char* text, const string& value0, const string& value1); - - void Write(const char* text, const string& value0, const string& value1, - const string& value2); - void Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); +class Descriptor; +class EnumDescriptor; +class FileDescriptor; +class ServiceDescriptor; - void WriteLine(); - - void WriteLine(const char* text); - - void WriteLine(const char* text, const string& value0); +namespace compiler { +namespace csharp { - void WriteLine(const char* text, const string& value0, const string& value1); +// Requires: +// descriptor != NULL +// +// Returns: +// The namespace to use for given file descriptor. +string GetFileNamespace(const FileDescriptor* descriptor); - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2); +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified C# class name. +string GetClassName(const Descriptor* descriptor); - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); - private: - io::Printer* printer_; - const char* newline_; -}; +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified name of the C# class that provides +// access to the file descriptor. Proto compiler generates +// such class for each .proto file processed. +std::string GetUmbrellaClassName(const FileDescriptor* descriptor); } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 652eb6b9..fc043ec0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -49,81 +49,42 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + // TODO(jonskeet): Make this cleaner... + is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING + && descriptor->type() != FieldDescriptor::TYPE_BYTES; + if (!is_value_type) { + variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; + variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; + } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { - } void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, "private bool has$property_name$;\n"); - } + // TODO(jonskeet): Work out whether we want to prevent the fields from ever being + // null, or whether we just handle it, in the cases of bytes and string. + // (Basically, should null-handling code be in the getter or the setter?) printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" + "$access_level$ $type_name$ $property_name$ {\n" " get { return $name$_; }\n" - "}\n"); -} - -void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { + " set {\n"); + if (is_value_type) { printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print(" PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print( - variables_, - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { + " $name$_ = value;\n"); + } else { printer->Print( variables_, - " result.has$property_name$ = false;\n"); + " $name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n"); } printer->Print( - variables_, - " result.$name$_ = $default_value$;\n" - " return this;\n" + " }\n" "}\n"); } @@ -135,60 +96,68 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { "}\n"); } -void PrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do here for primitive types -} - void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "result.has$property_name$ = input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } else { - printer->Print( - variables_, - "input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } + // Note: invoke the property setter rather than writing straight to the field, + // so that we can normalize "null to empty" for strings and bytes. + printer->Print( + variables_, + "$property_name$ = input.Read$capitalized_type_name$();\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$capitalized_type_name$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.Write$capitalized_type_name$($property_name$);\n" "}\n"); } void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n"); + printer->Indent(); + int fixedSize = GetFixedSize(descriptor_->type()); + if (fixedSize == -1) { + printer->Print( + variables_, + "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n"); + } else { + printer->Print( + "size += $tag_size$ + $fixed_size$;\n", + "fixed_size", SimpleItoa(fixedSize), + "tag_size", variables_["tag_size"]); + } + printer->Outdent(); + printer->Print("}\n"); } void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " hash ^= $name$_.GetHashCode();\n" - "}\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); - } else { - printer->Print( - variables_, - "if (!$name$_.Equals(other.$name$_)) return false;\n"); - } + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); } void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, - "PrintField(\"$descriptor_name$\", $has_property_check$, $name$_, writer);\n"); + "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n"); +} + +void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_;\n"); +} + +void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.For$capitalized_type_name$($tag$)"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( @@ -202,79 +171,41 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" + "$access_level$ $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { + " set {\n"); + if (is_value_type) { + printer->Print( + variables_, + " $oneof_name$_ = value;\n"); + } else { + printer->Print( + variables_, + " $oneof_name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n"); + } printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " if (result.$has_property_check$) {\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " }\n" - " return this;\n" - "}\n"); } -void PrimitiveOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { - printer->Print( - variables_, - "$type_name$ value = $default_value$;\n" - "if (input.Read$capitalized_type_name$(ref value)) {\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "}\n"); + printer->Print( + variables_, + "$property_name$ = input.Read$capitalized_type_name$();\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$;\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index 8a2d5020..8b87ebc4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class PrimitiveFieldGenerator : public FieldGeneratorBase { public: PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -60,6 +58,9 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); + protected: + bool is_value_type; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; @@ -69,9 +70,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveOneofFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index f5ebcfb1..625631df 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -56,187 +56,54 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { } void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } - printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n"); printer->Print(variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "scg::ICollection<object> unknownItems;\n" - "input.ReadEnumArray<$type_name$>(tag, field_name, result.$name$_, out unknownItems);\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - "if (unknownItems != null) {\n" - " if (unknownFields == null) {\n" - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " foreach (object rawValue in unknownItems)\n" - " if (rawValue is int)\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)rawValue);\n" - "}\n"); - } + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); - if (descriptor_->is_packed()) { - printer->Print( - variables_, - "output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); - } else { - printer->Print(variables_, - "output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n"); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { - printer->Print("{\n"); - printer->Indent(); printer->Print( variables_, - "int dataSize = 0;\n" - "if ($name$_.Count > 0) {\n"); - printer->Indent(); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); +} + +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" - "}\n" - "size += dataSize;\n"); - int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - if (descriptor_->is_packed()) { - printer->Print( - "size += $tag_size$;\n" - "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", - "tag_size", SimpleItoa(tagSize)); - } else { - printer->Print( - "size += $tag_size$ * $name$_.Count;\n", - "tag_size", SimpleItoa(tagSize), "name", name()); - } - printer->Outdent(); - printer->Print("}\n"); - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } - printer->Outdent(); - printer->Print("}\n"); + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { @@ -244,6 +111,14 @@ void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } +void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 68c3d6c9..ee50eef0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -41,17 +41,17 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - +// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We +// should probably have a RepeatedFieldGeneratorBase. class RepeatedEnumFieldGenerator : public FieldGeneratorBase { public: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedEnumFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2ae1d579..7fbab681 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -39,6 +39,8 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -48,7 +50,6 @@ namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["message_or_group"] = message_or_group(); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { @@ -58,162 +59,66 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return $name$_; }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = "); + // Don't want to duplicate the codec code here... maybe we should have a + // "create single field generator for this repeated field" + // function, but it doesn't seem worth it for just this. + if (IsWrapperType(descriptor_)) { + scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } else { + scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } + printer->Print(";\n"); printer->Print( variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(builderForValue.Build());\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$message_or_group$Array(tag, field_name, result.$name$_, $type_name$.DefaultInstance, extensionRegistry);\n"); + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, - "if ($name$_.Count > 0) {\n" - " output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n" - "}\n"); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "foreach ($type_name$ element in $property_name$List) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n" - "}\n"); + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } + void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } + void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); printer->Print( @@ -221,6 +126,14 @@ void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$field_name$\", $name$_, writer);\n"); } +void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 9db76939..cf601c7e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedMessageFieldGenerator : public FieldGeneratorBase { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedMessageFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index e27458bb..1163ce73 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -56,183 +56,67 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { } void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } - printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = pb::FieldCodec.For$capitalized_type_name$($tag$);\n"); + printer->Print(variables_, + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); +} - AddPublicMemberAttributes(printer); +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); + "$name$_.Add(other.$name$_);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" - "}\n"); + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { +void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { - printer->Print(variables_, - "input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( - io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); - if (descriptor_->is_packed()) { - printer->Print(variables_, - "output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); - } else { - printer->Print(variables_, - "output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n"); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( - io::Printer* printer) { - printer->Print("{\n"); - printer->Indent(); - printer->Print("int dataSize = 0;\n"); - int fixedSize = GetFixedSize(descriptor_->type()); - if (fixedSize == -1) { - printer->Print( - variables_, - "foreach ($type_name$ element in $property_name$List) {\n" - " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" - "}\n"); - } else { - printer->Print( - "dataSize = $size$ * $name$_.Count;\n", - "size", SimpleItoa(fixedSize), "name", name()); - } - printer->Print("size += dataSize;\n"); - int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - if (descriptor_->is_packed()) { - printer->Print( - "if ($name$_.Count != 0) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n" - "}\n", - "name", name(), "tag_size", SimpleItoa(tagSize)); - } else { - printer->Print( - "size += $tag_size$ * $name$_.Count;\n", - "tag_size", SimpleItoa(tagSize), "name", name()); - } - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); - } - printer->Outdent(); - printer->Print("}\n"); +void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } +void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 50af9dda..f1ceeb50 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { public: RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedPrimitiveFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index c52f6092..735d164a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -47,14 +47,6 @@ namespace csharp { SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) : descriptor_(descriptor) { - optimizeSize_ = (descriptor->options().optimize_for() - == FileOptions::CODE_SIZE); - optimizeSpeed_ = (descriptor->options().optimize_for() == FileOptions::SPEED); - useLiteRuntime_ = (descriptor->options().optimize_for() - == FileOptions::LITE_RUNTIME); - - optimizeSpeed_ |= useLiteRuntime_; - runtimeSuffix_ = useLiteRuntime_ ? "Lite" : ""; } SourceGeneratorBase::~SourceGeneratorBase() { @@ -65,7 +57,7 @@ void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) { } std::string SourceGeneratorBase::class_access_level() { - return "public"; // public_classes is always on. + return IsDescriptorProto(descriptor_) ? "internal" : "public"; // public_classes is always on. } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 61c19511..6caef171 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -47,27 +47,10 @@ class SourceGeneratorBase { std::string class_access_level(); - bool optimize_size() { - return optimizeSize_; - } - bool optimize_speed() { - return optimizeSpeed_; - } - bool use_lite_runtime() { - return useLiteRuntime_; - } - std::string runtime_suffix() { - return runtimeSuffix_; - } - void WriteGeneratedCodeAttributes(io::Printer* printer); private: const FileDescriptor* descriptor_; - bool optimizeSize_; - bool optimizeSpeed_; - bool useLiteRuntime_; - std::string runtimeSuffix_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase); }; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index b14bf5e8..399c64e1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -36,12 +36,14 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/strutil.h> + -#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h> #include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_extension.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_message.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> +#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h> namespace google { namespace protobuf { @@ -52,8 +54,8 @@ UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file) : SourceGeneratorBase(file), file_(file) { namespace_ = GetFileNamespace(file); - umbrellaClassname_ = GetFileUmbrellaClassname(file); - umbrellaNamespace_ = GetFileUmbrellaNamespace(file); + umbrellaClassname_ = GetUmbrellaClassUnqualifiedName(file); + umbrellaNamespace_ = GetUmbrellaClassNestedNamespace(file); } UmbrellaClassGenerator::~UmbrellaClassGenerator() { @@ -61,30 +63,8 @@ UmbrellaClassGenerator::~UmbrellaClassGenerator() { void UmbrellaClassGenerator::Generate(io::Printer* printer) { WriteIntroduction(printer); - WriteExtensionRegistration(printer); - // write children: Extensions - if (file_->extension_count() > 0) { - printer->Print("#region Extensions\n"); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.Generate(printer); - } - printer->Print("#endregion\n"); - printer->Print("\n"); - } - - printer->Print("#region Static variables\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariables(printer); - } - printer->Print("#endregion\n"); - if (!use_lite_runtime()) { - WriteDescriptor(printer); - } else { - WriteLiteExtensions(printer); - } + WriteDescriptor(printer); // Close the class declaration. printer->Outdent(); printer->Print("}\n"); @@ -134,9 +114,9 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { "#pragma warning disable 1591, 0612, 3021\n" "#region Designer generated code\n" "\n" - "using pb = global::Google.ProtocolBuffers;\n" - "using pbc = global::Google.ProtocolBuffers.Collections;\n" - "using pbd = global::Google.ProtocolBuffers.Descriptors;\n" + "using pb = global::Google.Protobuf;\n" + "using pbc = global::Google.Protobuf.Collections;\n" + "using pbr = global::Google.Protobuf.Reflection;\n" "using scg = global::System.Collections.Generic;\n", "file_name", file_->name()); @@ -165,31 +145,13 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { printer->Indent(); } -void UmbrellaClassGenerator::WriteExtensionRegistration(io::Printer* printer) { - printer->Print( - "#region Extension registration\n" - "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {\n"); - printer->Indent(); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n"); -} - void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print( "#region Descriptor\n" - "public static pbd::FileDescriptor Descriptor {\n" + "public static pbr::FileDescriptor Descriptor {\n" " get { return descriptor; }\n" "}\n" - "private static pbd::FileDescriptor descriptor;\n" + "private static pbr::FileDescriptor descriptor;\n" "\n" "static $umbrella_class_name$() {\n", "umbrella_class_name", umbrellaClassname_); @@ -207,82 +169,131 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60)); base64 = base64.substr(60); } - printer->Outdent(); printer->Print("\"$base64$\"));\n", "base64", base64); printer->Outdent(); printer->Outdent(); - printer->Print( - "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {\n"); - printer->Indent(); - printer->Print("descriptor = root;\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } - - if (uses_extensions()) { - // Must construct an ExtensionRegistry containing all possible extensions - // and return it. - printer->Print( - "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();\n"); - printer->Print("RegisterAllExtensions(registry);\n"); - for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print("$dependency$.RegisterAllExtensions(registry);\n", - "dependency", GetFullUmbrellaClassName(file_->dependency(i))); - } - printer->Print("return registry;\n"); - } else { - printer->Print("return null;\n"); - } printer->Outdent(); - printer->Print("};\n"); // ----------------------------------------------------------------- - // Invoke internalBuildGeneratedFileFrom() to build the file. + // Invoke InternalBuildGeneratedFileFrom() to build the file. printer->Print( - "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); - printer->Print(" new pbd::FileDescriptor[] {\n"); + "descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); + printer->Print(" new pbr::FileDescriptor[] { "); for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print( - " $full_umbrella_class_name$.Descriptor, \n", + // descriptor.proto is special: we don't allow access to the generated code, but there's + // a separately-exposed property to get at the file descriptor, specifically to allow this + // kind of dependency. + if (IsDescriptorProto(file_->dependency(i))) { + printer->Print("pbr::FileDescriptor.DescriptorProtoFileDescriptor, "); + } else { + printer->Print( + "$full_umbrella_class_name$.Descriptor, ", "full_umbrella_class_name", - GetFullUmbrellaClassName(file_->dependency(i))); + GetUmbrellaClassName(file_->dependency(i))); + } + } + printer->Print("},\n" + " new pbr::GeneratedCodeInfo("); + // Specify all the generated code information, recursively. + if (file_->enum_type_count() > 0) { + printer->Print("new[] {"); + for (int i = 0; i < file_->enum_type_count(); i++) { + printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i))); + } + printer->Print("}, "); + } + else { + printer->Print("null, "); + } + if (file_->message_type_count() > 0) { + printer->Print("new pbr::GeneratedCodeInfo[] {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1); + } + printer->Outdent(); + printer->Print("\n}));\n"); + printer->Outdent(); + printer->Outdent(); + } + else { + printer->Print("null));\n"); } - printer->Print(" }, assigner);\n"); + printer->Outdent(); printer->Print("}\n"); printer->Print("#endregion\n\n"); } -void UmbrellaClassGenerator::WriteLiteExtensions(io::Printer* printer) { - printer->Print( - "#region Extensions\n" - "internal static readonly object Descriptor;\n" - "static $umbrella_class_name$() {\n", - "umbrella_class_name", umbrellaClassname_); - printer->Indent(); - printer->Print("Descriptor = null;\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); +// Write out the generated code for a particular message. This consists of the CLR type, property names +// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part +// can be specified as null if it would be empty, to make the generated code somewhat simpler to read. +// We write a line break at the end of each generated code info, so that in the final file we'll see all +// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual, +// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to +// read even with multiple levels of nesting. +// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate +// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively +// just controlling the formatting in the generated code. +void UmbrellaClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) { + if (IsMapEntryMessage(descriptor)) { + printer->Print("null, "); + return; } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); + // Generated message type + printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor)); + + // Fields + if (descriptor->field_count() > 0) { + std::vector<std::string> fields; + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(GetPropertyName(descriptor->field(i))); + } + printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \"")); + } + else { + printer->Print("null, "); + } + + // Oneofs + if (descriptor->oneof_decl_count() > 0) { + std::vector<std::string> oneofs; + for (int i = 0; i < descriptor->oneof_decl_count(); i++) { + oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); + } + printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \"")); + } + else { + printer->Print("null, "); + } + + // Nested enums + if (descriptor->enum_type_count() > 0) { + std::vector<std::string> enums; + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enums.push_back(GetClassName(descriptor->enum_type(i))); + } + printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof(")); + } + else { + printer->Print("null, "); } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n\n"); -} -bool UmbrellaClassGenerator::uses_extensions() { - // TODO(jtattermusch): implement recursive descent that looks for extensions. - // For now, we conservatively assume that extensions are used. - return true; + // Nested types + if (descriptor->nested_type_count() > 0) { + // Need to specify array type explicitly here, as all elements may be null. + printer->Print("new pbr::GeneratedCodeInfo[] { "); + for (int i = 0; i < descriptor->nested_type_count(); i++) { + WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1); + } + printer->Print("}"); + } + else { + printer->Print("null"); + } + printer->Print(last ? ")" : "),\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h index 83e1f347..b8bd2133 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -41,8 +41,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class UmbrellaClassGenerator : public SourceGeneratorBase { public: UmbrellaClassGenerator(const FileDescriptor* file); @@ -58,11 +56,8 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { std::string umbrellaNamespace_; void WriteIntroduction(io::Printer* printer); - void WriteExtensionRegistration(io::Printer* printer); void WriteDescriptor(io::Printer* printer); - void WriteLiteExtensions(io::Printer* printer); - - bool uses_extensions(); + void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator); }; @@ -73,4 +68,3 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc new file mode 100644 index 00000000..44f832bf --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -0,0 +1,207 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#include <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> + +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && + wrapped_field->type() != FieldDescriptor::TYPE_BYTES; + if (is_value_type) { + variables_["nonnullable_type_name"] = type_name(wrapped_field); + } +} + +WrapperFieldGenerator::~WrapperFieldGenerator() { +} + +void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print( + variables_, + ";\n" + "private $type_name$ $name$_;\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n" + " $name$_ = value;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n" + " $property_name$ = other.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$ value = _single_$name$_codec.Read(input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); +} + +void WrapperFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); +} + +void WrapperFieldGenerator::WriteToString(io::Printer* printer) { + // TODO: Implement if we ever actually need it... +} + +void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$;\n"); +} + +void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { + if (is_value_type) { + printer->Print( + variables_, + "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)"); + } else { + printer->Print( + variables_, + "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)"); + } +} + +WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : WrapperFieldGenerator(descriptor, fieldOrdinal) { + SetCommonOneofFieldVariables(&variables_); +} + +WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() { +} + +void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field. + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print(";\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$property_name$ = _oneof_$name$_codec.Read(input);\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h new file mode 100644 index 00000000..6e2414af --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ + +#include <string> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/csharp/csharp_field_base.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class WrapperFieldGenerator : public FieldGeneratorBase { + public: + WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperFieldGenerator(); + + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + + private: + bool is_value_type; // True for int32 etc; false for bytes and string + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator); +}; + +class WrapperOneofFieldGenerator : public WrapperFieldGenerator { + public: + WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperOneofFieldGenerator(); + + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.cc b/src/google/protobuf/compiler/csharp/csharp_writer.cc deleted file mode 100644 index 2bcafde5..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_writer.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// 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: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <algorithm> -#include <google/protobuf/stubs/hash.h> -#include <limits> -#include <vector> - -#include <google/protobuf/compiler/csharp/csharp_writer.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> - -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -Writer::Writer(google::protobuf::io::Printer* printer) - : printer_(printer), - newline_("\n") { - // TODO(jtattermusch): make newline customizable. -} - -Writer::~Writer() { -} - -void Writer::Indent() { - printer_->Indent(); -} - -void Writer::Outdent() { - printer_->Outdent(); -} - -void Writer::Write(const char* text) { - printer_->Print(text); -} - -void Writer::Write(const char* text, const string& value0) { - printer_->Print(text, "0", value0); -} - -void Writer::Write(const char* text, const string& value0, - const string& value1) { - printer_->Print(text, "0", value0, "1", value1); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2) { - printer_->Print(text, "0", value0, "1", value1, "2", value2); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3) { - printer_->Print(text, "0", value0, "1", value1, "2", value2, "3", value3); -} - -void Writer::WriteLine() { - printer_->Print(newline_); -} - -void Writer::WriteLine(const char* text) { - Write(text); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0) { - Write(text, value0); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1) { - Write(text, value0, value1); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2) { - Write(text, value0, value1, value2); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2, - const string& value3) { - Write(text, value0, value1, value2, value3); - WriteLine(); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index f25970e5..44b86cd7 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -156,9 +156,7 @@ ImmutableMapFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 80a94f45..f2768f3a 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -68,9 +68,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; }; diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc index ccc1b32e..cd1698f0 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -139,9 +139,7 @@ ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h index 82472602..a09cd536 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -67,9 +67,6 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; }; diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index ad215cb7..a33eba1b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -67,8 +67,15 @@ void UpdateParamsRecursively(Params& params, file->name(), file->options().java_outer_classname()); } if (file->options().has_java_package()) { + string result = file->options().java_package(); + if (!file->options().javanano_use_deprecated_package()) { + if (!result.empty()) { + result += "."; + } + result += "nano"; + } params.set_java_package( - file->name(), file->options().java_package()); + file->name(), result); } if (file->options().has_java_multiple_files()) { params.set_java_multiple_files( diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 0d2ae9db..5465655f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -200,6 +200,14 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) { if (!result.empty()) result += '.'; result += file->package(); } + + if (!file->options().javanano_use_deprecated_package()) { + if (!result.empty()) { + result += "."; + } + result += "nano"; + } + return result; } } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc index b7c720d2..d6f01c60 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -34,7 +34,6 @@ #include <google/protobuf/compiler/objectivec/objectivec_enum.h> #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> namespace google { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 5a5c9e9b..184a84a3 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/stl_util.h> #include <google/protobuf/stubs/strutil.h> #include <sstream> @@ -55,9 +54,6 @@ FileGenerator::FileGenerator(const FileDescriptor *file) : file_(file), root_class_name_(FileClassName(file)), is_public_dep_(false) { - // Validate the objc prefix. - ValidateObjCClassPrefix(file_); - for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); enum_generators_.push_back(generator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 85e438f4..375b4e0f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -34,7 +34,6 @@ #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -58,8 +57,13 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, return false; } - FileGenerator file_generator(file); + // Validate the objc prefix/package pairing. + if (!ValidateObjCClassPrefix(file, error)) { + // *error will have been filled in. + return false; + } + FileGenerator file_generator(file); string filepath = FilePath(file); // Generate header. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index 24286ac9..09266b04 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -53,6 +53,7 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator); }; + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 9b645f09..b724d35c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -28,9 +28,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifdef _MSC_VER +#include <io.h> +#else +#include <unistd.h> +#endif +#include <climits> +#include <errno.h> +#include <fcntl.h> #include <fstream> #include <iostream> #include <sstream> +#include <stdlib.h> #include <vector> #include <google/protobuf/stubs/hash.h> @@ -38,6 +47,7 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/strutil.h> // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some @@ -50,45 +60,6 @@ namespace objectivec { namespace { -// islower()/isupper()/tolower()/toupper() change based on locale. -// -// src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the -// Objective C plugin, test failures were seen on TravisCI because isupper('A') -// was coming back false for some server's locale. This approach avoids any -// such issues. - -bool IsLower(const char c) { - return ('a' <= c && c <= 'z'); -} - -bool IsUpper(const char c) { - return ('A' <= c && c <= 'Z'); -} - -char ToLower(char c) { - if ('A' <= c && c <= 'Z') { - c += 'a' - 'A'; - } - return c; -} - -// toupper() changes based on locale. We don't want this! -char ToUpper(char c) { - if ('a' <= c && c <= 'z') { - c += 'A' - 'a'; - } - return c; -} - -string TrimString(const string& s) { - string::size_type start = s.find_first_not_of(" \n\r\t"); - if (start == string::npos) { - return ""; - } - string::size_type end = s.find_last_not_of(" \n\r\t") + 1; - return s.substr(start, end - start); -} - hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) { hash_set<string> result; for (int i = 0; i < num_words; i++) { @@ -114,7 +85,7 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { bool last_char_was_upper = false; for (int i = 0; i < input.size(); i++) { char c = input[i]; - if (c >= '0' && c <= '9') { + if (ascii_isdigit(c)) { if (!last_char_was_number) { values.push_back(current); current = ""; @@ -122,7 +93,7 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { current += c; last_char_was_number = last_char_was_lower = last_char_was_upper = false; last_char_was_number = true; - } else if (IsLower(c)) { + } else if (ascii_islower(c)) { // lowercase letter can follow a lowercase or uppercase letter if (!last_char_was_lower && !last_char_was_upper) { values.push_back(current); @@ -131,12 +102,12 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { current += c; // already lower last_char_was_number = last_char_was_lower = last_char_was_upper = false; last_char_was_lower = true; - } else if (IsUpper(c)) { + } else if (ascii_isupper(c)) { if (!last_char_was_upper) { values.push_back(current); current = ""; } - current += ToLower(c); + current += ascii_tolower(c); last_char_was_number = last_char_was_lower = last_char_was_upper = false; last_char_was_upper = true; } else { @@ -150,7 +121,7 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { bool all_upper = (kUpperSegments.count(value) > 0); for (int j = 0; j < value.length(); j++) { if (j == 0 || all_upper) { - value[j] = ToUpper(value[j]); + value[j] = ascii_toupper(value[j]); } else { // Nothing, already in lower. } @@ -162,7 +133,7 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { result += *i; } if ((result.length() != 0) && !first_capitalized) { - result[0] = ToLower(result[0]); + result[0] = ascii_tolower(result[0]); } return result; } @@ -271,7 +242,7 @@ bool IsSpecialName(const string& name, const string* special_names, // If name is longer than the retained_name[i] that it matches // the next character must be not lower case (newton vs newTon vs // new_ton). - return !IsLower(name[length]); + return !ascii_islower(name[length]); } else { return true; } @@ -341,30 +312,6 @@ string FileClassPrefix(const FileDescriptor* file) { return result; } -void ValidateObjCClassPrefix(const FileDescriptor* file) { - string prefix = file->options().objc_class_prefix(); - if (prefix.length() > 0) { - // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some - // error cases, so it seems to be ok to use as a back door for errors. - if (!IsUpper(prefix[0])) { - cerr << endl - << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" - << prefix << "\";' in '" << file->name() << "';" - << " it should start with a capital letter." - << endl; - cerr.flush(); - } - if (prefix.length() < 3) { - cerr << endl - << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" - << prefix << "\";' in '" << file->name() << "';" - << " Apple recommends they should be at least 3 characters long." - << endl; - cerr.flush(); - } - } -} - string FileClassName(const FileDescriptor* file) { string name = FileClassPrefix(file); name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); @@ -452,10 +399,10 @@ string UnCamelCaseEnumShortName(const string& name) { string result; for (int i = 0; i < name.size(); i++) { char c = name[i]; - if (i > 0 && c >= 'A' && c <= 'Z') { + if (i > 0 && ascii_isupper(c)) { result += '_'; } - result += ToUpper(c); + result += ascii_toupper(c); } return result; } @@ -486,7 +433,7 @@ string FieldNameCapitalized(const FieldDescriptor* field) { // name. string result = FieldName(field); if (result.length() > 0) { - result[0] = ToUpper(result[0]); + result[0] = ascii_toupper(result[0]); } return result; } @@ -510,7 +457,7 @@ string OneofNameCapitalized(const OneofDescriptor* descriptor) { // Use the common handling and then up-case the first letter. string result = OneofName(descriptor); if (result.length() > 0) { - result[0] = ToUpper(result[0]); + result[0] = ascii_toupper(result[0]); } return result; } @@ -525,8 +472,8 @@ string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { } if (field->type() == FieldDescriptor::TYPE_GROUP) { if (worker.length() > 0) { - if (worker[0] >= 'a' && worker[0] <= 'z') { - worker[0] = ToUpper(worker[0]); + if (ascii_islower(worker[0])) { + worker[0] = ascii_toupper(worker[0]); } } return worker; @@ -534,11 +481,11 @@ string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { string result; for (int i = 0; i < worker.size(); i++) { char c = worker[i]; - if (c >= 'A' && c <= 'Z') { + if (ascii_isupper(c)) { if (i > 0) { result += '_'; } - result += ToLower(c); + result += ascii_tolower(c); } else { result += c; } @@ -830,6 +777,252 @@ string BuildCommentsString(const SourceLocation& location) { return final_comments; } +namespace { + +// Internal helper class that parses the expected package to prefix mappings +// file. +class Parser { + public: + Parser(map<string, string>* inout_package_to_prefix_map) + : prefix_map_(inout_package_to_prefix_map), line_(0) {} + + // Parses a check of input, returning success/failure. + bool ParseChunk(StringPiece chunk); + + // Should be called to finish parsing (after all input has been provided via + // ParseChunk()). Returns success/failure. + bool Finish(); + + int last_line() const { return line_; } + string error_str() const { return error_str_; } + + private: + bool ParseLoop(); + + map<string, string>* prefix_map_; + int line_; + string error_str_; + StringPiece p_; + string leftover_; +}; + +bool Parser::ParseChunk(StringPiece chunk) { + if (!leftover_.empty()) { + chunk.AppendToString(&leftover_); + p_ = StringPiece(leftover_); + } else { + p_ = chunk; + } + bool result = ParseLoop(); + if (p_.empty()) { + leftover_.clear(); + } else { + leftover_ = p_.ToString(); + } + return result; +} + +bool Parser::Finish() { + if (leftover_.empty()) { + return true; + } + // Force a newline onto the end to finish parsing. + p_ = StringPiece(leftover_ + "\n"); + if (!ParseLoop()) { + return false; + } + return p_.empty(); // Everything used? +} + +static bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; } + +bool ReadLine(StringPiece* input, StringPiece* line) { + for (int len = 0; len < input->size(); ++len) { + if (ascii_isnewline((*input)[len])) { + *line = StringPiece(input->data(), len); + ++len; // advance over the newline + *input = StringPiece(input->data() + len, input->size() - len); + return true; + } + } + return false; // Ran out of input with no newline. +} + +void TrimWhitespace(StringPiece* input) { + while (!input->empty() && ascii_isspace(*input->data())) { + input->remove_prefix(1); + } + while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) { + input->remove_suffix(1); + } +} + +void RemoveComment(StringPiece* input) { + int offset = input->find('#'); + if (offset != StringPiece::npos) { + input->remove_suffix(input->length() - offset); + } +} + +bool Parser::ParseLoop() { + StringPiece line; + while (ReadLine(&p_, &line)) { + ++line_; + RemoveComment(&line); + TrimWhitespace(&line); + if (line.size() == 0) { + continue; // Blank line. + } + int offset = line.find('='); + if (offset == StringPiece::npos) { + error_str_ = + string("Line without equal sign: '") + line.ToString() + "'."; + return false; + } + StringPiece package(line, 0, offset); + StringPiece prefix(line, offset + 1, line.length() - offset - 1); + TrimWhitespace(&package); + TrimWhitespace(&prefix); + // Don't really worry about error checking the the package/prefix for + // being valid. Assume the file is validated when it is created/edited. + (*prefix_map_)[package.ToString()] = prefix.ToString(); + } + return true; +} + +bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map, + string* out_expect_file_path, + string* out_error) { + const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); + if (file_path == NULL) { + return true; + } + + int fd; + do { + fd = open(file_path, O_RDONLY); + } while (fd < 0 && errno == EINTR); + if (fd < 0) { + *out_error = + string(file_path) + ":0:0: error: Unable to open." + strerror(errno); + return false; + } + io::FileInputStream file_stream(fd); + file_stream.SetCloseOnDelete(true); + *out_expect_file_path = file_path; + + Parser parser(prefix_map); + const void* buf; + int buf_len; + while (file_stream.Next(&buf, &buf_len)) { + if (buf_len == 0) { + continue; + } + + if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) { + *out_error = string(file_path) + ":" + SimpleItoa(parser.last_line()) + + ":0: error: " + parser.error_str(); + return false; + } + } + return parser.Finish(); +} + +} // namespace + +bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { + const string prefix = file->options().objc_class_prefix(); + const string package = file->package(); + + // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some + // error cases, so it seems to be ok to use as a back door for warnings. + + // First Check: Warning - if there is a prefix, ensure it is is a reasonable + // value according to Apple's rules. + if (prefix.length()) { + if (!ascii_isupper(prefix[0])) { + cerr << endl + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " it should start with a capital letter." << endl; + cerr.flush(); + } + if (prefix.length() < 3) { + cerr << endl + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " Apple recommends they should be at least 3 characters long." + << endl; + cerr.flush(); + } + } + + // Load any expected package prefixes to validate against those. + map<string, string> expected_package_prefixes; + string expect_file_path; + if (!LoadExpectedPackagePrefixes(&expected_package_prefixes, + &expect_file_path, out_error)) { + return false; + } + + // If there are no expected prefixes, out of here. + if (expected_package_prefixes.size() == 0) { + return true; + } + + // Second Check: Error - See if there was an expected prefix for the package + // and report if it doesn't match. + map<string, string>::iterator package_match = + expected_package_prefixes.find(package); + if (package_match != expected_package_prefixes.end()) { + // There was an entry, and... + if (package_match->second == prefix) { + // ...it matches. All good, out of here! + return true; + } else { + // ...it didn't match! + *out_error = "protoc:0: error: Expected 'option objc_class_prefix = \"" + + package_match->second + "\";' in '" + file->name() + "'"; + if (prefix.length()) { + *out_error += "; but found '" + prefix + "' instead"; + } + *out_error += "."; + return false; + } + } + + // Third Check: Error - If there was a prefix make sure it wasn't expected + // for a different package instead (overlap is allowed, but it has to be + // listed as an expected overlap). + if (prefix.length()) { + for (map<string, string>::iterator i = expected_package_prefixes.begin(); + i != expected_package_prefixes.end(); ++i) { + if (i->second == prefix) { + *out_error = + "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix + + "\";' in '" + file->name() + + "'; that prefix is already used for 'package " + i->first + + ";'. It can only be reused by listing it in the expected file (" + + expect_file_path + ")."; + return false; // Only report first usage of the prefix. + } + } + } + + // Fourth Check: Warning - If there was a prefix, and it wasn't expected, + // issue a warning suggesting it gets added to the file. + if (prefix.length()) { + cerr << endl + << "protoc:0: warning: Found 'option objc_class_prefix = \"" << prefix + << "\";' in '" << file->name() << "';" + << " should you add it to the expected prefixes file (" + << expect_file_path << ")?" << endl; + cerr.flush(); + } + + return true; +} + void TextFormatDecodeData::AddString(int32 key, const string& input_for_decode, const string& desired_output) { @@ -897,7 +1090,7 @@ class DecodeDataBuilder { void AddChar(const char desired) { ++segment_len_; - is_all_upper_ &= IsUpper(desired); + is_all_upper_ &= ascii_isupper(desired); } void Push() { @@ -912,9 +1105,9 @@ class DecodeDataBuilder { bool AddFirst(const char desired, const char input) { if (desired == input) { op_ = kOpAsIs; - } else if (desired == ToUpper(input)) { + } else if (desired == ascii_toupper(input)) { op_ = kOpFirstUpper; - } else if (desired == ToLower(input)) { + } else if (desired == ascii_tolower(input)) { op_ = kOpFirstLower; } else { // Can't be transformed to match. @@ -952,7 +1145,7 @@ bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { if (desired == input) { // If we aren't transforming it, or we're upper casing it and it is // supposed to be uppercase; just add it to the segment. - if ((op_ != kOpAllUpper) || IsUpper(desired)) { + if ((op_ != kOpAllUpper) || ascii_isupper(desired)) { AddChar(desired); return true; } @@ -964,7 +1157,7 @@ bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { // If we need to uppercase, and everything so far has been uppercase, // promote op to AllUpper. - if ((desired == ToUpper(input)) && is_all_upper_) { + if ((desired == ascii_toupper(input)) && is_all_upper_) { op_ = kOpAllUpper; AddChar(desired); return true; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 10d51a34..072a2e57 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -62,9 +62,6 @@ string FileName(const FileDescriptor* file); // declared in the proto package. string FilePath(const FileDescriptor* file); -// Checks the prefix for a given file and outputs any warnings/errors needed. -void ValidateObjCClassPrefix(const FileDescriptor* file); - // Gets the name of the root class we'll generate in the file. This class // is not meant for external consumption, but instead contains helpers that // the rest of the the classes need @@ -145,6 +142,11 @@ string BuildFlagsString(const vector<string>& strings); string BuildCommentsString(const SourceLocation& location); +// Checks the prefix for a given file and outputs any warnings needed, if +// there are flat out errors, then out_error is filled in and the result is +// false. +bool ValidateObjCClassPrefix(const FileDescriptor* file, string *out_error); + // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the the expected output. class LIBPROTOC_EXPORT TextFormatDecodeData { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 77664c68..3cb87482 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -34,7 +34,6 @@ #include <google/protobuf/compiler/objectivec/objectivec_oneof.h> #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> namespace google { diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index ddf34bfa..cc6f1efb 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -229,6 +229,32 @@ TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { typedef ParserTest ParseMessageTest; +TEST_F(ParseMessageTest, IgnoreBOM) { + char input[] = " message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n"; + // Set UTF-8 BOM. + input[0] = (char)0xEF; + input[1] = (char)0xBB; + input[2] = (char)0xBF; + ExpectParsesTo(input, + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); +} + +TEST_F(ParseMessageTest, BOMError) { + char input[] = " message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n"; + input[0] = (char)0xEF; + ExpectHasErrors(input, + "0:1: Proto file starts with 0xEF but not UTF-8 BOM. " + "Only UTF-8 is accepted for proto file.\n" + "0:0: Expected top-level statement (e.g. \"message\").\n"); +} + TEST_F(ParseMessageTest, SimpleMessage) { ExpectParsesTo( "message TestMessage {\n" diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb index 100d6fa7..49b23fbe 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb @@ -13,7 +13,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do optional :optional_double, :double, 6 optional :optional_float, :float, 7 optional :optional_string, :string, 8 - optional :optional_bytes, :string, 9 + optional :optional_bytes, :bytes, 9 optional :optional_enum, :enum, 10, "A.B.C.TestEnum" optional :optional_msg, :message, 11, "A.B.C.TestMessage" repeated :repeated_int32, :int32, 21 @@ -24,7 +24,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do repeated :repeated_double, :double, 26 repeated :repeated_float, :float, 27 repeated :repeated_string, :string, 28 - repeated :repeated_bytes, :string, 29 + repeated :repeated_bytes, :bytes, 29 repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" map :map_int32_string, :int32, :string, 61 @@ -47,7 +47,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do optional :oneof_double, :double, 46 optional :oneof_float, :float, 47 optional :oneof_string, :string, 48 - optional :oneof_bytes, :string, 49 + optional :oneof_bytes, :bytes, 49 optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" optional :oneof_msg, :message, 51, "A.B.C.TestMessage" end diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index a9b6837e..9692f1bf 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -47,7 +47,7 @@ namespace compiler { namespace ruby { // Forward decls. -std::string IntToString(uint32 value); +std::string IntToString(int32 value); std::string StripDotProto(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); @@ -64,7 +64,7 @@ void GenerateEnumAssignment( const google::protobuf::EnumDescriptor* en, google::protobuf::io::Printer* printer); -std::string IntToString(uint32 value) { +std::string IntToString(int32 value) { std::ostringstream os; os << value; return os.str(); @@ -85,17 +85,25 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) { } std::string TypeName(const google::protobuf::FieldDescriptor* field) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: return "int32"; - case FieldDescriptor::CPPTYPE_INT64: return "int64"; - case FieldDescriptor::CPPTYPE_UINT32: return "uint32"; - case FieldDescriptor::CPPTYPE_UINT64: return "uint64"; - case FieldDescriptor::CPPTYPE_DOUBLE: return "double"; - case FieldDescriptor::CPPTYPE_FLOAT: return "float"; - case FieldDescriptor::CPPTYPE_BOOL: return "bool"; - case FieldDescriptor::CPPTYPE_ENUM: return "enum"; - case FieldDescriptor::CPPTYPE_STRING: return "string"; - case FieldDescriptor::CPPTYPE_MESSAGE: return "message"; + switch (field->type()) { + case FieldDescriptor::TYPE_INT32: return "int32"; + case FieldDescriptor::TYPE_INT64: return "int64"; + case FieldDescriptor::TYPE_UINT32: return "uint32"; + case FieldDescriptor::TYPE_UINT64: return "uint64"; + case FieldDescriptor::TYPE_SINT32: return "sint32"; + case FieldDescriptor::TYPE_SINT64: return "sint64"; + case FieldDescriptor::TYPE_FIXED32: return "fixed32"; + case FieldDescriptor::TYPE_FIXED64: return "fixed64"; + case FieldDescriptor::TYPE_SFIXED32: return "sfixed32"; + case FieldDescriptor::TYPE_SFIXED64: return "sfixed64"; + case FieldDescriptor::TYPE_DOUBLE: return "double"; + case FieldDescriptor::TYPE_FLOAT: return "float"; + case FieldDescriptor::TYPE_BOOL: return "bool"; + case FieldDescriptor::TYPE_ENUM: return "enum"; + case FieldDescriptor::TYPE_STRING: return "string"; + case FieldDescriptor::TYPE_BYTES: return "bytes"; + case FieldDescriptor::TYPE_MESSAGE: return "message"; + case FieldDescriptor::TYPE_GROUP: return "group"; default: assert(false); return ""; } } diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 30b3a3a7..5e7eeaa7 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -311,7 +311,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), -1); FileOptions_descriptor_ = file->message_type(9); - static const int FileOptions_offsets_[15] = { + static const int FileOptions_offsets_[16] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), @@ -326,6 +326,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, javanano_use_deprecated_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -695,7 +696,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti" "ons\030\004 \001(\0132\036.google.protobuf.MethodOption" "s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se" - "rver_streaming\030\006 \001(\010:\005false\"\201\005\n\013FileOpti" + "rver_streaming\030\006 \001(\010:\005false\"\252\005\n\013FileOpti" "ons\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_outer_" "classname\030\010 \001(\t\022\"\n\023java_multiple_files\030\n" " \001(\010:\005false\022,\n\035java_generate_equals_and_" @@ -708,55 +709,55 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005" "false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031" "\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name" - "space\030% \001(\t\022C\n\024uninterpreted_option\030\347\007 \003" - "(\0132$.google.protobuf.UninterpretedOption" - "\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE" - "\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mess" - "ageOptions\022&\n\027message_set_wire_format\030\001 " - "\001(\010:\005false\022.\n\037no_standard_descriptor_acc" - "essor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005" - "false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterprete" - "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte" - "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOption" - "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field" - "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n" - "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt" - "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa" - "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n" - " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003" - "(\0132$.google.protobuf.UninterpretedOption" - "\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRIN" - "G_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS" - "_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013" - "EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndepr" - "ecated\030\003 \001(\010:\005false\022C\n\024uninterpreted_opt" - "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret" - "edOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022" - "\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpre" - "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" - "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOpt" - "ions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMetho" - "dOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024u" - "ninterpreted_option\030\347\007 \003(\0132$.google.prot" - "obuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023" - "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog" - "le.protobuf.UninterpretedOption.NamePart" - "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i" - "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001" - "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value" - "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP" - "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002" - " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(" - "\0132(.google.protobuf.SourceCodeInfo.Locat" - "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" - "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" - "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" - "ached_comments\030\006 \003(\tBe\n\023com.google.proto" - "bufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003GP" - "B\252\002\'Google.ProtocolBuffers.DescriptorPro" - "tos", 4963); + "space\030% \001(\t\022\'\n\037javanano_use_deprecated_p" + "ackage\030& \001(\010\022C\n\024uninterpreted_option\030\347\007 " + "\003(\0132$.google.protobuf.UninterpretedOptio" + "n\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZ" + "E\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mes" + "sageOptions\022&\n\027message_set_wire_format\030\001" + " \001(\010:\005false\022.\n\037no_standard_descriptor_ac" + "cessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:" + "\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpret" + "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" + "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptio" + "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel" + "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?" + "\n\006jstype\030\006 \001(\0162$.google.protobuf.FieldOp" + "tions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005f" + "alse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030" + "\n \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 " + "\003(\0132$.google.protobuf.UninterpretedOptio" + "n\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRI" + "NG_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJ" + "S_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n" + "\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndep" + "recated\030\003 \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions" + "\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpr" + "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni" + "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOp" + "tions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unin" + "terpreted_option\030\347\007 \003(\0132$.google.protobu" + "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMeth" + "odOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024" + "uninterpreted_option\030\347\007 \003(\0132$.google.pro" + "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n" + "\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goo" + "gle.protobuf.UninterpretedOption.NamePar" + "t\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_" + "int_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 " + "\001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_valu" + "e\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010Name" + "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030" + "\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003" + "(\0132(.google.protobuf.SourceCodeInfo.Loca" + "tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s" + "pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022" + "\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de" + "tached_comments\030\006 \003(\tB[\n\023com.google.prot" + "obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G" + "PB\252\002\032Google.Protobuf.Reflection\260\002\001", 4994); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -7598,6 +7599,7 @@ const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kCcEnableArenasFieldNumber; const int FileOptions::kObjcClassPrefixFieldNumber; const int FileOptions::kCsharpNamespaceFieldNumber; +const int FileOptions::kJavananoUseDeprecatedPackageFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -7635,6 +7637,7 @@ void FileOptions::SharedCtor() { cc_enable_arenas_ = false; objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + javanano_use_deprecated_package_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -7701,8 +7704,8 @@ void FileOptions::Clear() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } } - if (_has_bits_[8 / 32] & 16128u) { - ZR_(java_generic_services_, cc_enable_arenas_); + if (_has_bits_[8 / 32] & 32512u) { + ZR_(java_generic_services_, javanano_use_deprecated_package_); if (has_objc_class_prefix()) { objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -7951,6 +7954,21 @@ bool FileOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(304)) goto parse_javanano_use_deprecated_package; + break; + } + + // optional bool javanano_use_deprecated_package = 38; + case 38: { + if (tag == 304) { + parse_javanano_use_deprecated_package: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &javanano_use_deprecated_package_))); + set_has_javanano_use_deprecated_package(); + } else { + goto handle_unusual; + } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -8098,6 +8116,11 @@ void FileOptions::SerializeWithCachedSizes( 37, this->csharp_namespace(), output); } + // optional bool javanano_use_deprecated_package = 38; + if (has_javanano_use_deprecated_package()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(38, this->javanano_use_deprecated_package(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -8219,6 +8242,11 @@ void FileOptions::SerializeWithCachedSizes( 37, this->csharp_namespace(), target); } + // optional bool javanano_use_deprecated_package = 38; + if (has_javanano_use_deprecated_package()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(38, this->javanano_use_deprecated_package(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -8290,7 +8318,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 16128u) { + if (_has_bits_[8 / 32] & 32512u) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -8325,6 +8353,11 @@ int FileOptions::ByteSize() const { this->csharp_namespace()); } + // optional bool javanano_use_deprecated_package = 38; + if (has_javanano_use_deprecated_package()) { + total_size += 2 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -8412,6 +8445,9 @@ void FileOptions::MergeFrom(const FileOptions& from) { set_has_csharp_namespace(); csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_); } + if (from.has_javanano_use_deprecated_package()) { + set_javanano_use_deprecated_package(from.javanano_use_deprecated_package()); + } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -8457,6 +8493,7 @@ void FileOptions::InternalSwap(FileOptions* other) { std::swap(cc_enable_arenas_, other->cc_enable_arenas_); objc_class_prefix_.Swap(&other->objc_class_prefix_); csharp_namespace_.Swap(&other->csharp_namespace_); + std::swap(javanano_use_deprecated_package_, other->javanano_use_deprecated_package_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -8957,6 +8994,30 @@ void FileOptions::clear_csharp_namespace() { // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } +// optional bool javanano_use_deprecated_package = 38; +bool FileOptions::has_javanano_use_deprecated_package() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} +void FileOptions::set_has_javanano_use_deprecated_package() { + _has_bits_[0] |= 0x00004000u; +} +void FileOptions::clear_has_javanano_use_deprecated_package() { + _has_bits_[0] &= ~0x00004000u; +} +void FileOptions::clear_javanano_use_deprecated_package() { + javanano_use_deprecated_package_ = false; + clear_has_javanano_use_deprecated_package(); +} + bool FileOptions::javanano_use_deprecated_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package) + return javanano_use_deprecated_package_; +} + void FileOptions::set_javanano_use_deprecated_package(bool value) { + set_has_javanano_use_deprecated_package(); + javanano_use_deprecated_package_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index b887b8cb..2aa076ae 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -2000,6 +2000,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { ::std::string* release_csharp_namespace(); void set_allocated_csharp_namespace(::std::string* csharp_namespace); + // optional bool javanano_use_deprecated_package = 38; + bool has_javanano_use_deprecated_package() const; + void clear_javanano_use_deprecated_package(); + static const int kJavananoUseDeprecatedPackageFieldNumber = 38; + bool javanano_use_deprecated_package() const; + void set_javanano_use_deprecated_package(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; void clear_uninterpreted_option(); @@ -2043,6 +2050,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_objc_class_prefix(); inline void set_has_csharp_namespace(); inline void clear_has_csharp_namespace(); + inline void set_has_javanano_use_deprecated_package(); + inline void clear_has_javanano_use_deprecated_package(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -2057,13 +2066,14 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { bool cc_generic_services_; int optimize_for_; ::google::protobuf::internal::ArenaStringPtr go_package_; - ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; - ::google::protobuf::internal::ArenaStringPtr csharp_namespace_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool java_generic_services_; bool py_generic_services_; bool deprecated_; bool cc_enable_arenas_; + bool javanano_use_deprecated_package_; + ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; + ::google::protobuf::internal::ArenaStringPtr csharp_namespace_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -5892,6 +5902,30 @@ inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_na // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } +// optional bool javanano_use_deprecated_package = 38; +inline bool FileOptions::has_javanano_use_deprecated_package() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} +inline void FileOptions::set_has_javanano_use_deprecated_package() { + _has_bits_[0] |= 0x00004000u; +} +inline void FileOptions::clear_has_javanano_use_deprecated_package() { + _has_bits_[0] &= ~0x00004000u; +} +inline void FileOptions::clear_javanano_use_deprecated_package() { + javanano_use_deprecated_package_ = false; + clear_has_javanano_use_deprecated_package(); +} +inline bool FileOptions::javanano_use_deprecated_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package) + return javanano_use_deprecated_package_; +} +inline void FileOptions::set_javanano_use_deprecated_package(bool value) { + set_has_javanano_use_deprecated_package(); + javanano_use_deprecated_package_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 13f136cb..9d3dd8fb 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -42,8 +42,9 @@ syntax = "proto2"; package google.protobuf; option go_package = "descriptor"; option java_package = "com.google.protobuf"; +option javanano_use_deprecated_package = true; option java_outer_classname = "DescriptorProtos"; -option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based @@ -369,6 +370,10 @@ message FileOptions { // Namespace for generated classes; defaults to the package. optional string csharp_namespace = 37; + // Whether the nano proto compiler should generate in the deprecated non-nano + // suffixed package. + optional bool javanano_use_deprecated_package = 38; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index f78fce21..2e22ccb1 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\036google/protobuf/duration.proto\022\017google" ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" - "\n\005nanos\030\002 \001(\005BH\n\023com.google.protobufB\rDu" - "rationProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Protocol" - "Buffersb\006proto3", 175); + "\n\005nanos\030\002 \001(\005BP\n\023com.google.protobufB\rDu" + "rationProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3", 183); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/duration.proto", &protobuf_RegisterTypes); Duration::default_instance_ = new Duration(); diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto index e466341a..0762c3c2 100644 --- a/src/google/protobuf/duration.proto +++ b/src/google/protobuf/duration.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "DurationProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; // A Duration represents a signed, fixed-length span of time represented diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 1a9a6661..1e1c2c8c 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -79,8 +79,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\033google/protobuf/empty.proto\022\017google.pr" - "otobuf\"\007\n\005EmptyB)\n\023com.google.protobufB\n" - "EmptyProtoP\001\242\002\003GPBb\006proto3", 106); + "otobuf\"\007\n\005EmptyBJ\n\023com.google.protobufB\n" + "EmptyProtoP\001\242\002\003GPB\252\002\036Google.Protobuf.Wel" + "lKnownTypesb\006proto3", 139); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/empty.proto", &protobuf_RegisterTypes); Empty::default_instance_ = new Empty(); diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto index 94df0397..363ec175 100644 --- a/src/google/protobuf/empty.proto +++ b/src/google/protobuf/empty.proto @@ -34,6 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "EmptyProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index 68314fd3..88020ef2 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -81,8 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n google/protobuf/field_mask.proto\022\017goog" "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" - "F\n\023com.google.protobufB\016FieldMaskProtoP\001" - "\242\002\003GPB\252\002\026Google.ProtocolBuffersb\006proto3", 159); + "N\n\023com.google.protobufB\016FieldMaskProtoP\001" + "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb" + "\006proto3", 167); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/field_mask.proto", &protobuf_RegisterTypes); FieldMask::default_instance_ = new FieldMask(); diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto index 35b1acc3..c19f4410 100644 --- a/src/google/protobuf/field_mask.proto +++ b/src/google/protobuf/field_mask.proto @@ -34,7 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "FieldMaskProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 961c1a3f..ad351dc3 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -112,8 +112,8 @@ #include <string> #include <utility> #ifdef _MSC_VER - #if defined(_M_IX86) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + // Assuming windows is always little-endian. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) #define PROTOBUF_LITTLE_ENDIAN 1 #endif #if _MSC_VER >= 1300 diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index ef2de300..60bd7957 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -762,6 +762,15 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments, next_leading_comments); if (current_.type == TYPE_START) { + // Ignore unicode byte order mark(BOM) if it appears at the file + // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted. + if (TryConsume((char)0xEF)) { + if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) { + AddError("Proto file starts with 0xEF but not UTF-8 BOM. " + "Only UTF-8 is accepted for proto file."); + return false; + } + } collector.DetachFromPrev(); } else { // A comment appearing on the same line must be attached to the previous diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 96d2f201..d928b7a7 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -168,10 +168,11 @@ class Map { } } -#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) +#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ + !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID) template<class NodeType, class... Args> void construct(NodeType* p, Args&&... args) { - new (p) NodeType(std::forward<Args>(args)...); + new ((void*)p) NodeType(std::forward<Args>(args)...); } template<class NodeType> diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index febfe5f6..c69e8d94 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -32,7 +32,6 @@ syntax = "proto2"; option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest_lite.proto"; diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto index 04ca6170..3d4af28e 100644 --- a/src/google/protobuf/map_proto2_unittest.proto +++ b/src/google/protobuf/map_proto2_unittest.proto @@ -36,8 +36,6 @@ syntax = "proto2"; // In map_test_util.h we do "using namespace unittest = protobuf_unittest". package protobuf_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - enum Proto2MapEnum { PROTO2_MAP_ENUM_FOO = 0; PROTO2_MAP_ENUM_BAR = 1; diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index cbf747d9..b308c7ff 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -31,7 +31,6 @@ syntax = "proto3"; option cc_enable_arenas = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest.proto"; diff --git a/src/google/protobuf/map_unittest_proto3.proto b/src/google/protobuf/map_unittest_proto3.proto new file mode 100644 index 00000000..16be2773 --- /dev/null +++ b/src/google/protobuf/map_unittest_proto3.proto @@ -0,0 +1,120 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +// This file is mostly equivalent to map_unittest.proto, but imports +// unittest_proto3.proto instead of unittest.proto, so that it only +// uses proto3 messages. This makes it suitable for testing +// implementations which only support proto3. +// The TestRequiredMessageMap message has been removed as there are no +// required fields in proto3. +syntax = "proto3"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In map_test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Tests maps. +message TestMap { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<string , string > map_string_string = 14; + map<int32 , bytes > map_int32_bytes = 15; + map<int32 , MapEnum > map_int32_enum = 16; + map<int32 , ForeignMessage> map_int32_foreign_message = 17; +} + +message TestMapSubmessage { + TestMap test_map = 1; +} + +message TestMessageMap { + map<int32, TestAllTypes> map_int32_message = 1; +} + +// Two map fields share the same entry default instance. +message TestSameTypeMap { + map<int32, int32> map1 = 1; + map<int32, int32> map2 = 2; +} + +enum MapEnum { + MAP_ENUM_FOO = 0; + MAP_ENUM_BAR = 1; + MAP_ENUM_BAZ = 2; +} + +message TestArenaMap { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<int32 , MapEnum > map_int32_enum = 14; + map<int32 , ForeignMessage> map_int32_foreign_message = 15; +} + +// Previously, message containing enum called Type cannot be used as value of +// map field. +message MessageContainingEnumCalledType { + enum Type { + TYPE_FOO = 0; + } + map<int32, MessageContainingEnumCalledType> type = 1; +} + +// Previously, message cannot contain map field called "entry". +message MessageContainingMapCalledEntry { + map<int32, int32> entry = 1; +} diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 3b3799a9..5c88363f 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -81,8 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n$google/protobuf/source_context.proto\022\017" "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" - "_name\030\001 \001(\tB1\n\023com.google.protobufB\022Sour" - "ceContextProtoP\001\242\002\003GPBb\006proto3", 150); + "_name\030\001 \001(\tBR\n\023com.google.protobufB\022Sour" + "ceContextProtoP\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3", 183); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/source_context.proto", &protobuf_RegisterTypes); SourceContext::default_instance_ = new SourceContext(); diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto index 2c8a17a8..98d4920a 100644 --- a/src/google/protobuf/source_context.proto +++ b/src/google/protobuf/source_context.proto @@ -34,6 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "SourceContextProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 30113cdb..a7e2eafd 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -165,9 +165,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() { "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" - "Value\022\016\n\nNULL_VALUE\020\000BF\n\023com.google.prot" - "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Pr" - "otocolBuffersb\006proto3", 581); + "Value\022\016\n\nNULL_VALUE\020\000BN\n\023com.google.prot" + "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pr" + "otobuf.WellKnownTypesb\006proto3", 589); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/struct.proto", &protobuf_RegisterTypes); Struct::default_instance_ = new Struct(); diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto index cd102731..4ff10cd0 100644 --- a/src/google/protobuf/struct.proto +++ b/src/google/protobuf/struct.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "StructProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h index dd7abf6f..a0116a60 100644 --- a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h +++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h @@ -61,8 +61,8 @@ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { - __atomic_compare_exchange(ptr, &old_value, &new_value, true, - __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + __atomic_compare_exchange_n(ptr, &old_value, new_value, true, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return old_value; } diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h new file mode 100644 index 00000000..c4f9edee --- /dev/null +++ b/src/google/protobuf/stubs/callback.h @@ -0,0 +1,463 @@ +#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ +#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ + +#include <google/protobuf/stubs/macros.h> +#include <google/protobuf/stubs/type_traits.h> + +// =================================================================== +// emulates google3/base/callback.h + +namespace google { +namespace protobuf { + +// Abstract interface for a callback. When calling an RPC, you must provide +// a Closure to call when the procedure completes. See the Service interface +// in service.h. +// +// To automatically construct a Closure which calls a particular function or +// method with a particular set of parameters, use the NewCallback() function. +// Example: +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(&FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// +// Example that calls a method: +// class Handler { +// public: +// ... +// +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(this, &Handler::FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// }; +// +// Currently NewCallback() supports binding zero, one, or two arguments. +// +// Callbacks created with NewCallback() automatically delete themselves when +// executed. They should be used when a callback is to be called exactly +// once (usually the case with RPC callbacks). If a callback may be called +// a different number of times (including zero), create it with +// NewPermanentCallback() instead. You are then responsible for deleting the +// callback (using the "delete" keyword as normal). +// +// Note that NewCallback() is a bit touchy regarding argument types. Generally, +// the values you provide for the parameter bindings must exactly match the +// types accepted by the callback function. For example: +// void Foo(string s); +// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string +// NewCallback(&Foo, string("foo")); // WORKS +// Also note that the arguments cannot be references: +// void Foo(const string& s); +// string my_str; +// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes. +// However, correctly-typed pointers will work just fine. +class LIBPROTOBUF_EXPORT Closure { + public: + Closure() {} + virtual ~Closure(); + + virtual void Run() = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); +}; + +template<typename R, typename A1> +class LIBPROTOBUF_EXPORT ResultCallback1 { + public: + ResultCallback1() {} + virtual ~ResultCallback1() {} + + virtual R Run(A1) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); +}; + +template<typename R, typename A1, typename A2> +class LIBPROTOBUF_EXPORT ResultCallback2 { + public: + ResultCallback2() {} + virtual ~ResultCallback2() {} + + virtual R Run(A1,A2) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); +}; + +namespace internal { + +class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { + public: + typedef void (*FunctionType)(); + + FunctionClosure0(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionClosure0(); + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template <typename Class> +class MethodClosure0 : public Closure { + public: + typedef void (Class::*MethodType)(); + + MethodClosure0(Class* object, MethodType method, bool self_deleting) + : object_(object), method_(method), self_deleting_(self_deleting) {} + ~MethodClosure0() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; +}; + +template <typename Arg1> +class FunctionClosure1 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1); + + FunctionClosure1(FunctionType function, bool self_deleting, + Arg1 arg1) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1) {} + ~FunctionClosure1() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; +}; + +template <typename Class, typename Arg1> +class MethodClosure1 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1); + + MethodClosure1(Class* object, MethodType method, bool self_deleting, + Arg1 arg1) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1) {} + ~MethodClosure1() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; +}; + +template <typename Arg1, typename Arg2> +class FunctionClosure2 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2); + + FunctionClosure2(FunctionType function, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~FunctionClosure2() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template <typename Class, typename Arg1, typename Arg2> +class MethodClosure2 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2); + + MethodClosure2(Class* object, MethodType method, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~MethodClosure2() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template<typename R, typename Arg1> +class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> { + public: + typedef R (*FunctionType)(Arg1 arg1); + + FunctionResultCallback_0_1(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_1() {} + + R Run(Arg1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template<typename R, typename P1, typename A1> +class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> { + public: + typedef R (*FunctionType)(P1, A1); + + FunctionResultCallback_1_1(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_1() {} + + R Run(A1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_, a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +template <typename T> +struct InternalConstRef { + typedef typename remove_reference<T>::type base_type; + typedef const base_type& type; +}; + +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename A1, typename A2> +class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> { + public: + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); + MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + method_(method), + self_deleting_(self_deleting), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) {} + ~MethodResultCallback_5_2() {} + + R Run(A1 a1, A2 a2) { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; + typename remove_reference<P1>::type p1_; + typename remove_reference<P2>::type p2_; + typename remove_reference<P3>::type p3_; + typename remove_reference<P4>::type p4_; + typename remove_reference<P5>::type p5_; +}; + +} // namespace internal + +// See Closure. +inline Closure* NewCallback(void (*function)()) { + return new internal::FunctionClosure0(function, true); +} + +// See Closure. +inline Closure* NewPermanentCallback(void (*function)()) { + return new internal::FunctionClosure0(function, false); +} + +// See Closure. +template <typename Class> +inline Closure* NewCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0<Class>(object, method, true); +} + +// See Closure. +template <typename Class> +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0<Class>(object, method, false); +} + +// See Closure. +template <typename Arg1> +inline Closure* NewCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1<Arg1>(function, true, arg1); +} + +// See Closure. +template <typename Arg1> +inline Closure* NewPermanentCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1<Arg1>(function, false, arg1); +} + +// See Closure. +template <typename Class, typename Arg1> +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1); +} + +// See Closure. +template <typename Class, typename Arg1> +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1); +} + +// See Closure. +template <typename Arg1, typename Arg2> +inline Closure* NewCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2<Arg1, Arg2>( + function, true, arg1, arg2); +} + +// See Closure. +template <typename Arg1, typename Arg2> +inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2<Arg1, Arg2>( + function, false, arg1, arg2); +} + +// See Closure. +template <typename Class, typename Arg1, typename Arg2> +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2<Class, Arg1, Arg2>( + object, method, true, arg1, arg2); +} + +// See Closure. +template <typename Class, typename Arg1, typename Arg2> +inline Closure* NewPermanentCallback( + Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2<Class, Arg1, Arg2>( + object, method, false, arg1, arg2); +} + +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, true); +} + +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, false); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, true, p1); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback( + R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, false, p1); +} + +// See MethodResultCallback_5_2 +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename A1, typename A2> +inline ResultCallback2<R, A1, A2>* NewPermanentCallback( + T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), + typename internal::InternalConstRef<P1>::type p1, + typename internal::InternalConstRef<P2>::type p2, + typename internal::InternalConstRef<P3>::type p3, + typename internal::InternalConstRef<P4>::type p4, + typename internal::InternalConstRef<P5>::type p5) { + return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1, + A2>(object, function, false, p1, + p2, p3, p4, p5); +} + +// A function which does nothing. Useful for creating no-op callbacks, e.g.: +// Closure* nothing = NewCallback(&DoNothing); +void LIBPROTOBUF_EXPORT DoNothing(); + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 3eb57a9b..de866e14 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -35,38 +35,16 @@ #ifndef GOOGLE_PROTOBUF_COMMON_H__ #define GOOGLE_PROTOBUF_COMMON_H__ -#include <assert.h> -#include <stdlib.h> -#include <cstddef> -#include <string> -#include <string.h> -#if defined(__osf__) -// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of -// what stdint.h would define. -#include <inttypes.h> -#elif !defined(_MSC_VER) -#include <stdint.h> -#endif -#undef PROTOBUF_LITTLE_ENDIAN -#ifdef _MSC_VER - // Assuming windows is always little-endian. - #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif - #if _MSC_VER >= 1300 - // If MSVC has "/RTCc" set, it will complain about truncating casts at - // runtime. This file contains some intentional truncating casts. - #pragma runtime_checks("c", off) - #endif -#else - #include <sys/param.h> // __BYTE_ORDER - #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif -#endif +#include <google/protobuf/stubs/port.h> +#include <google/protobuf/stubs/macros.h> +#include <google/protobuf/stubs/platform_macros.h> + +// TODO(liujisi): Remove the following includes after the include clean-up. +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/scoped_ptr.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/stubs/callback.h> #ifndef PROTOBUF_USE_EXCEPTIONS #if defined(_MSC_VER) && defined(_CPPUNWIND) @@ -81,9 +59,6 @@ #if PROTOBUF_USE_EXCEPTIONS #include <exception> #endif - -#include <google/protobuf/stubs/platform_macros.h> - #if defined(__APPLE__) #include <TargetConditionals.h> // for TARGET_OS_IPHONE #endif @@ -109,39 +84,10 @@ inline BOOL GetMessage( } #endif - namespace std {} namespace google { namespace protobuf { - -#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS -#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS -#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName(); \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) - #ifdef LIBPROTOBUF_EXPORTS - #define LIBPROTOBUF_EXPORT __declspec(dllexport) - #else - #define LIBPROTOBUF_EXPORT __declspec(dllimport) - #endif - #ifdef LIBPROTOC_EXPORTS - #define LIBPROTOC_EXPORT __declspec(dllexport) - #else - #define LIBPROTOC_EXPORT __declspec(dllimport) - #endif -#else - #define LIBPROTOBUF_EXPORT - #define LIBPROTOC_EXPORT -#endif - namespace internal { // Some of these constants are macros rather than const ints so that they can @@ -187,1230 +133,6 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version); GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \ __FILE__) -// =================================================================== -// from google3/base/port.h - -typedef unsigned int uint; - -#ifdef _MSC_VER -typedef signed __int8 int8; -typedef __int16 int16; -typedef __int32 int32; -typedef __int64 int64; - -typedef unsigned __int8 uint8; -typedef unsigned __int16 uint16; -typedef unsigned __int32 uint32; -typedef unsigned __int64 uint64; -#else -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; - -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; -#endif - -// long long macros to be used because gcc and vc++ use different suffixes, -// and different size specifiers in format strings -#undef GOOGLE_LONGLONG -#undef GOOGLE_ULONGLONG -#undef GOOGLE_LL_FORMAT - -#ifdef _MSC_VER -#define GOOGLE_LONGLONG(x) x##I64 -#define GOOGLE_ULONGLONG(x) x##UI64 -#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...) -#else -#define GOOGLE_LONGLONG(x) x##LL -#define GOOGLE_ULONGLONG(x) x##ULL -#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also. -#endif - -static const int32 kint32max = 0x7FFFFFFF; -static const int32 kint32min = -kint32max - 1; -static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF); -static const int64 kint64min = -kint64max - 1; -static const uint32 kuint32max = 0xFFFFFFFFu; -static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); - -// ------------------------------------------------------------------- -// Annotations: Some parts of the code have been annotated in ways that might -// be useful to some compilers or tools, but are not supported universally. -// You can #define these annotations yourself if the default implementation -// is not right for you. - -#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE -#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -// For functions we want to force inline. -// Introduced in gcc 3.1. -#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) -#else -// Other compilers will have to figure it out for themselves. -#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE -#endif -#endif - -#ifndef GOOGLE_ATTRIBUTE_NOINLINE -#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -// For functions we want to force not inline. -// Introduced in gcc 3.1. -#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline)) -#else -// Other compilers will have to figure it out for themselves. -#define GOOGLE_ATTRIBUTE_NOINLINE -#endif -#endif - -#ifndef GOOGLE_ATTRIBUTE_DEPRECATED -#ifdef __GNUC__ -// If the method/variable/type is used anywhere, produce a warning. -#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated)) -#else -#define GOOGLE_ATTRIBUTE_DEPRECATED -#endif -#endif - -#ifndef GOOGLE_PREDICT_TRUE -#ifdef __GNUC__ -// Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) -#else -#define GOOGLE_PREDICT_TRUE -#endif -#endif - -#ifndef GOOGLE_PREDICT_FALSE -#ifdef __GNUC__ -// Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) -#else -#define GOOGLE_PREDICT_FALSE -#endif -#endif - -// Delimits a block of code which may write to memory which is simultaneously -// written by other threads, but which has been determined to be thread-safe -// (e.g. because it is an idempotent write). -#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN -#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN() -#endif -#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END -#define GOOGLE_SAFE_CONCURRENT_WRITES_END() -#endif - -#define GOOGLE_GUARDED_BY(x) -#define GOOGLE_FALLTHROUGH_INTENDED -#define GOOGLE_ATTRIBUTE_COLD - -// x86 and x86-64 can perform unaligned loads/stores directly. -#if defined(_M_X64) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(__i386__) - -#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p)) -#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p)) -#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p)) - -#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val)) -#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val)) -#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val)) - -#else -inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) { - uint16 t; - memcpy(&t, p, sizeof t); - return t; -} - -inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) { - uint32 t; - memcpy(&t, p, sizeof t); - return t; -} - -inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) { - uint64 t; - memcpy(&t, p, sizeof t); - return t; -} - -inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) { - memcpy(p, &v, sizeof v); -} - -inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) { - memcpy(p, &v, sizeof v); -} - -inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { - memcpy(p, &v, sizeof v); -} -#endif - -#if defined(_MSC_VER) -#define GOOGLE_THREAD_LOCAL __declspec(thread) -#else -#define GOOGLE_THREAD_LOCAL __thread -#endif - -// =================================================================== -// from google3/base/basictypes.h - -// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr. -// The expression is a compile-time constant, and therefore can be -// used in defining new arrays, for example. -// -// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error -// -// "warning: division by zero in ..." -// -// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer. -// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays. -// -// The following comments are on the implementation details, and can -// be ignored by the users. -// -// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in -// the array) and sizeof(*(arr)) (the # of bytes in one array -// element). If the former is divisible by the latter, perhaps arr is -// indeed an array, in which case the division result is the # of -// elements in the array. Otherwise, arr cannot possibly be an array, -// and we generate a compiler error to prevent the code from -// compiling. -// -// Since the size of bool is implementation-defined, we need to cast -// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final -// result has type size_t. -// -// This macro is not perfect as it wrongfully accepts certain -// pointers, namely where the pointer size is divisible by the pointee -// size. Since all our code has to go through a 32-bit compiler, -// where a pointer is 4 bytes, this means all pointers to a type whose -// size is 3 or greater than 4 will be (righteously) rejected. -// -// Kudos to Jorg Brown for this simple and elegant implementation. - -#undef GOOGLE_ARRAYSIZE -#define GOOGLE_ARRAYSIZE(a) \ - ((sizeof(a) / sizeof(*(a))) / \ - static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) - -// The COMPILE_ASSERT macro can be used to verify that a compile time -// expression is true. For example, you could use it to verify the -// size of a static array: -// -// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, -// content_type_names_incorrect_size); -// -// or to make sure a struct is smaller than a certain size: -// -// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); -// -// The second argument to the macro is the name of the variable. If -// the expression is false, most compilers will issue a warning/error -// containing the name of the variable. - -namespace internal { - -template <bool> -struct CompileAssert { -}; - -} // namespace internal - -#undef GOOGLE_COMPILE_ASSERT -#define GOOGLE_COMPILE_ASSERT(expr, msg) \ - ::google::protobuf::internal::CompileAssert<(bool(expr))> \ - msg[bool(expr) ? 1 : -1]; \ - (void)msg - - -// Implementation details of COMPILE_ASSERT: -// -// - COMPILE_ASSERT works by defining an array type that has -1 -// elements (and thus is invalid) when the expression is false. -// -// - The simpler definition -// -// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] -// -// does not work, as gcc supports variable-length arrays whose sizes -// are determined at run-time (this is gcc's extension and not part -// of the C++ standard). As a result, gcc fails to reject the -// following code with the simple definition: -// -// int foo; -// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is -// // not a compile-time constant. -// -// - By using the type CompileAssert<(bool(expr))>, we ensures that -// expr is a compile-time constant. (Template arguments must be -// determined at compile-time.) -// -// - The outter parentheses in CompileAssert<(bool(expr))> are necessary -// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written -// -// CompileAssert<bool(expr)> -// -// instead, these compilers will refuse to compile -// -// COMPILE_ASSERT(5 > 0, some_message); -// -// (They seem to think the ">" in "5 > 0" marks the end of the -// template argument list.) -// -// - The array size is (bool(expr) ? 1 : -1), instead of simply -// -// ((expr) ? 1 : -1). -// -// This is to avoid running into a bug in MS VC 7.1, which -// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. - -// =================================================================== -// from google3/base/scoped_ptr.h - -namespace internal { - -// This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class, and its closely-related brethren, -// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. - -template <class C> class scoped_ptr; -template <class C> class scoped_array; - -// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr<T> owns the T object that it points to. -// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. -// -// The size of a scoped_ptr is small: -// sizeof(scoped_ptr<C>) == sizeof(C*) -template <class C> -class scoped_ptr { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with new. - explicit scoped_ptr(C* p = NULL) : ptr_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_ptr() { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != ptr_) { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - ptr_ = p; - } - } - - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - C* get() const { return ptr_; } - - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return ptr_ == p; } - bool operator!=(C* p) const { return ptr_ != p; } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - C* tmp = ptr_; - ptr_ = p2.ptr_; - p2.ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* retVal = ptr_; - ptr_ = NULL; - return retVal; - } - - private: - C* ptr_; - - // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't - // make sense, and if C2 == C, it still doesn't make sense because you should - // never have the same object owned by two different scoped_ptrs. - template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; - template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; - - // Disallow evil constructors - scoped_ptr(const scoped_ptr&); - void operator=(const scoped_ptr&); -}; - -// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate -// with new [] and the destructor deletes objects with delete []. -// -// As with scoped_ptr<C>, a scoped_array<C> either points to an object -// or is NULL. A scoped_array<C> owns the object that it points to. -// -// Size: sizeof(scoped_array<C>) == sizeof(C*) -template <class C> -class scoped_array { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_array. - // The input parameter must be allocated with new []. - explicit scoped_array(C* p = NULL) : array_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_array() { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != array_) { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - array_ = p; - } - } - - // Get one element of the current object. - // Will assert() if there is no current object, or index i is negative. - C& operator[](std::ptrdiff_t i) const { - assert(i >= 0); - assert(array_ != NULL); - return array_[i]; - } - - // Get a pointer to the zeroth element of the current object. - // If there is no current object, return NULL. - C* get() const { - return array_; - } - - // Comparison operators. - // These return whether two scoped_array refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return array_ == p; } - bool operator!=(C* p) const { return array_ != p; } - - // Swap two scoped arrays. - void swap(scoped_array& p2) { - C* tmp = array_; - array_ = p2.array_; - p2.array_ = tmp; - } - - // Release an array. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* retVal = array_; - array_ = NULL; - return retVal; - } - - private: - C* array_; - - // Forbid comparison of different scoped_array types. - template <class C2> bool operator==(scoped_array<C2> const& p2) const; - template <class C2> bool operator!=(scoped_array<C2> const& p2) const; - - // Disallow evil constructors - scoped_array(const scoped_array&); - void operator=(const scoped_array&); -}; - -} // namespace internal - -// We made these internal so that they would show up as such in the docs, -// but we don't want to stick "internal::" in front of them everywhere. -using internal::scoped_ptr; -using internal::scoped_array; - -// =================================================================== -// emulates google3/base/logging.h - -enum LogLevel { - LOGLEVEL_INFO, // Informational. This is never actually used by - // libprotobuf. - LOGLEVEL_WARNING, // Warns about issues that, although not technically a - // problem now, could cause problems in the future. For - // example, a // warning will be printed when parsing a - // message that is near the message size limit. - LOGLEVEL_ERROR, // An error occurred which should never happen during - // normal use. - LOGLEVEL_FATAL, // An error occurred from which the library cannot - // recover. This usually indicates a programming error - // in the code which calls the library, especially when - // compiled in debug mode. - -#ifdef NDEBUG - LOGLEVEL_DFATAL = LOGLEVEL_ERROR -#else - LOGLEVEL_DFATAL = LOGLEVEL_FATAL -#endif -}; - -class StringPiece; -namespace util { -class Status; -} -namespace internal { - -class LogFinisher; - -class LIBPROTOBUF_EXPORT LogMessage { - public: - LogMessage(LogLevel level, const char* filename, int line); - ~LogMessage(); - - LogMessage& operator<<(const std::string& value); - LogMessage& operator<<(const char* value); - LogMessage& operator<<(char value); - LogMessage& operator<<(int value); - LogMessage& operator<<(unsigned int value); - LogMessage& operator<<(long value); - LogMessage& operator<<(unsigned long value); - LogMessage& operator<<(long long value); - LogMessage& operator<<(unsigned long long value); - LogMessage& operator<<(double value); - LogMessage& operator<<(void* value); - LogMessage& operator<<(const StringPiece& value); - LogMessage& operator<<(const ::google::protobuf::util::Status& status); - - private: - friend class LogFinisher; - void Finish(); - - LogLevel level_; - const char* filename_; - int line_; - std::string message_; -}; - -// Used to make the entire "LOG(BLAH) << etc." expression have a void return -// type and print a newline after each message. -class LIBPROTOBUF_EXPORT LogFinisher { - public: - void operator=(LogMessage& other); -}; - -template<typename T> -bool IsOk(T status) { return status.ok(); } -template<> -inline bool IsOk(bool status) { return status; } - -} // namespace internal - -// Undef everything in case we're being mixed with some other Google library -// which already defined them itself. Presumably all Google libraries will -// support the same syntax for these so it should not be a big deal if they -// end up using our definitions instead. -#undef GOOGLE_LOG -#undef GOOGLE_LOG_IF - -#undef GOOGLE_CHECK -#undef GOOGLE_CHECK_OK -#undef GOOGLE_CHECK_EQ -#undef GOOGLE_CHECK_NE -#undef GOOGLE_CHECK_LT -#undef GOOGLE_CHECK_LE -#undef GOOGLE_CHECK_GT -#undef GOOGLE_CHECK_GE -#undef GOOGLE_CHECK_NOTNULL - -#undef GOOGLE_DLOG -#undef GOOGLE_DCHECK -#undef GOOGLE_DCHECK_OK -#undef GOOGLE_DCHECK_EQ -#undef GOOGLE_DCHECK_NE -#undef GOOGLE_DCHECK_LT -#undef GOOGLE_DCHECK_LE -#undef GOOGLE_DCHECK_GT -#undef GOOGLE_DCHECK_GE - -#define GOOGLE_LOG(LEVEL) \ - ::google::protobuf::internal::LogFinisher() = \ - ::google::protobuf::internal::LogMessage( \ - ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) -#define GOOGLE_LOG_IF(LEVEL, CONDITION) \ - !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) - -#define GOOGLE_CHECK(EXPRESSION) \ - GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " -#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) -#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) -#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) -#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) -#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) -#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) -#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) - -namespace internal { -template<typename T> -T* CheckNotNull(const char* /* file */, int /* line */, - const char* name, T* val) { - if (val == NULL) { - GOOGLE_LOG(FATAL) << name; - } - return val; -} -} // namespace internal -#define GOOGLE_CHECK_NOTNULL(A) \ - ::google::protobuf::internal::CheckNotNull(\ - __FILE__, __LINE__, "'" #A "' must not be NULL", (A)) - -#ifdef NDEBUG - -#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) - -#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) -#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) -#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) -#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) -#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) -#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) -#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) -#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) - -#else // NDEBUG - -#define GOOGLE_DLOG GOOGLE_LOG - -#define GOOGLE_DCHECK GOOGLE_CHECK -#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK -#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ -#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE -#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT -#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE -#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT -#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE - -#endif // !NDEBUG - -typedef void LogHandler(LogLevel level, const char* filename, int line, - const std::string& message); - -// The protobuf library sometimes writes warning and error messages to -// stderr. These messages are primarily useful for developers, but may -// also help end users figure out a problem. If you would prefer that -// these messages be sent somewhere other than stderr, call SetLogHandler() -// to set your own handler. This returns the old handler. Set the handler -// to NULL to ignore log messages (but see also LogSilencer, below). -// -// Obviously, SetLogHandler is not thread-safe. You should only call it -// at initialization time, and probably not from library code. If you -// simply want to suppress log messages temporarily (e.g. because you -// have some code that tends to trigger them frequently and you know -// the warnings are not important to you), use the LogSilencer class -// below. -LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); - -// Create a LogSilencer if you want to temporarily suppress all log -// messages. As long as any LogSilencer objects exist, non-fatal -// log messages will be discarded (the current LogHandler will *not* -// be called). Constructing a LogSilencer is thread-safe. You may -// accidentally suppress log messages occurring in another thread, but -// since messages are generally for debugging purposes only, this isn't -// a big deal. If you want to intercept log messages, use SetLogHandler(). -class LIBPROTOBUF_EXPORT LogSilencer { - public: - LogSilencer(); - ~LogSilencer(); -}; - -// =================================================================== -// emulates google3/base/callback.h - -// Abstract interface for a callback. When calling an RPC, you must provide -// a Closure to call when the procedure completes. See the Service interface -// in service.h. -// -// To automatically construct a Closure which calls a particular function or -// method with a particular set of parameters, use the NewCallback() function. -// Example: -// void FooDone(const FooResponse* response) { -// ... -// } -// -// void CallFoo() { -// ... -// // When done, call FooDone() and pass it a pointer to the response. -// Closure* callback = NewCallback(&FooDone, response); -// // Make the call. -// service->Foo(controller, request, response, callback); -// } -// -// Example that calls a method: -// class Handler { -// public: -// ... -// -// void FooDone(const FooResponse* response) { -// ... -// } -// -// void CallFoo() { -// ... -// // When done, call FooDone() and pass it a pointer to the response. -// Closure* callback = NewCallback(this, &Handler::FooDone, response); -// // Make the call. -// service->Foo(controller, request, response, callback); -// } -// }; -// -// Currently NewCallback() supports binding zero, one, or two arguments. -// -// Callbacks created with NewCallback() automatically delete themselves when -// executed. They should be used when a callback is to be called exactly -// once (usually the case with RPC callbacks). If a callback may be called -// a different number of times (including zero), create it with -// NewPermanentCallback() instead. You are then responsible for deleting the -// callback (using the "delete" keyword as normal). -// -// Note that NewCallback() is a bit touchy regarding argument types. Generally, -// the values you provide for the parameter bindings must exactly match the -// types accepted by the callback function. For example: -// void Foo(string s); -// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string -// NewCallback(&Foo, string("foo")); // WORKS -// Also note that the arguments cannot be references: -// void Foo(const string& s); -// string my_str; -// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes. -// However, correctly-typed pointers will work just fine. -class LIBPROTOBUF_EXPORT Closure { - public: - Closure() {} - virtual ~Closure(); - - virtual void Run() = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); -}; - -template<typename R, typename A1> -class LIBPROTOBUF_EXPORT ResultCallback1 { - public: - ResultCallback1() {} - virtual ~ResultCallback1() {} - - virtual R Run(A1) = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); -}; - -template<typename R, typename A1, typename A2> -class LIBPROTOBUF_EXPORT ResultCallback2 { - public: - ResultCallback2() {} - virtual ~ResultCallback2() {} - - virtual R Run(A1,A2) = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); -}; - -namespace internal { - -class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { - public: - typedef void (*FunctionType)(); - - FunctionClosure0(FunctionType function, bool self_deleting) - : function_(function), self_deleting_(self_deleting) {} - ~FunctionClosure0(); - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - function_(); - if (needs_delete) delete this; - } - - private: - FunctionType function_; - bool self_deleting_; -}; - -template <typename Class> -class MethodClosure0 : public Closure { - public: - typedef void (Class::*MethodType)(); - - MethodClosure0(Class* object, MethodType method, bool self_deleting) - : object_(object), method_(method), self_deleting_(self_deleting) {} - ~MethodClosure0() {} - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - (object_->*method_)(); - if (needs_delete) delete this; - } - - private: - Class* object_; - MethodType method_; - bool self_deleting_; -}; - -template <typename Arg1> -class FunctionClosure1 : public Closure { - public: - typedef void (*FunctionType)(Arg1 arg1); - - FunctionClosure1(FunctionType function, bool self_deleting, - Arg1 arg1) - : function_(function), self_deleting_(self_deleting), - arg1_(arg1) {} - ~FunctionClosure1() {} - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - function_(arg1_); - if (needs_delete) delete this; - } - - private: - FunctionType function_; - bool self_deleting_; - Arg1 arg1_; -}; - -template <typename Class, typename Arg1> -class MethodClosure1 : public Closure { - public: - typedef void (Class::*MethodType)(Arg1 arg1); - - MethodClosure1(Class* object, MethodType method, bool self_deleting, - Arg1 arg1) - : object_(object), method_(method), self_deleting_(self_deleting), - arg1_(arg1) {} - ~MethodClosure1() {} - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - (object_->*method_)(arg1_); - if (needs_delete) delete this; - } - - private: - Class* object_; - MethodType method_; - bool self_deleting_; - Arg1 arg1_; -}; - -template <typename Arg1, typename Arg2> -class FunctionClosure2 : public Closure { - public: - typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2); - - FunctionClosure2(FunctionType function, bool self_deleting, - Arg1 arg1, Arg2 arg2) - : function_(function), self_deleting_(self_deleting), - arg1_(arg1), arg2_(arg2) {} - ~FunctionClosure2() {} - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - function_(arg1_, arg2_); - if (needs_delete) delete this; - } - - private: - FunctionType function_; - bool self_deleting_; - Arg1 arg1_; - Arg2 arg2_; -}; - -template <typename Class, typename Arg1, typename Arg2> -class MethodClosure2 : public Closure { - public: - typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2); - - MethodClosure2(Class* object, MethodType method, bool self_deleting, - Arg1 arg1, Arg2 arg2) - : object_(object), method_(method), self_deleting_(self_deleting), - arg1_(arg1), arg2_(arg2) {} - ~MethodClosure2() {} - - void Run() { - bool needs_delete = self_deleting_; // read in case callback deletes - (object_->*method_)(arg1_, arg2_); - if (needs_delete) delete this; - } - - private: - Class* object_; - MethodType method_; - bool self_deleting_; - Arg1 arg1_; - Arg2 arg2_; -}; - -template<typename R, typename Arg1> -class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> { - public: - typedef R (*FunctionType)(Arg1 arg1); - - FunctionResultCallback_0_1(FunctionType function, bool self_deleting) - : function_(function), self_deleting_(self_deleting) {} - ~FunctionResultCallback_0_1() {} - - R Run(Arg1 a1) { - bool needs_delete = self_deleting_; // read in case callback deletes - R result = function_(a1); - if (needs_delete) delete this; - return result; - } - - private: - FunctionType function_; - bool self_deleting_; -}; - -template<typename R, typename P1, typename A1> -class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> { - public: - typedef R (*FunctionType)(P1, A1); - - FunctionResultCallback_1_1(FunctionType function, bool self_deleting, - P1 p1) - : function_(function), self_deleting_(self_deleting), p1_(p1) {} - ~FunctionResultCallback_1_1() {} - - R Run(A1 a1) { - bool needs_delete = self_deleting_; // read in case callback deletes - R result = function_(p1_, a1); - if (needs_delete) delete this; - return result; - } - - private: - FunctionType function_; - bool self_deleting_; - P1 p1_; -}; - -// Duplicate this again in the type_traits.h, due to dependency problems. -template <class T> struct internal_remove_reference; -template<typename T> struct internal_remove_reference { typedef T type; }; -template<typename T> struct internal_remove_reference<T&> { typedef T type; }; - -template <typename T> -struct InternalConstRef { - typedef typename internal_remove_reference<T>::type base_type; - typedef const base_type& type; -}; - -template <typename R, typename T, typename P1, typename P2, typename P3, - typename P4, typename P5, typename A1, typename A2> -class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> { - public: - typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); - MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, - P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) - : object_(object), - method_(method), - self_deleting_(self_deleting), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5) {} - ~MethodResultCallback_5_2() {} - - R Run(A1 a1, A2 a2) { - bool needs_delete = self_deleting_; - R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); - if (needs_delete) delete this; - return result; - } - - private: - T* object_; - MethodType method_; - bool self_deleting_; - typename internal_remove_reference<P1>::type p1_; - typename internal_remove_reference<P2>::type p2_; - typename internal_remove_reference<P3>::type p3_; - typename internal_remove_reference<P4>::type p4_; - typename internal_remove_reference<P5>::type p5_; -}; - -} // namespace internal - -// See Closure. -inline Closure* NewCallback(void (*function)()) { - return new internal::FunctionClosure0(function, true); -} - -// See Closure. -inline Closure* NewPermanentCallback(void (*function)()) { - return new internal::FunctionClosure0(function, false); -} - -// See Closure. -template <typename Class> -inline Closure* NewCallback(Class* object, void (Class::*method)()) { - return new internal::MethodClosure0<Class>(object, method, true); -} - -// See Closure. -template <typename Class> -inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) { - return new internal::MethodClosure0<Class>(object, method, false); -} - -// See Closure. -template <typename Arg1> -inline Closure* NewCallback(void (*function)(Arg1), - Arg1 arg1) { - return new internal::FunctionClosure1<Arg1>(function, true, arg1); -} - -// See Closure. -template <typename Arg1> -inline Closure* NewPermanentCallback(void (*function)(Arg1), - Arg1 arg1) { - return new internal::FunctionClosure1<Arg1>(function, false, arg1); -} - -// See Closure. -template <typename Class, typename Arg1> -inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1), - Arg1 arg1) { - return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1); -} - -// See Closure. -template <typename Class, typename Arg1> -inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1), - Arg1 arg1) { - return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1); -} - -// See Closure. -template <typename Arg1, typename Arg2> -inline Closure* NewCallback(void (*function)(Arg1, Arg2), - Arg1 arg1, Arg2 arg2) { - return new internal::FunctionClosure2<Arg1, Arg2>( - function, true, arg1, arg2); -} - -// See Closure. -template <typename Arg1, typename Arg2> -inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2), - Arg1 arg1, Arg2 arg2) { - return new internal::FunctionClosure2<Arg1, Arg2>( - function, false, arg1, arg2); -} - -// See Closure. -template <typename Class, typename Arg1, typename Arg2> -inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2), - Arg1 arg1, Arg2 arg2) { - return new internal::MethodClosure2<Class, Arg1, Arg2>( - object, method, true, arg1, arg2); -} - -// See Closure. -template <typename Class, typename Arg1, typename Arg2> -inline Closure* NewPermanentCallback( - Class* object, void (Class::*method)(Arg1, Arg2), - Arg1 arg1, Arg2 arg2) { - return new internal::MethodClosure2<Class, Arg1, Arg2>( - object, method, false, arg1, arg2); -} - -// See ResultCallback1 -template<typename R, typename A1> -inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) { - return new internal::FunctionResultCallback_0_1<R, A1>(function, true); -} - -// See ResultCallback1 -template<typename R, typename A1> -inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) { - return new internal::FunctionResultCallback_0_1<R, A1>(function, false); -} - -// See ResultCallback1 -template<typename R, typename P1, typename A1> -inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) { - return new internal::FunctionResultCallback_1_1<R, P1, A1>( - function, true, p1); -} - -// See ResultCallback1 -template<typename R, typename P1, typename A1> -inline ResultCallback1<R, A1>* NewPermanentCallback( - R (*function)(P1, A1), P1 p1) { - return new internal::FunctionResultCallback_1_1<R, P1, A1>( - function, false, p1); -} - -// See MethodResultCallback_5_2 -template <typename R, typename T, typename P1, typename P2, typename P3, - typename P4, typename P5, typename A1, typename A2> -inline ResultCallback2<R, A1, A2>* NewPermanentCallback( - T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), - typename internal::InternalConstRef<P1>::type p1, - typename internal::InternalConstRef<P2>::type p2, - typename internal::InternalConstRef<P3>::type p3, - typename internal::InternalConstRef<P4>::type p4, - typename internal::InternalConstRef<P5>::type p5) { - return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1, - A2>(object, function, false, p1, - p2, p3, p4, p5); -} - -// A function which does nothing. Useful for creating no-op callbacks, e.g.: -// Closure* nothing = NewCallback(&DoNothing); -void LIBPROTOBUF_EXPORT DoNothing(); - -// =================================================================== -// emulates google3/base/mutex.h - -namespace internal { - -// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T -// may hold a mutex at a given time. If T attempts to Lock() the same Mutex -// while holding it, T will deadlock. -class LIBPROTOBUF_EXPORT Mutex { - public: - // Create a Mutex that is not held by anybody. - Mutex(); - - // Destructor - ~Mutex(); - - // Block if necessary until this Mutex is free, then acquire it exclusively. - void Lock(); - - // Release this Mutex. Caller must hold it exclusively. - void Unlock(); - - // Crash if this Mutex is not held exclusively by this thread. - // May fail to crash when it should; will never crash when it should not. - void AssertHeld(); - - private: - struct Internal; - Internal* mInternal; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex); -}; - -// Undefine the macros to workaround the conflicts with Google internal -// MutexLock implementation. -// TODO(liujisi): Remove the undef once internal macros are removed. -#undef MutexLock -#undef ReaderMutexLock -#undef WriterMutexLock -#undef MutexLockMaybe - -// MutexLock(mu) acquires mu when constructed and releases it when destroyed. -class LIBPROTOBUF_EXPORT MutexLock { - public: - explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); } - ~MutexLock() { this->mu_->Unlock(); } - private: - Mutex *const mu_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock); -}; - -// TODO(kenton): Implement these? Hard to implement portably. -typedef MutexLock ReaderMutexLock; -typedef MutexLock WriterMutexLock; - -// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL. -class LIBPROTOBUF_EXPORT MutexLockMaybe { - public: - explicit MutexLockMaybe(Mutex *mu) : - mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } } - ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } } - private: - Mutex *const mu_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); -}; - -#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) -template<typename T> -class ThreadLocalStorage { - public: - ThreadLocalStorage() { - pthread_key_create(&key_, &ThreadLocalStorage::Delete); - } - ~ThreadLocalStorage() { - pthread_key_delete(key_); - } - T* Get() { - T* result = static_cast<T*>(pthread_getspecific(key_)); - if (result == NULL) { - result = new T(); - pthread_setspecific(key_, result); - } - return result; - } - private: - static void Delete(void* value) { - delete static_cast<T*>(value); - } - pthread_key_t key_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage); -}; -#endif - -} // namespace internal - -// We made these internal so that they would show up as such in the docs, -// but we don't want to stick "internal::" in front of them everywhere. -using internal::Mutex; -using internal::MutexLock; -using internal::ReaderMutexLock; -using internal::WriterMutexLock; -using internal::MutexLockMaybe; // =================================================================== // from google3/util/utf8/public/unilib.h @@ -1423,114 +145,6 @@ LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); } // namespace internal -// =================================================================== -// from google3/base/port.h - -// The following guarantees declaration of the byte swap functions, and -// defines __BYTE_ORDER for MSVC -#ifdef _MSC_VER -#include <stdlib.h> // NOLINT(build/include) -#define __BYTE_ORDER __LITTLE_ENDIAN -#define bswap_16(x) _byteswap_ushort(x) -#define bswap_32(x) _byteswap_ulong(x) -#define bswap_64(x) _byteswap_uint64(x) - -#elif defined(__APPLE__) -// Mac OS X / Darwin features -#include <libkern/OSByteOrder.h> -#define bswap_16(x) OSSwapInt16(x) -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) - -#elif defined(__GLIBC__) || defined(__CYGWIN__) -#include <byteswap.h> // IWYU pragma: export - -#else - -static inline uint16 bswap_16(uint16 x) { - return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); -} -#define bswap_16(x) bswap_16(x) -static inline uint32 bswap_32(uint32 x) { - return (((x & 0xFF) << 24) | - ((x & 0xFF00) << 8) | - ((x & 0xFF0000) >> 8) | - ((x & 0xFF000000) >> 24)); -} -#define bswap_32(x) bswap_32(x) -static inline uint64 bswap_64(uint64 x) { - return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) | - ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) | - ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) | - ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) | - ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) | - ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) | - ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) | - ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56)); -} -#define bswap_64(x) bswap_64(x) - -#endif - -// =================================================================== -// from google3/util/endian/endian.h -LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); - -class BigEndian { - public: -#ifdef PROTOBUF_LITTLE_ENDIAN - - static uint16 FromHost16(uint16 x) { return bswap_16(x); } - static uint16 ToHost16(uint16 x) { return bswap_16(x); } - - static uint32 FromHost32(uint32 x) { return bswap_32(x); } - static uint32 ToHost32(uint32 x) { return bswap_32(x); } - - static uint64 FromHost64(uint64 x) { return bswap_64(x); } - static uint64 ToHost64(uint64 x) { return bswap_64(x); } - - static bool IsLittleEndian() { return true; } - -#else - - static uint16 FromHost16(uint16 x) { return x; } - static uint16 ToHost16(uint16 x) { return x; } - - static uint32 FromHost32(uint32 x) { return x; } - static uint32 ToHost32(uint32 x) { return x; } - - static uint64 FromHost64(uint64 x) { return x; } - static uint64 ToHost64(uint64 x) { return x; } - - static bool IsLittleEndian() { return false; } - -#endif /* ENDIAN */ - - // Functions to do unaligned loads and stores in big-endian order. - static uint16 Load16(const void *p) { - return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); - } - - static void Store16(void *p, uint16 v) { - GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); - } - - static uint32 Load32(const void *p) { - return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); - } - - static void Store32(void *p, uint32 v) { - GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); - } - - static uint64 Load64(const void *p) { - return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); - } - - static void Store64(void *p, uint64 v) { - GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); - } -}; // =================================================================== // Shutdown support. diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index 4da8a5d8..9a6b217a 100755 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -37,12 +37,117 @@ #include <string.h> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/pbconfig.h> + +#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 +#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 + +// Use C++11 unordered_{map|set} if available. Otherwise, libc++ always support +// unordered_{map|set} +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) || \ + defined(_LIBCPP_VERSION) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH + +// For XCode >= 4.6: the compiler is clang with libc++. +// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. +// libc++ provides <unordered_map> and friends even in non C++11 mode, +// and it does not provide the tr1 library. Therefore the following macro +// checks against this special case. +// Note that we should not test the __APPLE_CC__ version number or the +// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in +// which case <unordered_map> is not compilable without -std=c++11 +#elif defined(__APPLE_CC__) +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# else +// Not tested for gcc < 4... These setting can compile under 4.2.1 though. +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx +# include <ext/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include <ext/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for gcc. +#elif defined(__GNUC__) +// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the +// instructions from: +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# elif __GNUC__ >= 3 +# include <backward/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include <backward/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later +# endif +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE +# include <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for MSC. +// Apparently Microsoft decided to move hash_map *back* to the std namespace in +// MSVC 2010: +// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx +// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That +// said, use unordered_map for MSVC 2010 and beyond is our safest bet. +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 // Since Visual Studio 2010 +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare +# elif _MSC_VER >= 1500 // Since Visual Studio 2008 +# define GOOGLE_PROTOBUF_HAS_TR1 +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# elif _MSC_VER >= 1310 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext +# include <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# include <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# endif + +// **ADD NEW COMPILERS SUPPORT HERE.** +// For other compilers, undefine the macro and fallback to use std::map, in +// google/protobuf/stubs/hash.h +#else +# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP +# undef GOOGLE_PROTOBUF_HAVE_HASH_SET +#endif + +#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# include <unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# include <unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#elif defined(GOOGLE_PROTOBUF_HAS_TR1) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 +# include <tr1/unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# include <tr1/unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#endif + +#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH +#undef GOOGLE_PROTOBUF_HAS_TR1 #if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) -#include GOOGLE_PROTOBUF_HASH_MAP_H -#include GOOGLE_PROTOBUF_HASH_SET_H #else #define GOOGLE_PROTOBUF_MISSING_HASH #include <map> @@ -92,13 +197,13 @@ template <typename Key, typename Data, typename HashFcn = hash<Key>, typename EqualKey = std::equal_to<Key>, typename Alloc = std::allocator< std::pair<const Key, Data> > > -class hash_map : public std::map<Key, Data, HashFcn, EqualKey, Alloc> { - typedef std::map<Key, Data, HashFcn, EqualKey, Alloc> BaseClass; +class hash_map : public std::map<Key, Data, HashFcn, Alloc> { + typedef std::map<Key, Data, HashFcn, Alloc> BaseClass; public: hash_map(int a = 0, const HashFcn& b = HashFcn(), const EqualKey& c = EqualKey(), - const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} + const Alloc& d = Alloc()) : BaseClass(b, d) {} }; template <typename Key, diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h new file mode 100644 index 00000000..330d33d2 --- /dev/null +++ b/src/google/protobuf/stubs/logging.h @@ -0,0 +1,235 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_ +#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_ + +#include <google/protobuf/stubs/macros.h> +#include <google/protobuf/stubs/port.h> + +// =================================================================== +// emulates google3/base/logging.h + +namespace google { +namespace protobuf { + +enum LogLevel { + LOGLEVEL_INFO, // Informational. This is never actually used by + // libprotobuf. + LOGLEVEL_WARNING, // Warns about issues that, although not technically a + // problem now, could cause problems in the future. For + // example, a // warning will be printed when parsing a + // message that is near the message size limit. + LOGLEVEL_ERROR, // An error occurred which should never happen during + // normal use. + LOGLEVEL_FATAL, // An error occurred from which the library cannot + // recover. This usually indicates a programming error + // in the code which calls the library, especially when + // compiled in debug mode. + +#ifdef NDEBUG + LOGLEVEL_DFATAL = LOGLEVEL_ERROR +#else + LOGLEVEL_DFATAL = LOGLEVEL_FATAL +#endif +}; + +class StringPiece; +namespace util { +class Status; +} +namespace internal { + +class LogFinisher; + +class LIBPROTOBUF_EXPORT LogMessage { + public: + LogMessage(LogLevel level, const char* filename, int line); + ~LogMessage(); + + LogMessage& operator<<(const std::string& value); + LogMessage& operator<<(const char* value); + LogMessage& operator<<(char value); + LogMessage& operator<<(int value); + LogMessage& operator<<(unsigned int value); + LogMessage& operator<<(long value); + LogMessage& operator<<(unsigned long value); + LogMessage& operator<<(long long value); + LogMessage& operator<<(unsigned long long value); + LogMessage& operator<<(double value); + LogMessage& operator<<(void* value); + LogMessage& operator<<(const StringPiece& value); + LogMessage& operator<<(const ::google::protobuf::util::Status& status); + + private: + friend class LogFinisher; + void Finish(); + + LogLevel level_; + const char* filename_; + int line_; + std::string message_; +}; + +// Used to make the entire "LOG(BLAH) << etc." expression have a void return +// type and print a newline after each message. +class LIBPROTOBUF_EXPORT LogFinisher { + public: + void operator=(LogMessage& other); +}; + +template<typename T> +bool IsOk(T status) { return status.ok(); } +template<> +inline bool IsOk(bool status) { return status; } + +} // namespace internal + +// Undef everything in case we're being mixed with some other Google library +// which already defined them itself. Presumably all Google libraries will +// support the same syntax for these so it should not be a big deal if they +// end up using our definitions instead. +#undef GOOGLE_LOG +#undef GOOGLE_LOG_IF + +#undef GOOGLE_CHECK +#undef GOOGLE_CHECK_OK +#undef GOOGLE_CHECK_EQ +#undef GOOGLE_CHECK_NE +#undef GOOGLE_CHECK_LT +#undef GOOGLE_CHECK_LE +#undef GOOGLE_CHECK_GT +#undef GOOGLE_CHECK_GE +#undef GOOGLE_CHECK_NOTNULL + +#undef GOOGLE_DLOG +#undef GOOGLE_DCHECK +#undef GOOGLE_DCHECK_OK +#undef GOOGLE_DCHECK_EQ +#undef GOOGLE_DCHECK_NE +#undef GOOGLE_DCHECK_LT +#undef GOOGLE_DCHECK_LE +#undef GOOGLE_DCHECK_GT +#undef GOOGLE_DCHECK_GE + +#define GOOGLE_LOG(LEVEL) \ + ::google::protobuf::internal::LogFinisher() = \ + ::google::protobuf::internal::LogMessage( \ + ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) +#define GOOGLE_LOG_IF(LEVEL, CONDITION) \ + !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) + +#define GOOGLE_CHECK(EXPRESSION) \ + GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) +#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) +#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) +#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) +#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) +#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) +#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) + +namespace internal { +template<typename T> +T* CheckNotNull(const char* /* file */, int /* line */, + const char* name, T* val) { + if (val == NULL) { + GOOGLE_LOG(FATAL) << name; + } + return val; +} +} // namespace internal +#define GOOGLE_CHECK_NOTNULL(A) \ + ::google::protobuf::internal::CheckNotNull(\ + __FILE__, __LINE__, "'" #A "' must not be NULL", (A)) + +#ifdef NDEBUG + +#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) + +#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) +#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) +#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) +#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) +#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) +#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) +#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) + +#else // NDEBUG + +#define GOOGLE_DLOG GOOGLE_LOG + +#define GOOGLE_DCHECK GOOGLE_CHECK +#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK +#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ +#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE +#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT +#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE +#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT +#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE + +#endif // !NDEBUG + +typedef void LogHandler(LogLevel level, const char* filename, int line, + const std::string& message); + +// The protobuf library sometimes writes warning and error messages to +// stderr. These messages are primarily useful for developers, but may +// also help end users figure out a problem. If you would prefer that +// these messages be sent somewhere other than stderr, call SetLogHandler() +// to set your own handler. This returns the old handler. Set the handler +// to NULL to ignore log messages (but see also LogSilencer, below). +// +// Obviously, SetLogHandler is not thread-safe. You should only call it +// at initialization time, and probably not from library code. If you +// simply want to suppress log messages temporarily (e.g. because you +// have some code that tends to trigger them frequently and you know +// the warnings are not important to you), use the LogSilencer class +// below. +LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); + +// Create a LogSilencer if you want to temporarily suppress all log +// messages. As long as any LogSilencer objects exist, non-fatal +// log messages will be discarded (the current LogHandler will *not* +// be called). Constructing a LogSilencer is thread-safe. You may +// accidentally suppress log messages occurring in another thread, but +// since messages are generally for debugging purposes only, this isn't +// a big deal. If you want to intercept log messages, use SetLogHandler(). +class LIBPROTOBUF_EXPORT LogSilencer { + public: + LogSilencer(); + ~LogSilencer(); +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_ diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h new file mode 100644 index 00000000..0e9a9ec1 --- /dev/null +++ b/src/google/protobuf/stubs/macros.h @@ -0,0 +1,168 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_MACROS_H__ +#define GOOGLE_PROTOBUF_MACROS_H__ + +#include <google/protobuf/stubs/port.h> + +namespace google { +namespace protobuf { + +#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS +#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS +#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// =================================================================== +// from google3/base/basictypes.h + +// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. +// +// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer. +// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +// +// Kudos to Jorg Brown for this simple and elegant implementation. + +#undef GOOGLE_ARRAYSIZE +#define GOOGLE_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +namespace internal { + +template <bool> +struct CompileAssert { +}; + +} // namespace internal + +#undef GOOGLE_COMPILE_ASSERT +#if __cplusplus >= 201103L +#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) +#else +#define GOOGLE_COMPILE_ASSERT(expr, msg) \ + ::google::protobuf::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1]; \ + (void)msg +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert<bool(expr)> +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. +#endif // __cplusplus >= 201103L + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_MACROS_H__ diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h index 87ca5e91..99c4d452 100644 --- a/src/google/protobuf/stubs/mathutil.h +++ b/src/google/protobuf/stubs/mathutil.h @@ -34,6 +34,7 @@ #include <math.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/mathlimits.h> namespace google { diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h new file mode 100644 index 00000000..7ef1cb69 --- /dev/null +++ b/src/google/protobuf/stubs/mutex.h @@ -0,0 +1,148 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_ +#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_ + +#ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL +#include <pthread.h> +#endif + +#include <google/protobuf/stubs/macros.h> + +// =================================================================== +// emulates google3/base/mutex.h +namespace google { +namespace protobuf { +namespace internal { + +// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T +// may hold a mutex at a given time. If T attempts to Lock() the same Mutex +// while holding it, T will deadlock. +class LIBPROTOBUF_EXPORT Mutex { + public: + // Create a Mutex that is not held by anybody. + Mutex(); + + // Destructor + ~Mutex(); + + // Block if necessary until this Mutex is free, then acquire it exclusively. + void Lock(); + + // Release this Mutex. Caller must hold it exclusively. + void Unlock(); + + // Crash if this Mutex is not held exclusively by this thread. + // May fail to crash when it should; will never crash when it should not. + void AssertHeld(); + + private: + struct Internal; + Internal* mInternal; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex); +}; + +// Undefine the macros to workaround the conflicts with Google internal +// MutexLock implementation. +// TODO(liujisi): Remove the undef once internal macros are removed. +#undef MutexLock +#undef ReaderMutexLock +#undef WriterMutexLock +#undef MutexLockMaybe + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class LIBPROTOBUF_EXPORT MutexLock { + public: + explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); } + ~MutexLock() { this->mu_->Unlock(); } + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock); +}; + +// TODO(kenton): Implement these? Hard to implement portably. +typedef MutexLock ReaderMutexLock; +typedef MutexLock WriterMutexLock; + +// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL. +class LIBPROTOBUF_EXPORT MutexLockMaybe { + public: + explicit MutexLockMaybe(Mutex *mu) : + mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } } + ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } } + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); +}; + +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) +template<typename T> +class ThreadLocalStorage { + public: + ThreadLocalStorage() { + pthread_key_create(&key_, &ThreadLocalStorage::Delete); + } + ~ThreadLocalStorage() { + pthread_key_delete(key_); + } + T* Get() { + T* result = static_cast<T*>(pthread_getspecific(key_)); + if (result == NULL) { + result = new T(); + pthread_setspecific(key_, result); + } + return result; + } + private: + static void Delete(void* value) { + delete static_cast<T*>(value); + } + pthread_key_t key_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage); +}; +#endif + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::Mutex; +using internal::MutexLock; +using internal::ReaderMutexLock; +using internal::WriterMutexLock; +using internal::MutexLockMaybe; + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_ diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h index cc62bbaa..1f082c37 100644 --- a/src/google/protobuf/stubs/once.h +++ b/src/google/protobuf/stubs/once.h @@ -79,6 +79,7 @@ #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ #include <google/protobuf/stubs/atomicops.h> +#include <google/protobuf/stubs/callback.h> #include <google/protobuf/stubs/common.h> namespace google { diff --git a/src/google/protobuf/stubs/pbconfig.h b/src/google/protobuf/stubs/pbconfig.h deleted file mode 100644 index 0f21c560..00000000 --- a/src/google/protobuf/stubs/pbconfig.h +++ /dev/null @@ -1,142 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// 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. - -#ifndef GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ -#define GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ - -#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 -#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 - -// Use C++11 unordered_{map|set} if available. -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) -# define GOOGLE_PROTOBUF_HAS_CXX11_HASH - -// For XCode >= 4.6: the compiler is clang with libc++. -// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. -// libc++ provides <unordered_map> and friends even in non C++11 mode, -// and it does not provide the tr1 library. Therefore the following macro -// checks against this special case. -// Note that we should not test the __APPLE_CC__ version number or the -// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in -// which case <unordered_map> is not compilable without -std=c++11 -#elif defined(__APPLE_CC__) -# if defined(_LIBCPP_VERSION) -# define GOOGLE_PROTOBUF_HAS_CXX11_HASH -# elif __GNUC__ >= 4 -# define GOOGLE_PROTOBUF_HAS_TR1 -# else -// Not tested for gcc < 4... These setting can compile under 4.2.1 though. -# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx -# define GOOGLE_PROTOBUF_HASH_MAP_H <ext/hash_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# define GOOGLE_PROTOBUF_HASH_SET_H <ext/hash_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# endif - -// Version checks for gcc. -#elif defined(__GNUC__) -// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the -// instructions from: -// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html -# if __GNUC__ >= 4 -# define GOOGLE_PROTOBUF_HAS_TR1 -# elif __GNUC__ >= 3 -# define GOOGLE_PROTOBUF_HASH_MAP_H <backward/hash_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# define GOOGLE_PROTOBUF_HASH_SET_H <backward/hash_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later -# endif -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE -# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# endif - -// Version checks for MSC. -// Apparently Microsoft decided to move hash_map *back* to the std namespace in -// MSVC 2010: -// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx -// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That -// said, use unordered_map for MSVC 2010 and beyond is our safest bet. -#elif defined(_MSC_VER) -# if _MSC_VER >= 1600 // Since Visual Studio 2010 -# define GOOGLE_PROTOBUF_HAS_CXX11_HASH -# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare -# elif _MSC_VER >= 1500 // Since Visual Studio 2008 -# define GOOGLE_PROTOBUF_HAS_TR1 -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# elif _MSC_VER >= 1310 -# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext -# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std -# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# endif - -// **ADD NEW COMPILERS SUPPORT HERE.** -// For other compilers, undefine the macro and fallback to use std::map, in -// google/protobuf/stubs/hash.h -#else -# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP -# undef GOOGLE_PROTOBUF_HAVE_HASH_SET -#endif - -#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std -# define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -# define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#elif defined(GOOGLE_PROTOBUF_HAS_TR1) -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 -# define GOOGLE_PROTOBUF_HASH_MAP_H <tr1/unordered_map> -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -# define GOOGLE_PROTOBUF_HASH_SET_H <tr1/unordered_set> -# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#endif - -#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH -#undef GOOGLE_PROTOBUF_HAS_TR1 - -#endif // GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h new file mode 100644 index 00000000..8a5d1a13 --- /dev/null +++ b/src/google/protobuf/stubs/port.h @@ -0,0 +1,382 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_PORT_H_ +#define GOOGLE_PROTOBUF_STUBS_PORT_H_ + +#include <assert.h> +#include <stdlib.h> +#include <cstddef> +#include <string> +#include <string.h> +#if defined(__osf__) +// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of +// what stdint.h would define. +#include <inttypes.h> +#elif !defined(_MSC_VER) +#include <stdint.h> +#endif + +#undef PROTOBUF_LITTLE_ENDIAN +#ifdef _MSC_VER + // Assuming windows is always little-endian. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 + // If MSVC has "/RTCc" set, it will complain about truncating casts at + // runtime. This file contains some intentional truncating casts. + #pragma runtime_checks("c", off) + #endif +#else + #include <sys/param.h> // __BYTE_ORDER + #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif +#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) + #ifdef LIBPROTOBUF_EXPORTS + #define LIBPROTOBUF_EXPORT __declspec(dllexport) + #else + #define LIBPROTOBUF_EXPORT __declspec(dllimport) + #endif + #ifdef LIBPROTOC_EXPORTS + #define LIBPROTOC_EXPORT __declspec(dllexport) + #else + #define LIBPROTOC_EXPORT __declspec(dllimport) + #endif +#else + #define LIBPROTOBUF_EXPORT + #define LIBPROTOC_EXPORT +#endif + +// =================================================================== +// from google3/base/port.h +namespace google { +namespace protobuf { + +typedef unsigned int uint; + +#ifdef _MSC_VER +typedef signed __int8 int8; +typedef __int16 int16; +typedef __int32 int32; +typedef __int64 int64; + +typedef unsigned __int8 uint8; +typedef unsigned __int16 uint16; +typedef unsigned __int32 uint32; +typedef unsigned __int64 uint64; +#else +typedef signed char int8; +typedef short int16; +typedef int int32; +// NOTE: This should be "long long" for consistency with upstream, but +// something is stacked against this particular type for 64bit hashing. +// Switching it causes an obvious missing hash function (with an unobvious +// cause) when building the tests. +typedef int64_t int64; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +// NOTE: This should be "unsigned long long" for consistency with upstream, but +// something is stacked against this particular type for 64bit hashing. +// Switching it causes an obvious missing hash function (with an unobvious +// cause) when building the tests. +typedef uint64_t uint64; +#endif + +// long long macros to be used because gcc and vc++ use different suffixes, +// and different size specifiers in format strings +#undef GOOGLE_LONGLONG +#undef GOOGLE_ULONGLONG +#undef GOOGLE_LL_FORMAT + +#ifdef _MSC_VER +#define GOOGLE_LONGLONG(x) x##I64 +#define GOOGLE_ULONGLONG(x) x##UI64 +#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...) +#else +#define GOOGLE_LONGLONG(x) x##LL +#define GOOGLE_ULONGLONG(x) x##ULL +#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also. +#endif + +static const int32 kint32max = 0x7FFFFFFF; +static const int32 kint32min = -kint32max - 1; +static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF); +static const int64 kint64min = -kint64max - 1; +static const uint32 kuint32max = 0xFFFFFFFFu; +static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); + +// ------------------------------------------------------------------- +// Annotations: Some parts of the code have been annotated in ways that might +// be useful to some compilers or tools, but are not supported universally. +// You can #define these annotations yourself if the default implementation +// is not right for you. + +#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force inline. +// Introduced in gcc 3.1. +#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) +#else +// Other compilers will have to figure it out for themselves. +#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#endif +#endif + +#ifndef GOOGLE_ATTRIBUTE_NOINLINE +#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force not inline. +// Introduced in gcc 3.1. +#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline)) +#else +// Other compilers will have to figure it out for themselves. +#define GOOGLE_ATTRIBUTE_NOINLINE +#endif +#endif + +#ifndef GOOGLE_ATTRIBUTE_DEPRECATED +#ifdef __GNUC__ +// If the method/variable/type is used anywhere, produce a warning. +#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated)) +#else +#define GOOGLE_ATTRIBUTE_DEPRECATED +#endif +#endif + +#ifndef GOOGLE_PREDICT_TRUE +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#else +#define GOOGLE_PREDICT_TRUE +#endif +#endif + +#ifndef GOOGLE_PREDICT_FALSE +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#else +#define GOOGLE_PREDICT_FALSE +#endif +#endif + +// Delimits a block of code which may write to memory which is simultaneously +// written by other threads, but which has been determined to be thread-safe +// (e.g. because it is an idempotent write). +#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN +#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN() +#endif +#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END +#define GOOGLE_SAFE_CONCURRENT_WRITES_END() +#endif + +#if defined(__clang__) && defined(__has_cpp_attribute) \ + && !defined(GOOGLE_PROTOBUF_OS_APPLE) +# if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) || \ + __has_cpp_attribute(clang::fallthrough) +# define GOOGLE_FALLTHROUGH_INTENDED [[clang::fallthrough]] +# endif +#endif + +#ifndef GOOGLE_FALLTHROUGH_INTENDED +# define GOOGLE_FALLTHROUGH_INTENDED +#endif + +#define GOOGLE_GUARDED_BY(x) +#define GOOGLE_ATTRIBUTE_COLD + +// x86 and x86-64 can perform unaligned loads/stores directly. +#if defined(_M_X64) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(__i386__) + +#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p)) +#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p)) +#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p)) + +#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val)) + +#else +inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) { + uint16 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) { + uint32 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) { + uint64 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { + memcpy(p, &v, sizeof v); +} +#endif + +#if defined(_MSC_VER) +#define GOOGLE_THREAD_LOCAL __declspec(thread) +#else +#define GOOGLE_THREAD_LOCAL __thread +#endif + +// The following guarantees declaration of the byte swap functions, and +// defines __BYTE_ORDER for MSVC +#ifdef _MSC_VER +#include <stdlib.h> // NOLINT(build/include) +#define __BYTE_ORDER __LITTLE_ENDIAN +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include <libkern/OSByteOrder.h> +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif defined(__GLIBC__) || defined(__CYGWIN__) +#include <byteswap.h> // IWYU pragma: export + +#else + +static inline uint16 bswap_16(uint16 x) { + return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); +} +#define bswap_16(x) bswap_16(x) +static inline uint32 bswap_32(uint32 x) { + return (((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} +#define bswap_32(x) bswap_32(x) +static inline uint64 bswap_64(uint64 x) { + return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) | + ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) | + ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) | + ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) | + ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) | + ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) | + ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) | + ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56)); +} +#define bswap_64(x) bswap_64(x) + +#endif + +// =================================================================== +// from google3/util/endian/endian.h +LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); + +class BigEndian { + public: +#ifdef PROTOBUF_LITTLE_ENDIAN + + static uint16 FromHost16(uint16 x) { return bswap_16(x); } + static uint16 ToHost16(uint16 x) { return bswap_16(x); } + + static uint32 FromHost32(uint32 x) { return bswap_32(x); } + static uint32 ToHost32(uint32 x) { return bswap_32(x); } + + static uint64 FromHost64(uint64 x) { return bswap_64(x); } + static uint64 ToHost64(uint64 x) { return bswap_64(x); } + + static bool IsLittleEndian() { return true; } + +#else + + static uint16 FromHost16(uint16 x) { return x; } + static uint16 ToHost16(uint16 x) { return x; } + + static uint32 FromHost32(uint32 x) { return x; } + static uint32 ToHost32(uint32 x) { return x; } + + static uint64 FromHost64(uint64 x) { return x; } + static uint64 ToHost64(uint64 x) { return x; } + + static bool IsLittleEndian() { return false; } + +#endif /* ENDIAN */ + + // Functions to do unaligned loads and stores in big-endian order. + static uint16 Load16(const void *p) { + return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16 v) { + GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32 Load32(const void *p) { + return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32 v) { + GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); + } + + static uint64 Load64(const void *p) { + return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); + } + + static void Store64(void *p, uint64 v) { + GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); + } +}; + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_ diff --git a/src/google/protobuf/stubs/scoped_ptr.h b/src/google/protobuf/stubs/scoped_ptr.h new file mode 100644 index 00000000..4423c118 --- /dev/null +++ b/src/google/protobuf/stubs/scoped_ptr.h @@ -0,0 +1,236 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ +#define GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ + +#include <google/protobuf/stubs/port.h> + +namespace google { +namespace protobuf { + +// =================================================================== +// from google3/base/scoped_ptr.h + +namespace internal { + +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class, and its closely-related brethren, +// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. + +template <class C> class scoped_ptr; +template <class C> class scoped_array; + +// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr<T> owns the T object that it points to. +// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. +// +// The size of a scoped_ptr is small: +// sizeof(scoped_ptr<C>) == sizeof(C*) +template <class C> +class scoped_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to initializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with new. + explicit scoped_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + ptr_ = p; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return ptr_ == p; } + bool operator!=(C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + private: + C* ptr_; + + // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different scoped_ptrs. + template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; + template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; + + // Disallow evil constructors + scoped_ptr(const scoped_ptr&); + void operator=(const scoped_ptr&); +}; + +// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate +// with new [] and the destructor deletes objects with delete []. +// +// As with scoped_ptr<C>, a scoped_array<C> either points to an object +// or is NULL. A scoped_array<C> owns the object that it points to. +// +// Size: sizeof(scoped_array<C>) == sizeof(C*) +template <class C> +class scoped_array { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to initializing with NULL. + // There is no way to create an uninitialized scoped_array. + // The input parameter must be allocated with new []. + explicit scoped_array(C* p = NULL) : array_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_array() { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != array_) { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + array_ = p; + } + } + + // Get one element of the current object. + // Will assert() if there is no current object, or index i is negative. + C& operator[](std::ptrdiff_t i) const { + assert(i >= 0); + assert(array_ != NULL); + return array_[i]; + } + + // Get a pointer to the zeroth element of the current object. + // If there is no current object, return NULL. + C* get() const { + return array_; + } + + // Comparison operators. + // These return whether two scoped_array refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return array_ == p; } + bool operator!=(C* p) const { return array_ != p; } + + // Swap two scoped arrays. + void swap(scoped_array& p2) { + C* tmp = array_; + array_ = p2.array_; + p2.array_ = tmp; + } + + // Release an array. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = array_; + array_ = NULL; + return retVal; + } + + private: + C* array_; + + // Forbid comparison of different scoped_array types. + template <class C2> bool operator==(scoped_array<C2> const& p2) const; + template <class C2> bool operator!=(scoped_array<C2> const& p2) const; + + // Disallow evil constructors + scoped_array(const scoped_array&); + void operator=(const scoped_array&); +}; + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::scoped_ptr; +using internal::scoped_array; + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 2ec62b42..8442f2ce 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -872,13 +872,6 @@ char *FastHex32ToBuffer(uint32 value, char* buffer) { return InternalFastHexToBuffer(value, buffer, 8); } -static inline char* PlaceNum(char* p, int num, char prev_sep) { - *p-- = '0' + num % 10; - *p-- = '0' + num / 10; - *p-- = prev_sep; - return p; -} - // ---------------------------------------------------------------------- // FastInt32ToBufferLeft() // FastUInt32ToBufferLeft() diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h index 36a8f3b1..0d8127e5 100644 --- a/src/google/protobuf/stubs/type_traits.h +++ b/src/google/protobuf/stubs/type_traits.h @@ -59,9 +59,9 @@ #ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_ #define GOOGLE_PROTOBUF_TYPE_TRAITS_H_ +#include <cstddef> // for NULL #include <utility> // For pair -#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/template_util.h> // For true_type and false_type namespace google { diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc index c9d085c8..76f8cfe1 100644 --- a/src/google/protobuf/testing/zcgunzip.cc +++ b/src/google/protobuf/testing/zcgunzip.cc @@ -43,6 +43,15 @@ #include <stdlib.h> #include <fcntl.h> +#ifdef _WIN32 +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#endif + #include <google/protobuf/io/gzip_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc index e910f321..992ddc6e 100644 --- a/src/google/protobuf/testing/zcgzip.cc +++ b/src/google/protobuf/testing/zcgzip.cc @@ -42,6 +42,15 @@ #include <stdlib.h> #include <fcntl.h> +#ifdef _WIN32 +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#endif + #include <google/protobuf/io/gzip_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 877dc8f3..2ee0ec29 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\037google/protobuf/timestamp.proto\022\017googl" "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" - "\022\r\n\005nanos\030\002 \001(\005BI\n\023com.google.protobufB\016" - "TimestampProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Proto" - "colBuffersb\006proto3", 178); + "\022\r\n\005nanos\030\002 \001(\005BQ\n\023com.google.protobufB\016" + "TimestampProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Proto" + "buf.WellKnownTypesb\006proto3", 186); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/timestamp.proto", &protobuf_RegisterTypes); Timestamp::default_instance_ = new Timestamp(); diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto index 381ff997..11f258da 100644 --- a/src/google/protobuf/timestamp.proto +++ b/src/google/protobuf/timestamp.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "TimestampProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 8b08909e..029a72c6 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -221,9 +221,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() { "ntext\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006numb" "er\030\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.proto" "buf.Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005va" - "lue\030\002 \001(\0132\024.google.protobuf.AnyB(\n\023com.g" - "oogle.protobufB\tTypeProtoP\001\242\002\003GPBb\006proto" - "3", 1321); + "lue\030\002 \001(\0132\024.google.protobuf.AnyBI\n\023com.g" + "oogle.protobufB\tTypeProtoP\001\242\002\003GPB\252\002\036Goog" + "le.Protobuf.WellKnownTypesb\006proto3", 1354); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/type.proto", &protobuf_RegisterTypes); Type::default_instance_ = new Type(); diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto index ace5d995..ce22d33d 100644 --- a/src/google/protobuf/type.proto +++ b/src/google/protobuf/type.proto @@ -37,6 +37,7 @@ import "google/protobuf/source_context.proto"; option java_multiple_files = true; option java_outer_classname = "TypeProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index 834c9b56..85fe6153 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -42,7 +42,6 @@ option cc_generic_services = true; // auto-added option java_generic_services = true; // auto-added option py_generic_services = true; // auto-added option cc_enable_arenas = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest_import.proto"; diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index 8f9fb582..d4d6e869 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -41,7 +41,6 @@ syntax = "proto2"; option cc_generic_services = true; // auto-added option java_generic_services = true; // auto-added option py_generic_services = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // A custom file option (defined below). option (file_opt1) = 9876543210; diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto index faaddc6e..8aa3a37b 100644 --- a/src/google/protobuf/unittest_drop_unknown_fields.proto +++ b/src/google/protobuf/unittest_drop_unknown_fields.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package unittest_drop_unknown_fields; option objc_class_prefix = "DropUnknowns"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; +option csharp_namespace = "Google.Protobuf.TestProtos"; message Foo { enum NestedEnum { diff --git a/src/google/protobuf/unittest_embed_optimize_for.proto b/src/google/protobuf/unittest_embed_optimize_for.proto index c4ccccb7..d8b0f9b9 100644 --- a/src/google/protobuf/unittest_embed_optimize_for.proto +++ b/src/google/protobuf/unittest_embed_optimize_for.proto @@ -39,8 +39,6 @@ import "google/protobuf/unittest_optimize_for.proto"; package protobuf_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - // We optimize for speed here, but we are importing a proto that is optimized // for code size. option optimize_for = SPEED; diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto index f8fcc9c0..6e65dc18 100644 --- a/src/google/protobuf/unittest_enormous_descriptor.proto +++ b/src/google/protobuf/unittest_enormous_descriptor.proto @@ -40,7 +40,6 @@ syntax = "proto2"; package google.protobuf; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Avoid generating insanely long methods. option optimize_for = CODE_SIZE; diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto index ae2e90b8..7e165220 100644 --- a/src/google/protobuf/unittest_import.proto +++ b/src/google/protobuf/unittest_import.proto @@ -47,7 +47,6 @@ option cc_enable_arenas = true; // Exercise the java_package option. option java_package = "com.google.protobuf.test"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Do not set a java_outer_classname here to verify that Proto2 works without // one. diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto index ca208582..a7afa452 100644 --- a/src/google/protobuf/unittest_import_lite.proto +++ b/src/google/protobuf/unittest_import_lite.proto @@ -38,7 +38,6 @@ package protobuf_unittest_import; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import public "google/protobuf/unittest_import_public_lite.proto"; diff --git a/src/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto new file mode 100644 index 00000000..59673eaf --- /dev/null +++ b/src/google/protobuf/unittest_import_proto3.proto @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest_proto3.proto to test importing. + +syntax = "proto3"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do +// "using namespace unittest_import = protobuf_unittest_import". +package protobuf_unittest_import; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// Exercise the java_package option. +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +// Do not set a java_outer_classname here to verify that Proto2 works without +// one. + +// Test public import +import public "google/protobuf/unittest_import_public_proto3.proto"; + +message ImportMessage { + int32 d = 1; +} + +enum ImportEnum { + IMPORT_ENUM_UNSPECIFIED = 0; + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + diff --git a/src/google/protobuf/unittest_import_public.proto b/src/google/protobuf/unittest_import_public.proto index 0bc5d617..ffaf7736 100644 --- a/src/google/protobuf/unittest_import_public.proto +++ b/src/google/protobuf/unittest_import_public.proto @@ -35,7 +35,6 @@ syntax = "proto2"; package protobuf_unittest_import; option java_package = "com.google.protobuf.test"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message PublicImportMessage { optional int32 e = 1; diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto index 231ab9dd..33549c22 100644 --- a/src/google/protobuf/unittest_import_public_lite.proto +++ b/src/google/protobuf/unittest_import_public_lite.proto @@ -37,7 +37,6 @@ package protobuf_unittest_import; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message PublicImportMessageLite { optional int32 e = 1; diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto new file mode 100644 index 00000000..d6f11e28 --- /dev/null +++ b/src/google/protobuf/unittest_import_public_proto3.proto @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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: liujisi@google.com (Pherl Liu) + +syntax = "proto3"; + +package protobuf_unittest_import; + +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +message PublicImportMessage { + int32 e = 1; +} diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index 0040874b..662c0e46 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -40,7 +40,6 @@ import "google/protobuf/unittest_import_lite.proto"; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Same as TestAllTypes but with the lite runtime. message TestAllTypesLite { diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto index d955cc14..132d6a82 100644 --- a/src/google/protobuf/unittest_lite_imports_nonlite.proto +++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto @@ -38,7 +38,6 @@ package protobuf_unittest; import "google/protobuf/unittest.proto"; option optimize_for = LITE_RUNTIME; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message TestLiteImportsNonlite { optional TestAllTypes message = 1; diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto index 425c9a5a..3aa31fa9 100644 --- a/src/google/protobuf/unittest_mset.proto +++ b/src/google/protobuf/unittest_mset.proto @@ -39,7 +39,6 @@ package protobuf_unittest; option cc_enable_arenas = true; option optimize_for = SPEED; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // A message with message_set_wire_format. message TestMessageSet { diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto index f5cc4cc3..994afff4 100644 --- a/src/google/protobuf/unittest_no_field_presence.proto +++ b/src/google/protobuf/unittest_no_field_presence.proto @@ -37,8 +37,6 @@ import "google/protobuf/unittest.proto"; package proto2_nofieldpresence_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos.Proto3"; - // This proto includes every type of field in both singular and repeated // forms. message TestAllTypes { diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto index 2bcd16e4..ee9cc7bd 100644 --- a/src/google/protobuf/unittest_optimize_for.proto +++ b/src/google/protobuf/unittest_optimize_for.proto @@ -40,7 +40,6 @@ import "google/protobuf/unittest.proto"; package protobuf_unittest; option optimize_for = CODE_SIZE; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message TestOptimizedForSize { optional int32 i = 1; diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto index abc3de28..2f91332c 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package proto3_preserve_unknown_enum_unittest; option objc_class_prefix = "UnknownEnums"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; +option csharp_namespace = "Google.Protobuf.TestProtos"; enum MyEnum { FOO = 0; diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto index 168b2407..adf42968 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum2.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto @@ -32,8 +32,6 @@ syntax = "proto2"; package proto2_preserve_unknown_enum_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - enum MyEnum { FOO = 0; BAR = 1; diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto new file mode 100644 index 00000000..f59d2178 --- /dev/null +++ b/src/google/protobuf/unittest_proto3.proto @@ -0,0 +1,388 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto3"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_import_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage + repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated=true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + // In proto3, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage single_nested_message = 200; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +service TestService { + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto index e157260e..2cb7775c 100644 --- a/src/google/protobuf/unittest_well_known_types.proto +++ b/src/google/protobuf/unittest_well_known_types.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package protobuf_unittest; +option csharp_namespace = "Google.Protobuf.TestProtos"; option java_multiple_files = true; option java_package = "com.google.protobuf.test"; @@ -17,6 +18,8 @@ import "google/protobuf/type.proto"; import "google/protobuf/wrappers.proto"; // Test that we can include all well-known types. +// Each wrapper type is included separately, as languages +// map handle different wrappers in different ways. message TestWellKnownTypes { google.protobuf.Any any_field = 1; google.protobuf.Api api_field = 2; @@ -27,5 +30,83 @@ message TestWellKnownTypes { google.protobuf.Struct struct_field = 7; google.protobuf.Timestamp timestamp_field = 8; google.protobuf.Type type_field = 9; - google.protobuf.Int32Value int32_field = 10; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; +} + +// A repeated field for each well-known type. +message RepeatedWellKnownTypes { + repeated google.protobuf.Any any_field = 1; + repeated google.protobuf.Api api_field = 2; + repeated google.protobuf.Duration duration_field = 3; + repeated google.protobuf.Empty empty_field = 4; + repeated google.protobuf.FieldMask field_mask_field = 5; + repeated google.protobuf.SourceContext source_context_field = 6; + repeated google.protobuf.Struct struct_field = 7; + repeated google.protobuf.Timestamp timestamp_field = 8; + repeated google.protobuf.Type type_field = 9; + // These don't actually make a lot of sense, but they're not prohibited... + repeated google.protobuf.DoubleValue double_field = 10; + repeated google.protobuf.FloatValue float_field = 11; + repeated google.protobuf.Int64Value int64_field = 12; + repeated google.protobuf.UInt64Value uint64_field = 13; + repeated google.protobuf.Int32Value int32_field = 14; + repeated google.protobuf.UInt32Value uint32_field = 15; + repeated google.protobuf.BoolValue bool_field = 16; + repeated google.protobuf.StringValue string_field = 17; + repeated google.protobuf.BytesValue bytes_field = 18; +} + +message OneofWellKnownTypes { + oneof oneof_field { + google.protobuf.Any any_field = 1; + google.protobuf.Api api_field = 2; + google.protobuf.Duration duration_field = 3; + google.protobuf.Empty empty_field = 4; + google.protobuf.FieldMask field_mask_field = 5; + google.protobuf.SourceContext source_context_field = 6; + google.protobuf.Struct struct_field = 7; + google.protobuf.Timestamp timestamp_field = 8; + google.protobuf.Type type_field = 9; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; + } +} + +// A map field for each well-known type. We only +// need to worry about the value part of the map being the +// well-known types, as messages can't be map keys. +message MapWellKnownTypes { + map<int32,google.protobuf.Any> any_field = 1; + map<int32,google.protobuf.Api> api_field = 2; + map<int32,google.protobuf.Duration> duration_field = 3; + map<int32,google.protobuf.Empty> empty_field = 4; + map<int32,google.protobuf.FieldMask> field_mask_field = 5; + map<int32,google.protobuf.SourceContext> source_context_field = 6; + map<int32,google.protobuf.Struct> struct_field = 7; + map<int32,google.protobuf.Timestamp> timestamp_field = 8; + map<int32,google.protobuf.Type> type_field = 9; + map<int32,google.protobuf.DoubleValue> double_field = 10; + map<int32,google.protobuf.FloatValue> float_field = 11; + map<int32,google.protobuf.Int64Value> int64_field = 12; + map<int32,google.protobuf.UInt64Value> uint64_field = 13; + map<int32,google.protobuf.Int32Value> int32_field = 14; + map<int32,google.protobuf.UInt32Value> uint32_field = 15; + map<int32,google.protobuf.BoolValue> bool_field = 16; + map<int32,google.protobuf.StringValue> string_field = 17; + map<int32,google.protobuf.BytesValue> bytes_field = 18; } diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto index 3c549cc7..0ea1ede3 100644 --- a/src/google/protobuf/unknown_enum_test.proto +++ b/src/google/protobuf/unknown_enum_test.proto @@ -36,8 +36,6 @@ syntax = "proto2"; package google.protobuf.util; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - message DownRevision { enum Enum { DEFAULT_VALUE = 2; diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index 54cd653a..c5db963b 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -54,15 +54,6 @@ namespace google { namespace protobuf { namespace internal { -namespace { - -// This function turns out to be convenient when using some macros later. -inline int GetEnumNumber(const EnumValueDescriptor* descriptor) { - return descriptor->number(); -} - -} // anonymous namespace - // =================================================================== bool UnknownFieldSetFieldSkipper::SkipField( diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index ffc77f1c..db75db15 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -262,9 +262,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() { "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013" "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022" "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001" - " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BE\n\023com" + " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BM\n\023com" ".google.protobufB\rWrappersProtoP\001\242\002\003GPB\252" - "\002\026Google.ProtocolBuffersb\006proto3", 392); + "\002\036Google.Protobuf.WellKnownTypesb\006proto3", 400); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/wrappers.proto", &protobuf_RegisterTypes); DoubleValue::default_instance_ = new DoubleValue(); diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto index a13e6edb..6d3181bf 100644 --- a/src/google/protobuf/wrappers.proto +++ b/src/google/protobuf/wrappers.proto @@ -40,7 +40,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "WrappersProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; |