aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
diff options
context:
space:
mode:
authorAmos <48657826+Mauler125@users.noreply.github.com>2022-03-02 23:44:27 +0100
committerAmos <48657826+Mauler125@users.noreply.github.com>2022-03-02 23:44:27 +0100
commit5e3b22e336217dd2b0aec771ce80b69caa07d571 (patch)
treeac7b21e816b818e1dcdc724fa56d3fa1f4cfd0b1 /NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
parent62e137b32ad7c601b2db37e69b9f435a7dbc730d (diff)
downloadNorthstarLauncher-5e3b22e336217dd2b0aec771ce80b69caa07d571.tar.gz
NorthstarLauncher-5e3b22e336217dd2b0aec771ce80b69caa07d571.zip
Add 'protobuf' library to project
Library is configured to compile as 'lite'.
Diffstat (limited to 'NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc')
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc779
1 files changed, 779 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
new file mode 100644
index 00000000..963b9c87
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
@@ -0,0 +1,779 @@
+// 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 <algorithm>
+#include <map>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_enum.h>
+#include <compiler/csharp/csharp_field_base.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_message.h>
+#include <compiler/csharp/csharp_names.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
+ return d1->number() < d2->number();
+}
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+ const Options* options)
+ : SourceGeneratorBase(options),
+ descriptor_(descriptor),
+ has_bit_field_count_(0),
+ end_tag_(GetGroupEndTag(descriptor)),
+ has_extension_ranges_(descriptor->extension_range_count() > 0) {
+ // fields by number
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ fields_by_number_.push_back(descriptor_->field(i));
+ }
+ std::sort(fields_by_number_.begin(), fields_by_number_.end(),
+ CompareFieldNumbers);
+
+ int presence_bit_count = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (RequiresPresenceBit(field)) {
+ presence_bit_count++;
+ if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) {
+ has_bit_field_count_++;
+ }
+ }
+ }
+}
+
+MessageGenerator::~MessageGenerator() {
+}
+
+std::string MessageGenerator::class_name() {
+ return descriptor_->name();
+}
+
+std::string MessageGenerator::full_class_name() {
+ return GetClassName(descriptor_);
+}
+
+const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
+ return fields_by_number_;
+}
+
+void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
+ if (descriptor_->options().deprecated()) {
+ printer->Print("[global::System.ObsoleteAttribute]\n");
+ }
+}
+
+void MessageGenerator::AddSerializableAttribute(io::Printer* printer) {
+ if (this->options()->serializable) {
+ printer->Print("[global::System.SerializableAttribute]\n");
+ }
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+ vars["access_level"] = class_access_level();
+
+ WriteMessageDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ AddSerializableAttribute(printer);
+
+ printer->Print(
+ vars,
+ "$access_level$ sealed partial class $class_name$ : ");
+
+ if (has_extension_ranges_) {
+ printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
+ }
+ else {
+ printer->Print(vars, "pb::IMessage<$class_name$>\n");
+ }
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Print(" , pb::IBufferMessage\n");
+ printer->Print("#endif\n");
+ printer->Print("{\n");
+ printer->Indent();
+
+ // All static fields and properties
+ printer->Print(
+ vars,
+ "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
+
+ printer->Print(
+ "private pb::UnknownFieldSet _unknownFields;\n");
+
+ if (has_extension_ranges_) {
+ if (IsDescriptorProto(descriptor_->file())) {
+ printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility
+ } else {
+ printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
+ }
+
+ // a read-only property for fast
+ // retrieval of the set in IsInitialized
+ printer->Print(vars,
+ "private pb::ExtensionSet<$class_name$> _Extensions { get { "
+ "return _extensions; } }\n");
+ }
+
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ // don't use arrays since all arrays are heap allocated, saving allocations
+ // use ints instead of bytes since bytes lack bitwise operators, saving casts
+ printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
+ }
+
+ WriteGeneratedCodeAttributes(printer);
+
+ printer->Print(
+ vars,
+ "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
+
+ // Access the message descriptor via the relevant file descriptor or containing message descriptor.
+ if (!descriptor_->containing_type()) {
+ vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
+ + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
+ } else {
+ vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+ + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
+ }
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public static pbr::MessageDescriptor Descriptor {\n"
+ " get { return $descriptor_accessor$; }\n"
+ "}\n"
+ "\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+ " get { return Descriptor; }\n"
+ "}\n"
+ "\n");
+
+ // Parameterless constructor and partial OnConstruction method.
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $class_name$() {\n"
+ " OnConstruction();\n"
+ "}\n\n"
+ "partial void OnConstruction();\n\n");
+
+ GenerateCloningCode(printer);
+ GenerateFreezingCode(printer);
+
+ // 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(
+ "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
+ "public const int $field_constant_name$ = $index$;\n",
+ "field_name", fieldDescriptor->name(),
+ "field_constant_name", GetFieldConstantName(fieldDescriptor),
+ "index", StrCat(fieldDescriptor->number()));
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fieldDescriptor));
+ generator->GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ // oneof properties (for real oneofs, which come before synthetic ones)
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ vars["original_name"] = oneof->name();
+ printer->Print(
+ vars,
+ "private object $name$_;\n"
+ "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
+ "public enum $property_name$OneofCase {\n");
+ printer->Indent();
+ printer->Print("None = 0,\n");
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ printer->Print("$field_property_name$ = $index$,\n",
+ "field_property_name", GetPropertyName(field),
+ "index", StrCat(field->number()));
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ // TODO: Should we put the oneof .proto comments here?
+ // It's unclear exactly where they should go.
+ printer->Print(
+ vars,
+ "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $property_name$OneofCase $property_name$Case {\n"
+ " get { return $name$Case_; }\n"
+ "}\n\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public void Clear$property_name$() {\n"
+ " $name$Case_ = $property_name$OneofCase.None;\n"
+ " $name$_ = null;\n"
+ "}\n\n");
+ }
+
+ // Standard methods
+ GenerateFrameworkMethods(printer);
+ GenerateMessageSerializationMethods(printer);
+ GenerateMergingMethods(printer);
+
+ if (has_extension_ranges_) {
+ printer->Print(
+ vars,
+ "public TValue GetExtension<TValue>(pb::Extension<$class_name$, "
+ "TValue> extension) {\n"
+ " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
+ "}\n"
+ "public pbc::RepeatedField<TValue> "
+ "GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
+ "extension) {\n"
+ " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
+ "}\n"
+ "public pbc::RepeatedField<TValue> "
+ "GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, "
+ "TValue> extension) {\n"
+ " return pb::ExtensionSet.GetOrInitialize(ref _extensions, "
+ "extension);\n"
+ "}\n"
+ "public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> "
+ "extension, TValue value) {\n"
+ " pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
+ "}\n"
+ "public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> "
+ "extension) {\n"
+ " return pb::ExtensionSet.Has(ref _extensions, extension);\n"
+ "}\n"
+ "public void ClearExtension<TValue>(pb::Extension<$class_name$, "
+ "TValue> extension) {\n"
+ " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
+ "}\n"
+ "public void "
+ "ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
+ "extension) {\n"
+ " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
+ "}\n\n");
+ }
+
+ // Nested messages and enums
+ if (HasNestedGeneratedTypes()) {
+ printer->Print(
+ vars,
+ "#region Nested types\n"
+ "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\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), this->options());
+ enumGenerator.Generate(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), this->options());
+ messageGenerator.Generate(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n"
+ "#endregion\n"
+ "\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print(
+ vars,
+ "#region Extensions\n"
+ "/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public static partial class Extensions {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->extension(i)));
+ generator->GenerateExtensionCode(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "#endregion\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::GenerateCloningCode(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ WriteGeneratedCodeAttributes(printer);
+ vars["class_name"] = class_name();
+ printer->Print(
+ vars,
+ "public $class_name$($class_name$ other) : this() {\n");
+ printer->Indent();
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
+ }
+ // Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->real_containing_oneof()) {
+ continue;
+ }
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateCloningCode(printer);
+ }
+ // Clone just the right field for each real oneof
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ std::unique_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");
+ }
+ // Clone unknown fields
+ printer->Print(
+ "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
+ if (has_extension_ranges_) {
+ printer->Print(
+ "_extensions = pb::ExtensionSet.Clone(other._extensions);\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $class_name$ Clone() {\n"
+ " return new $class_name$(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+
+ // Equality
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public override bool Equals(object other) {\n"
+ " return Equals(other as $class_name$);\n"
+ "}\n\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "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++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteEquals(printer);
+ }
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
+ "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (!Equals(_extensions, other._extensions)) {\n"
+ " return false;\n"
+ "}\n");
+ }
+ printer->Outdent();
+ printer->Print(
+ " return Equals(_unknownFields, other._unknownFields);\n"
+ "}\n\n");
+
+ // GetHashCode
+ // Start with a non-zero value to easily distinguish between null and "empty" messages.
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public override int GetHashCode() {\n"
+ " int hash = 1;\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteHash(printer);
+ }
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ printer->Print("hash ^= (int) $name$Case_;\n",
+ "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (_extensions != null) {\n"
+ " hash ^= _extensions.GetHashCode();\n"
+ "}\n");
+ }
+ printer->Print(
+ "if (_unknownFields != null) {\n"
+ " hash ^= _unknownFields.GetHashCode();\n"
+ "}\n"
+ "return hash;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public override string ToString() {\n"
+ " return pb::JsonFormatter.ToDiagnosticString(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public void WriteTo(pb::CodedOutputStream output) {\n");
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Indent();
+ printer->Print("output.WriteRawMessage(this);\n");
+ printer->Outdent();
+ printer->Print("#else\n");
+ printer->Indent();
+ GenerateWriteToBody(printer, false);
+ printer->Outdent();
+ printer->Print("#endif\n");
+ printer->Print("}\n\n");
+
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n");
+ printer->Indent();
+ GenerateWriteToBody(printer, true);
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("#endif\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public int CalculateSize() {\n");
+ printer->Indent();
+ printer->Print("int size = 0;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateSerializedSizeCode(printer);
+ }
+
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (_extensions != null) {\n"
+ " size += _extensions.CalculateSize();\n"
+ "}\n");
+ }
+
+ printer->Print(
+ "if (_unknownFields != null) {\n"
+ " size += _unknownFields.CalculateSize();\n"
+ "}\n");
+
+ printer->Print("return size;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) {
+ // Serialize all the fields
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fields_by_number()[i]));
+ generator->GenerateSerializationCode(printer, use_write_context);
+ }
+
+ if (has_extension_ranges_) {
+ // Serialize extensions
+ printer->Print(
+ use_write_context
+ ? "if (_extensions != null) {\n"
+ " _extensions.WriteTo(ref output);\n"
+ "}\n"
+ : "if (_extensions != null) {\n"
+ " _extensions.WriteTo(output);\n"
+ "}\n");
+ }
+
+ // Serialize unknown fields
+ printer->Print(
+ use_write_context
+ ? "if (_unknownFields != null) {\n"
+ " _unknownFields.WriteTo(ref output);\n"
+ "}\n"
+ : "if (_unknownFields != null) {\n"
+ " _unknownFields.WriteTo(output);\n"
+ "}\n");
+
+ // TODO(jonskeet): Memoize size of frozen messages?
+}
+
+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.
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public void MergeFrom($class_name$ other) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (other == null) {\n"
+ " return;\n"
+ "}\n");
+ // Merge non-oneof fields, treating optional proto3 fields as normal fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->real_containing_oneof()) {
+ continue;
+ }
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateMergingCode(printer);
+ }
+ // Merge oneof fields (for non-synthetic oneofs)
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ vars["field_property_name"] = GetPropertyName(field);
+ printer->Print(
+ vars,
+ "case $property_name$OneofCase.$field_property_name$:\n");
+ printer->Indent();
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateMergingCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ // Merge extensions
+ if (has_extension_ranges_) {
+ printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n");
+ }
+
+ // Merge unknown fields.
+ printer->Print(
+ "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Indent();
+ printer->Print("input.ReadRawMessage(this);\n");
+ printer->Outdent();
+ printer->Print("#else\n");
+ printer->Indent();
+ GenerateMainParseLoop(printer, false);
+ printer->Outdent();
+ printer->Print("#endif\n");
+ printer->Print("}\n\n");
+
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n");
+ printer->Indent();
+ GenerateMainParseLoop(printer, true);
+ printer->Outdent();
+ printer->Print("}\n"); // method
+ printer->Print("#endif\n\n");
+
+}
+
+void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) {
+ std::map<std::string, std::string> vars;
+ vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
+
+ printer->Print(
+ "uint tag;\n"
+ "while ((tag = input.ReadTag()) != 0) {\n"
+ " switch(tag) {\n");
+ printer->Indent();
+ printer->Indent();
+ if (end_tag_ != 0) {
+ printer->Print(
+ "case $end_tag$:\n"
+ " return;\n",
+ "end_tag", StrCat(end_tag_));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(vars,
+ "default:\n"
+ " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n"
+ " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
+ " }\n"
+ " break;\n");
+ } else {
+ printer->Print(vars,
+ "default:\n"
+ " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
+ " 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);
+ // 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 $packed_tag$:\n",
+ "packed_tag",
+ StrCat(
+ internal::WireFormatLite::MakeTag(
+ field->number(),
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
+ }
+
+ printer->Print("case $tag$: {\n", "tag", StrCat(tag));
+ printer->Indent();
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(field));
+ generator->GenerateParsingCode(printer, use_parse_context);
+ printer->Print("break;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n"); // switch
+ printer->Outdent();
+ printer->Print("}\n"); // while
+}
+
+// it's a waste of space to track presence for all values, so we only track them if they're not nullable
+int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
+ if (!RequiresPresenceBit(descriptor)) {
+ return -1;
+ }
+
+ int index = 0;
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ const FieldDescriptor* field = fields_by_number()[i];
+ if (field == descriptor) {
+ return index;
+ }
+ if (RequiresPresenceBit(field)) {
+ index++;
+ }
+ }
+ GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
+ return -1;
+}
+
+FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
+ const FieldDescriptor* descriptor) {
+ return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google