Media CAS Proxy SDK release: 16.5.0

This commit is contained in:
Buildbot
2021-07-12 21:46:29 +00:00
parent 760d53c347
commit d69222d492
1968 changed files with 638006 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
// 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 test insures that
// csharp/src/Google.Protobuf/Reflection/Descriptor.cs match exactly
// what would be generated by the protocol compiler. The file is not
// generated automatically at build time.
//
// If this test fails, run the script
// "generate_descriptor_proto.sh" and add the changed files under
// csharp/src/ to your changelist.
#include <map>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
namespace {
class MockErrorCollector : public MultiFileErrorCollector {
public:
MockErrorCollector() {}
~MockErrorCollector() {}
std::string text_;
// implements ErrorCollector ---------------------------------------
void AddError(const std::string& filename, int line, int column,
const std::string& message) {
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
filename, line, column, message);
}
};
class MockGeneratorContext : public GeneratorContext {
public:
void ExpectFileMatches(const std::string& virtual_filename,
const std::string& physical_filename) {
auto it = files_.find(virtual_filename);
ASSERT_TRUE(it != files_.end())
<< "Generator failed to generate file: " << virtual_filename;
std::string expected_contents = *it->second;
std::string actual_contents;
GOOGLE_CHECK_OK(
File::GetContentsAsText(TestSourceDir() + "/" + physical_filename,
&actual_contents, true))
<< "Unable to get " << physical_filename;
EXPECT_TRUE(actual_contents == expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
"generate_descriptor_proto.sh. Then add this file "
"to your CL.";
}
// implements GeneratorContext --------------------------------------
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
auto& map_slot = files_[filename];
map_slot.reset(new std::string);
return new io::StringOutputStream(map_slot.get());
}
private:
std::map<std::string, std::unique_ptr<std::string>> files_;
};
class GenerateAndTest {
public:
GenerateAndTest() {}
void Run(const FileDescriptor* proto_file, std::string file1, std::string file2) {
ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
&context_, &error_));
context_.ExpectFileMatches(file1, file2);
}
void SetParameter(string parameter) {
parameter_ = parameter;
}
private:
Generator generator_;
MockGeneratorContext context_;
std::string error_;
std::string parameter_;
};
TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
// Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
// only distribution).
std::string descriptor_file_name =
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
return;
}
MockErrorCollector error_collector;
DiskSourceTree source_tree;
Importer importer(&source_tree, &error_collector);
GenerateAndTest generate_test;
generate_test.SetParameter("base_namespace=Google.Protobuf");
source_tree.MapPath("", TestSourceDir());
generate_test.Run(importer.Import("google/protobuf/descriptor.proto"),
"Reflection/Descriptor.cs",
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs");
generate_test.Run(importer.Import("google/protobuf/any.proto"),
"WellKnownTypes/Any.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Any.cs");
generate_test.Run(importer.Import("google/protobuf/api.proto"),
"WellKnownTypes/Api.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Api.cs");
generate_test.Run(importer.Import("google/protobuf/duration.proto"),
"WellKnownTypes/Duration.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs");
generate_test.Run(importer.Import("google/protobuf/empty.proto"),
"WellKnownTypes/Empty.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs");
generate_test.Run(importer.Import("google/protobuf/field_mask.proto"),
"WellKnownTypes/FieldMask.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs");
generate_test.Run(importer.Import("google/protobuf/source_context.proto"),
"WellKnownTypes/SourceContext.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs");
generate_test.Run(importer.Import("google/protobuf/struct.proto"),
"WellKnownTypes/Struct.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs");
generate_test.Run(importer.Import("google/protobuf/timestamp.proto"),
"WellKnownTypes/Timestamp.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs");
generate_test.Run(importer.Import("google/protobuf/type.proto"),
"WellKnownTypes/Type.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Type.cs");
generate_test.Run(importer.Import("google/protobuf/wrappers.proto"),
"WellKnownTypes/Wrappers.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
generate_test.SetParameter("");
source_tree.MapPath("", TestSourceDir() + "/../conformance");
generate_test.Run(importer.Import("conformance.proto"),
"Conformance.cs",
"../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
EXPECT_EQ("", error_collector.text_);
}
} // namespace
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,116 @@
// 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 <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// Functions to create C# XML documentation comments.
// Currently this only includes documentation comments containing text specified as comments
// in the .proto file; documentation comments generated just from field/message/enum/proto names
// is inlined in the relevant code. If more control is required, that code can be moved here.
void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
std::string comments = location.leading_comments.empty() ?
location.trailing_comments : location.leading_comments;
if (comments.empty()) {
return;
}
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
// node of a summary element, not part of an attribute.
comments = StringReplace(comments, "&", "&amp;", true);
comments = StringReplace(comments, "<", "&lt;", true);
std::vector<std::string> lines;
lines = Split(comments, "\n", false);
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
// but that needs to be part of a bigger effort to understand the markdown better anyway.
printer->Print("/// <summary>\n");
bool last_was_empty = false;
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
// to preserve the blank lines themselves, as this is relevant in the markdown.
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
// (We don't skip "just whitespace" lines, either.)
for (std::vector<std::string>::iterator it = lines.begin();
it != lines.end(); ++it) {
std::string line = *it;
if (line.empty()) {
last_was_empty = true;
} else {
if (last_was_empty) {
printer->Print("///\n");
}
last_was_empty = false;
printer->Print("///$line$\n", "line", *it);
}
}
printer->Print("/// </summary>\n");
}
template <typename DescriptorType>
static void WriteDocCommentBody(
io::Printer* printer, const DescriptorType* descriptor) {
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
WriteDocCommentBodyImpl(printer, location);
}
}
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
WriteDocCommentBody(printer, message);
}
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
WriteDocCommentBody(printer, field);
}
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
WriteDocCommentBody(printer, enumDescriptor);
}
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
WriteDocCommentBody(printer, value);
}
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
WriteDocCommentBody(printer, method);
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,51 @@
// 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_DOC_COMMENT_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__

View File

@@ -0,0 +1,99 @@
// 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/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_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_enum.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor) {
}
EnumGenerator::~EnumGenerator() {
}
void EnumGenerator::Generate(io::Printer* printer) {
WriteEnumDocComment(printer, descriptor_);
printer->Print("$access_level$ enum $name$ {\n",
"access_level", class_access_level(),
"name", descriptor_->name());
printer->Indent();
std::set<std::string> used_names;
std::set<int> used_number;
for (int i = 0; i < descriptor_->value_count(); i++) {
WriteEnumValueDocComment(printer, descriptor_->value(i));
std::string original_name = descriptor_->value(i)->name();
std::string name =
GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
// Make sure we don't get any duplicate names due to prefix removal.
while (!used_names.insert(name).second) {
// It's possible we'll end up giving this warning multiple times, but that's better than not at all.
GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
<< ") in " << descriptor_->name() << "; adding underscore to distinguish";
name += "_";
}
int number = descriptor_->value(i)->number();
if (!used_number.insert(number).second) {
printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
"original_name", original_name,
"name", name,
"number", StrCat(number));
} else {
printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
"original_name", original_name,
"name", name,
"number", StrCat(number));
}
}
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,66 @@
// 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_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class EnumGenerator : public SourceGeneratorBase {
public:
EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
~EnumGenerator();
EnumGenerator(const EnumGenerator&) = delete;
EnumGenerator& operator=(const EnumGenerator&) = delete;
void Generate(io::Printer* printer);
private:
const EnumDescriptor* descriptor_;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__

View File

@@ -0,0 +1,135 @@
// 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/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_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
}
EnumFieldGenerator::~EnumFieldGenerator() {
}
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
"$property_name$ = ($type_name$) input.ReadEnum();\n");
}
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_,
"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 += $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, $default_value$)");
}
void EnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
}
void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
}
void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// TODO(jonskeet): What about if we read the default value?
printer->Print(
variables_,
"$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.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n");
}
void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,83 @@
// 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_ENUM_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class EnumFieldGenerator : public PrimitiveFieldGenerator {
public:
EnumFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~EnumFieldGenerator();
EnumFieldGenerator(const EnumFieldGenerator&) = delete;
EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
virtual void GenerateCodecCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
};
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
public:
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~EnumOneofFieldGenerator();
EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete;
EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete;
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__

View File

@@ -0,0 +1,459 @@
// 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 <cmath>
#include <limits>
#include <sstream>
#include <google/protobuf/compiler/code_generator.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/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>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
void FieldGeneratorBase::SetCommonFieldVariables(
std::map<std::string, std::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());
int part_tag_size = tag_size;
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
part_tag_size /= 2;
}
uint tag = internal::WireFormat::MakeTag(descriptor_);
uint8 tag_array[5];
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
std::string tag_bytes = StrCat(tag_array[0]);
for (int i = 1; i < part_tag_size; i++) {
tag_bytes += ", " + StrCat(tag_array[i]);
}
(*variables)["tag"] = StrCat(tag);
(*variables)["tag_size"] = StrCat(tag_size);
(*variables)["tag_bytes"] = tag_bytes;
if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
tag = internal::WireFormatLite::MakeTag(
descriptor_->number(),
internal::WireFormatLite::WIRETYPE_END_GROUP);
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
tag_bytes = StrCat(tag_array[0]);
for (int i = 1; i < part_tag_size; i++) {
tag_bytes += ", " + StrCat(tag_array[i]);
}
variables_["end_tag"] = StrCat(tag);
variables_["end_tag_bytes"] = tag_bytes;
}
(*variables)["access_level"] = "public";
(*variables)["property_name"] = property_name();
(*variables)["type_name"] = type_name();
(*variables)["extended_type"] = GetClassName(descriptor_->containing_type());
(*variables)["name"] = name();
(*variables)["descriptor_name"] = descriptor_->name();
(*variables)["default_value"] = default_value();
(*variables)["capitalized_type_name"] = capitalized_type_name();
(*variables)["number"] = number();
if (has_default_value() && !SupportsPresenceApi(descriptor_)) {
(*variables)["name_def_message"] =
(*variables)["name"] + "_ = " + (*variables)["default_value"];
} else {
(*variables)["name_def_message"] = (*variables)["name"] + "_";
}
if (SupportsPresenceApi(descriptor_)) {
(*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
(*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
(*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
(*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
if (presenceIndex_ != -1) {
std::string hasBitsNumber = StrCat(presenceIndex_ / 32);
std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
(*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
(*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
(*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
}
} else {
(*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(
std::map<std::string, std::string>* variables) {
(*variables)["oneof_name"] = oneof_name();
if (SupportsPresenceApi(descriptor_)) {
(*variables)["has_property_check"] = "Has" + property_name();
} else {
(*variables)["has_property_check"] =
oneof_name() + "Case_ == " + oneof_property_name() +
"OneofCase." + property_name();
}
(*variables)["oneof_property_name"] = oneof_property_name();
}
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
int presenceIndex, const Options* options)
: SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor),
presenceIndex_(presenceIndex) {
SetCommonFieldVariables(&variables_);
}
FieldGeneratorBase::~FieldGeneratorBase() {
}
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::GenerateCodecCode(io::Printer* printer) {
// No-op: expect this to be overridden by appropriate types.
// Could fail if we get called here though...
}
void FieldGeneratorBase::GenerateExtensionCode(io::Printer* printer) {
// No-op: only message fields, enum fields, primitives,
// and repeated fields need this default is to not generate any code
}
void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
// for some field types the value of "use_parse_context" doesn't matter,
// so we fallback to the default implementation.
GenerateParsingCode(printer);
}
void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
// for some field types the value of "use_write_context" doesn't matter,
// so we fallback to the default implementation.
GenerateSerializationCode(printer);
}
void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
if (descriptor_->options().deprecated()) {
printer->Print("[global::System.ObsoleteAttribute]\n");
} else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor_->message_type()->options().deprecated()) {
printer->Print("[global::System.ObsoleteAttribute]\n");
}
}
void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
AddDeprecatedFlag(printer);
WriteGeneratedCodeAttributes(printer);
}
std::string FieldGeneratorBase::oneof_property_name() {
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
}
std::string FieldGeneratorBase::oneof_name() {
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
}
std::string FieldGeneratorBase::property_name() {
return GetPropertyName(descriptor_);
}
std::string FieldGeneratorBase::name() {
return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
}
std::string FieldGeneratorBase::type_name() {
return type_name(descriptor_);
}
std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
return GetClassName(descriptor->enum_type());
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
const FieldDescriptor* wrapped_field =
descriptor->message_type()->field(0);
std::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:
return "float";
case FieldDescriptor::TYPE_INT64:
return "long";
case FieldDescriptor::TYPE_UINT64:
return "ulong";
case FieldDescriptor::TYPE_INT32:
return "int";
case FieldDescriptor::TYPE_FIXED64:
return "ulong";
case FieldDescriptor::TYPE_FIXED32:
return "uint";
case FieldDescriptor::TYPE_BOOL:
return "bool";
case FieldDescriptor::TYPE_STRING:
return "string";
case FieldDescriptor::TYPE_BYTES:
return "pb::ByteString";
case FieldDescriptor::TYPE_UINT32:
return "uint";
case FieldDescriptor::TYPE_SFIXED32:
return "int";
case FieldDescriptor::TYPE_SFIXED64:
return "long";
case FieldDescriptor::TYPE_SINT32:
return "int";
case FieldDescriptor::TYPE_SINT64:
return "long";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
bool FieldGeneratorBase::has_default_value() {
switch (descriptor_->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
return true;
case FieldDescriptor::TYPE_DOUBLE:
return descriptor_->default_value_double() != 0.0;
case FieldDescriptor::TYPE_FLOAT:
return descriptor_->default_value_float() != 0.0;
case FieldDescriptor::TYPE_INT64:
return descriptor_->default_value_int64() != 0L;
case FieldDescriptor::TYPE_UINT64:
return descriptor_->default_value_uint64() != 0L;
case FieldDescriptor::TYPE_INT32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_FIXED64:
return descriptor_->default_value_uint64() != 0L;
case FieldDescriptor::TYPE_FIXED32:
return descriptor_->default_value_uint32() != 0;
case FieldDescriptor::TYPE_BOOL:
return descriptor_->default_value_bool();
case FieldDescriptor::TYPE_STRING:
return true;
case FieldDescriptor::TYPE_BYTES:
return true;
case FieldDescriptor::TYPE_UINT32:
return descriptor_->default_value_uint32() != 0;
case FieldDescriptor::TYPE_SFIXED32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_SFIXED64:
return descriptor_->default_value_int64() != 0L;
case FieldDescriptor::TYPE_SINT32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_SINT64:
return descriptor_->default_value_int64() != 0L;
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return true;
}
}
bool AllPrintableAscii(const std::string& text) {
for(int i = 0; i < text.size(); i++) {
if (text[i] < 0x20 || text[i] > 0x7e) {
return false;
}
}
return true;
}
std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "\"\"";
else
return "global::System.Text.Encoding.UTF8.GetString(global::System."
"Convert.FromBase64String(\"" +
StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")";
}
std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "pb::ByteString.Empty";
else
return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
}
std::string FieldGeneratorBase::default_value() {
return default_value(descriptor_);
}
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
return GetClassName(descriptor->default_value_enum()->type()) + "." +
GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
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();
if (value == std::numeric_limits<double>::infinity()) {
return "double.PositiveInfinity";
} else if (value == -std::numeric_limits<double>::infinity()) {
return "double.NegativeInfinity";
} else if (std::isnan(value)) {
return "double.NaN";
}
return StrCat(value) + "D";
}
case FieldDescriptor::TYPE_FLOAT: {
float value = descriptor->default_value_float();
if (value == std::numeric_limits<float>::infinity()) {
return "float.PositiveInfinity";
} else if (value == -std::numeric_limits<float>::infinity()) {
return "float.NegativeInfinity";
} else if (std::isnan(value)) {
return "float.NaN";
}
return StrCat(value) + "F";
}
case FieldDescriptor::TYPE_INT64:
return StrCat(descriptor->default_value_int64()) + "L";
case FieldDescriptor::TYPE_UINT64:
return StrCat(descriptor->default_value_uint64()) + "UL";
case FieldDescriptor::TYPE_INT32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_FIXED64:
return StrCat(descriptor->default_value_uint64()) + "UL";
case FieldDescriptor::TYPE_FIXED32:
return StrCat(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_BOOL:
if (descriptor->default_value_bool()) {
return "true";
} else {
return "false";
}
case FieldDescriptor::TYPE_STRING:
return GetStringDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_BYTES:
return GetBytesDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_UINT32:
return StrCat(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_SFIXED32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_SFIXED64:
return StrCat(descriptor->default_value_int64()) + "L";
case FieldDescriptor::TYPE_SINT32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_SINT64:
return StrCat(descriptor->default_value_int64()) + "L";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
std::string FieldGeneratorBase::number() {
return StrCat(descriptor_->number());
}
std::string FieldGeneratorBase::capitalized_type_name() {
switch (descriptor_->type()) {
case FieldDescriptor::TYPE_ENUM:
return "Enum";
case FieldDescriptor::TYPE_MESSAGE:
return "Message";
case FieldDescriptor::TYPE_GROUP:
return "Group";
case FieldDescriptor::TYPE_DOUBLE:
return "Double";
case FieldDescriptor::TYPE_FLOAT:
return "Float";
case FieldDescriptor::TYPE_INT64:
return "Int64";
case FieldDescriptor::TYPE_UINT64:
return "UInt64";
case FieldDescriptor::TYPE_INT32:
return "Int32";
case FieldDescriptor::TYPE_FIXED64:
return "Fixed64";
case FieldDescriptor::TYPE_FIXED32:
return "Fixed32";
case FieldDescriptor::TYPE_BOOL:
return "Bool";
case FieldDescriptor::TYPE_STRING:
return "String";
case FieldDescriptor::TYPE_BYTES:
return "Bytes";
case FieldDescriptor::TYPE_UINT32:
return "UInt32";
case FieldDescriptor::TYPE_SFIXED32:
return "SFixed32";
case FieldDescriptor::TYPE_SFIXED64:
return "SFixed64";
case FieldDescriptor::TYPE_SINT32:
return "SInt32";
case FieldDescriptor::TYPE_SINT64:
return "SInt64";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,111 @@
// 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_FIELD_BASE_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
#include <string>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class FieldGeneratorBase : public SourceGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
~FieldGeneratorBase();
FieldGeneratorBase(const FieldGeneratorBase&) = delete;
FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete;
virtual void GenerateCloningCode(io::Printer* printer) = 0;
virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateCodecCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer) = 0;
virtual void GenerateMergingCode(io::Printer* printer) = 0;
virtual void GenerateParsingCode(io::Printer* printer) = 0;
virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer) = 0;
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
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:
const FieldDescriptor* descriptor_;
const int presenceIndex_;
std::map<std::string, std::string> variables_;
void AddDeprecatedFlag(io::Printer* printer);
void AddNullCheck(io::Printer* printer);
void AddNullCheck(io::Printer* printer, const std::string& name);
void AddPublicMemberAttributes(io::Printer* printer);
void SetCommonOneofFieldVariables(
std::map<std::string, std::string>* variables);
std::string oneof_property_name();
std::string oneof_name();
std::string property_name();
std::string name();
std::string type_name();
std::string type_name(const FieldDescriptor* descriptor);
bool has_default_value();
std::string default_value();
std::string default_value(const FieldDescriptor* descriptor);
std::string number();
std::string capitalized_type_name();
private:
void SetCommonFieldVariables(std::map<std::string, std::string>* variables);
std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__

View File

@@ -0,0 +1,112 @@
// 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/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_generator.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
Generator::Generator() {}
Generator::~Generator() {}
uint64_t Generator::GetSupportedFeatures() const {
return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
}
void GenerateFile(const FileDescriptor* file, io::Printer* printer,
const Options* options) {
ReflectionClassGenerator reflectionClassGenerator(file, options);
reflectionClassGenerator.Generate(printer);
}
bool Generator::Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const {
std::vector<std::pair<std::string, std::string> > options;
ParseGeneratorParameter(parameter, &options);
struct Options cli_options;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "file_extension") {
cli_options.file_extension = options[i].second;
} else if (options[i].first == "base_namespace") {
cli_options.base_namespace = options[i].second;
cli_options.base_namespace_specified = true;
} else if (options[i].first == "internal_access") {
cli_options.internal_access = true;
} else if (options[i].first == "serializable") {
cli_options.serializable = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
std::string filename_error = "";
std::string filename = GetOutputFile(file,
cli_options.file_extension,
cli_options.base_namespace_specified,
cli_options.base_namespace,
&filename_error);
if (filename.empty()) {
*error = filename_error;
return false;
}
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(filename));
io::Printer printer(output.get(), '$');
GenerateFile(file, &printer, &cli_options);
return true;
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,70 @@
// 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.
// Generates C# code for a given .proto file.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// CodeGenerator implementation which generates a C# source file and
// header. If you create your own protocol compiler binary and you want
// it to support C# output, you can do so by registering an instance of this
// CodeGenerator with the CommandLineInterface in your main() function.
class PROTOC_EXPORT Generator : public CodeGenerator {
public:
Generator();
~Generator();
bool Generate(
const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const override;
uint64_t GetSupportedFeatures() const override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__

View File

@@ -0,0 +1,70 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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 <memory>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/testing/file.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
namespace {
TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
// Identifiers can't start with digits
EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
}
} // namespace
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,592 @@
// 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 <limits>
#include <vector>
#include <sstream>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.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/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_options.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 {
namespace compiler {
namespace csharp {
CSharpType GetCSharpType(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_INT64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_UINT32:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_UINT64:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_SINT32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_SINT64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_FIXED32:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_FIXED64:
return CSHARPTYPE_UINT64;
case FieldDescriptor::TYPE_SFIXED32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_SFIXED64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_FLOAT:
return CSHARPTYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE:
return CSHARPTYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL:
return CSHARPTYPE_BOOL;
case FieldDescriptor::TYPE_ENUM:
return CSHARPTYPE_ENUM;
case FieldDescriptor::TYPE_STRING:
return CSHARPTYPE_STRING;
case FieldDescriptor::TYPE_BYTES:
return CSHARPTYPE_BYTESTRING;
case FieldDescriptor::TYPE_GROUP:
return CSHARPTYPE_MESSAGE;
case FieldDescriptor::TYPE_MESSAGE:
return CSHARPTYPE_MESSAGE;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return (CSharpType) -1;
}
std::string StripDotProto(const std::string& proto_file) {
int lastindex = proto_file.find_last_of(".");
return proto_file.substr(0, lastindex);
}
std::string GetFileNamespace(const FileDescriptor* descriptor) {
if (descriptor->options().has_csharp_namespace()) {
return descriptor->options().csharp_namespace();
}
return UnderscoresToCamelCase(descriptor->package(), true, true);
}
// Returns the Pascal-cased last part of the proto file. For example,
// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
std::string GetFileNameBase(const FileDescriptor* descriptor) {
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 GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
// TODO: Detect collisions with existing messages,
// and append an underscore if necessary.
return GetFileNameBase(descriptor) + "Reflection";
}
std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) {
// TODO: Detect collisions with existing messages,
// and append an underscore if necessary.
return GetFileNameBase(descriptor) + "Extensions";
}
// TODO(jtattermusch): can we reuse a utility function?
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter,
bool preserve_period) {
std::string result;
// Note: I distrust ctype.h due to locales.
for (int i = 0; i < input.size(); i++) {
if ('a' <= input[i] && input[i] <= 'z') {
if (cap_next_letter) {
result += input[i] + ('A' - 'a');
} else {
result += input[i];
}
cap_next_letter = false;
} else if ('A' <= input[i] && input[i] <= 'Z') {
if (i == 0 && !cap_next_letter) {
// Force first letter to lower-case unless explicitly told to
// capitalize it.
result += input[i] + ('a' - 'A');
} else {
// Capital letters after the first are left as-is.
result += input[i];
}
cap_next_letter = false;
} else if ('0' <= input[i] && input[i] <= '9') {
result += input[i];
cap_next_letter = true;
} else {
cap_next_letter = true;
if (input[i] == '.' && preserve_period) {
result += '.';
}
}
}
// Add a trailing "_" if the name should be altered.
if (input.size() > 0 && input[input.size() - 1] == '#') {
result += '_';
}
return result;
}
std::string UnderscoresToPascalCase(const std::string& input) {
return UnderscoresToCamelCase(input, true);
}
// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
// into a PascalCase string. Precise rules implemented:
// Previous input character Current character Case
// Any Non-alphanumeric Skipped
// None - first char of input Alphanumeric Upper
// Non-letter (e.g. _ or 1) Alphanumeric Upper
// Numeric Alphanumeric Upper
// Lower letter Alphanumeric Same as current
// Upper letter Alphanumeric Lower
std::string ShoutyToPascalCase(const std::string& input) {
std::string result;
// Simple way of implementing "always start with upper"
char previous = '_';
for (int i = 0; i < input.size(); i++) {
char current = input[i];
if (!ascii_isalnum(current)) {
previous = current;
continue;
}
if (!ascii_isalnum(previous)) {
result += ascii_toupper(current);
} else if (ascii_isdigit(previous)) {
result += ascii_toupper(current);
} else if (ascii_islower(previous)) {
result += current;
} else {
result += ascii_tolower(current);
}
previous = current;
}
return result;
}
// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
// (foo, foo_bar) => bar - underscore after prefix is skipped
// (FOO, foo_bar) => bar - casing is ignored
// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
// (foobar, foo_barbaz) => baz - underscore in value is ignored
// (foo, bar) => bar - prefix isn't matched; return original value
std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
// First normalize to a lower-case no-underscores prefix to match against
std::string prefix_to_match = "";
for (size_t i = 0; i < prefix.size(); i++) {
if (prefix[i] != '_') {
prefix_to_match += ascii_tolower(prefix[i]);
}
}
// This keeps track of how much of value we've consumed
size_t prefix_index, value_index;
for (prefix_index = 0, value_index = 0;
prefix_index < prefix_to_match.size() && value_index < value.size();
value_index++) {
// Skip over underscores in the value
if (value[value_index] == '_') {
continue;
}
if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
// Failed to match the prefix - bail out early.
return value;
}
}
// If we didn't finish looking through the prefix, we can't strip it.
if (prefix_index < prefix_to_match.size()) {
return value;
}
// Step over any underscores after the prefix
while (value_index < value.size() && value[value_index] == '_') {
value_index++;
}
// If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
if (value_index == value.size()) {
return value;
}
return value.substr(value_index);
}
// Format the enum value name in a pleasant way for C#:
// - Strip the enum name as a prefix if possible
// - Convert to PascalCase.
// For example, an enum called Color with a value of COLOR_BLUE should
// result in an enum value in C# called just Blue
std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
std::string result = ShoutyToPascalCase(stripped);
// Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
// string is a valid identifier.
if (ascii_isdigit(result[0])) {
result = "_" + result;
}
return result;
}
uint GetGroupEndTag(const Descriptor* descriptor) {
const Descriptor* containing_type = descriptor->containing_type();
if (containing_type != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_type->field_count(); i++) {
field = containing_type->field(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
for (int i = 0; i < containing_type->extension_count(); i++) {
field = containing_type->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
} else {
const FileDescriptor* containing_file = descriptor->file();
if (containing_file != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_file->extension_count(); i++) {
field = containing_file->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
}
}
return 0;
}
std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
std::string result = GetFileNamespace(file);
if (!result.empty()) {
result += '.';
}
std::string classname;
if (file->package().empty()) {
classname = name;
} else {
// Strip the proto package from full_name since we've replaced it with
// the C# namespace.
classname = name.substr(file->package().size() + 1);
}
result += StringReplace(classname, ".", ".Types.", true);
return "global::" + result;
}
std::string GetReflectionClassName(const FileDescriptor* descriptor) {
std::string result = GetFileNamespace(descriptor);
if (!result.empty()) {
result += '.';
}
result += GetReflectionClassUnqualifiedName(descriptor);
return "global::" + result;
}
std::string GetFullExtensionName(const FieldDescriptor* descriptor) {
if (descriptor->extension_scope()) {
return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor);
}
else {
return GetExtensionClassUnqualifiedName(descriptor->file()) + "." + GetPropertyName(descriptor);
}
}
std::string GetClassName(const Descriptor* descriptor) {
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
std::string GetClassName(const EnumDescriptor* descriptor) {
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In C#, though, we would like to retain the original
// capitalization of the type name.
std::string GetFieldName(const FieldDescriptor* descriptor) {
if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
return descriptor->message_type()->name();
} else {
return descriptor->name();
}
}
std::string GetFieldConstantName(const FieldDescriptor* field) {
return GetPropertyName(field) + "FieldNumber";
}
std::string GetPropertyName(const FieldDescriptor* descriptor) {
// TODO(jtattermusch): consider introducing csharp_property_name field option
std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
// 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;
}
std::string GetOutputFile(const FileDescriptor* descriptor,
const std::string file_extension,
const bool generate_directories,
const std::string base_namespace,
std::string* error) {
std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
if (!generate_directories) {
return relative_filename;
}
std::string ns = GetFileNamespace(descriptor);
std::string namespace_suffix = ns;
if (!base_namespace.empty()) {
// Check that the base_namespace is either equal to or a leading part of
// the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
// be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
// to both.
std::string extended_ns = ns + ".";
if (extended_ns.find(base_namespace + ".") != 0) {
*error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
return ""; // This will be ignored, because we've set an error.
}
namespace_suffix = ns.substr(base_namespace.length());
if (namespace_suffix.find(".") == 0) {
namespace_suffix = namespace_suffix.substr(1);
}
}
std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
if (!namespace_dir.empty()) {
namespace_dir += "/";
}
return namespace_dir + relative_filename;
}
// TODO: c&p from Java protoc plugin
// For encodings with fixed sizes, returns that size in bytes. Otherwise
// returns -1.
int GetFixedSize(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32 : return -1;
case FieldDescriptor::TYPE_INT64 : return -1;
case FieldDescriptor::TYPE_UINT32 : return -1;
case FieldDescriptor::TYPE_UINT64 : return -1;
case FieldDescriptor::TYPE_SINT32 : return -1;
case FieldDescriptor::TYPE_SINT64 : return -1;
case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize;
case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize;
case FieldDescriptor::TYPE_BOOL : return internal::WireFormatLite::kBoolSize;
case FieldDescriptor::TYPE_ENUM : return -1;
case FieldDescriptor::TYPE_STRING : return -1;
case FieldDescriptor::TYPE_BYTES : return -1;
case FieldDescriptor::TYPE_GROUP : return -1;
case FieldDescriptor::TYPE_MESSAGE : return -1;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return -1;
}
static const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string StringToBase64(const std::string& input) {
std::string result;
size_t remaining = input.size();
const unsigned char *src = (const unsigned char*) input.c_str();
while (remaining > 2) {
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
result += base64_chars[src[2] & 0x3f];
remaining -= 3;
src += 3;
}
switch (remaining) {
case 2:
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
result += base64_chars[(src[1] & 0xf) << 2];
result += '=';
src += 2;
break;
case 1:
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4)];
result += '=';
result += '=';
src += 1;
break;
}
return result;
}
std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
std::string fdp_bytes;
FileDescriptorProto fdp;
descriptor->CopyTo(&fdp);
fdp.SerializeToString(&fdp_bytes);
return StringToBase64(fdp_bytes);
}
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
if (descriptor->is_repeated()) {
if (descriptor->is_map()) {
return new MapFieldGenerator(descriptor, presenceIndex, options);
} else {
return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (IsWrapperType(descriptor)) {
if (descriptor->real_containing_oneof()) {
return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new WrapperFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (descriptor->real_containing_oneof()) {
return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new MessageFieldGenerator(descriptor, presenceIndex, options);
}
}
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->real_containing_oneof()) {
return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new EnumFieldGenerator(descriptor, presenceIndex, options);
}
}
default:
if (descriptor->is_repeated()) {
return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->real_containing_oneof()) {
return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
}
}
}
}
bool IsNullable(const FieldDescriptor* descriptor) {
if (descriptor->is_repeated()) {
return true;
}
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_BOOL:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SFIXED32:
case FieldDescriptor::TYPE_SFIXED64:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_SINT64:
return false;
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES:
return true;
default:
GOOGLE_LOG(FATAL) << "Unknown field type.";
return true;
}
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,195 @@
// 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.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#include <string>
#include <google/protobuf/port.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
struct Options;
class FieldGeneratorBase;
// TODO: start using this enum.
enum CSharpType {
CSHARPTYPE_INT32 = 1,
CSHARPTYPE_INT64 = 2,
CSHARPTYPE_UINT32 = 3,
CSHARPTYPE_UINT64 = 4,
CSHARPTYPE_FLOAT = 5,
CSHARPTYPE_DOUBLE = 6,
CSHARPTYPE_BOOL = 7,
CSHARPTYPE_STRING = 8,
CSHARPTYPE_BYTESTRING = 9,
CSHARPTYPE_MESSAGE = 10,
CSHARPTYPE_ENUM = 11,
MAX_CSHARPTYPE = 11
};
// Converts field type to corresponding C# type.
CSharpType GetCSharpType(FieldDescriptor::Type type);
std::string StripDotProto(const std::string& proto_file);
// Gets unqualified name of the reflection class
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
// Gets unqualified name of the extension class
std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
std::string GetClassName(const EnumDescriptor* descriptor);
std::string GetFieldName(const FieldDescriptor* descriptor);
std::string GetFieldConstantName(const FieldDescriptor* field);
std::string GetPropertyName(const FieldDescriptor* descriptor);
int GetFixedSize(FieldDescriptor::Type type);
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);
// Note that we wouldn't normally want to export this (we're not expecting
// it to be used outside libprotoc itself) but this exposes it for testing.
std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name,
const std::string& enum_value_name);
// TODO(jtattermusch): perhaps we could move this to strutil
std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
std::string GetFullExtensionName(const FieldDescriptor* descriptor);
bool IsNullable(const FieldDescriptor* 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();
}
// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group
uint GetGroupEndTag(const Descriptor* descriptor);
// 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) {
return descriptor->name() == "google/protobuf/descriptor.proto";
}
// Determines whether the given message is an options message within descriptor.proto.
inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
if (!IsDescriptorProto(descriptor->file())) {
return false;
}
const std::string name = descriptor->full_name();
return name == "google.protobuf.FileOptions" ||
name == "google.protobuf.MessageOptions" ||
name == "google.protobuf.FieldOptions" ||
name == "google.protobuf.OneofOptions" ||
name == "google.protobuf.EnumOptions" ||
name == "google.protobuf.EnumValueOptions" ||
name == "google.protobuf.ServiceOptions" ||
name == "google.protobuf.MethodOptions";
}
inline bool IsWrapperType(const FieldDescriptor* descriptor) {
return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
}
inline bool IsProto2(const FileDescriptor* descriptor) {
return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
}
inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
// Unlike most languages, we don't generate Has/Clear members for message
// types, because they can always be set to null in C#. They're not really
// needed for oneof fields in proto2 either, as everything can be done via
// oneof case, but we follow the convention from other languages. Proto3
// oneof fields never have Has/Clear members - but will also never have
// the explicit optional keyword either.
//
// None of the built-in helpers (descriptor->has_presence() etc) describe
// quite the behavior we want, so the rules are explicit below.
if (descriptor->is_repeated() ||
descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
return false;
}
// has_optional_keyword() has more complex rules for proto2, but that
// doesn't matter given the first part of this condition.
return IsProto2(descriptor->file()) || descriptor->has_optional_keyword();
}
inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
return SupportsPresenceApi(descriptor) &&
!IsNullable(descriptor) &&
!descriptor->is_extension() &&
!descriptor->real_containing_oneof();
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__

View File

@@ -0,0 +1,152 @@
// 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/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_doc_comment.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 presenceIndex,
const Options* options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
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);
std::unique_ptr<FieldGeneratorBase> key_generator(
CreateFieldGenerator(key_descriptor, 1, this->options()));
std::unique_ptr<FieldGeneratorBase> value_generator(
CreateFieldGenerator(value_descriptor, 2, this->options()));
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$>();\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(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) {
GenerateParsingCode(printer, true);
}
void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
}
void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
: "$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

View File

@@ -0,0 +1,75 @@
// 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_MAP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_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 MapFieldGenerator : public FieldGeneratorBase {
public:
MapFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
~MapFieldGenerator();
MapFieldGenerator(const MapFieldGenerator&) = delete;
MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__

View File

@@ -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 <google/protobuf/compiler/code_generator.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/wire_format.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_enum.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>
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(descriptor->file(), 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

View File

@@ -0,0 +1,94 @@
// 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_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
#include <string>
#include <vector>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class FieldGeneratorBase;
class MessageGenerator : public SourceGeneratorBase {
public:
MessageGenerator(const Descriptor* descriptor, const Options* options);
~MessageGenerator();
MessageGenerator(const MessageGenerator&) = delete;
MessageGenerator& operator=(const MessageGenerator&) = delete;
void GenerateCloningCode(io::Printer* printer);
void GenerateFreezingCode(io::Printer* printer);
void GenerateFrameworkMethods(io::Printer* printer);
void Generate(io::Printer* printer);
private:
const Descriptor* descriptor_;
std::vector<const FieldDescriptor*> fields_by_number_;
int has_bit_field_count_;
uint end_tag_;
bool has_extension_ranges_;
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateWriteToBody(io::Printer* printer, bool use_write_context);
void GenerateMergingMethods(io::Printer* printer);
void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context);
int GetPresenceIndex(const FieldDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor);
bool HasNestedGeneratedTypes();
void AddDeprecatedFlag(io::Printer* printer);
void AddSerializableAttribute(io::Printer* printer);
std::string class_name();
std::string full_class_name();
// field descriptors sorted by number
const std::vector<const FieldDescriptor*>& fields_by_number();
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__

View File

@@ -0,0 +1,293 @@
// 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/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/wire_format.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
if (!SupportsPresenceApi(descriptor_)) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
}
}
MessageFieldGenerator::~MessageFieldGenerator() {
}
void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private $type_name$ $name$_;\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
" $name$_ = value;\n"
" }\n"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $name$_ != null; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" $name$_ = null;\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if (other.$has_property_check$) {\n"
" if ($has_not_property_check$) {\n"
" $property_name$ = new $type_name$();\n"
" }\n"
" $property_name$.MergeFrom(other.$property_name$);\n"
"}\n");
}
void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_not_property_check$) {\n"
" $property_name$ = new $type_name$();\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(variables_, "input.ReadMessage($property_name$);\n");
} else {
printer->Print(variables_, "input.ReadGroup($property_name$);\n");
}
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage($property_name$);\n"
"}\n");
} else {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteGroup($property_name$);\n"
" output.WriteRawTag($end_tag_bytes$);\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
"}\n");
} else {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
"}\n");
}
}
void MessageFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
}
void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
}
void MessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_["field_name"] = GetFieldName(descriptor_);
printer->Print(
variables_,
"PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
}
void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
}
void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
}
void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
} else {
printer->Print(
variables_,
"pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
}
}
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options)
: MessageFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
}
void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$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"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_,
"if ($property_name$ == null) {\n"
" $property_name$ = new $type_name$();\n"
"}\n"
"$property_name$.MergeFrom(other.$property_name$);\n");
}
void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// TODO(jonskeet): We may be able to do better than this
printer->Print(
variables_,
"$type_name$ subBuilder = new $type_name$();\n"
"if ($has_property_check$) {\n"
" subBuilder.MergeFrom($property_name$);\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print("input.ReadMessage(subBuilder);\n");
} else {
printer->Print("input.ReadGroup(subBuilder);\n");
}
printer->Print(variables_, "$property_name$ = subBuilder;\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
} // namespace google

View File

@@ -0,0 +1,93 @@
// 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_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_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 MessageFieldGenerator : public FieldGeneratorBase {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~MessageFieldGenerator();
MessageFieldGenerator(const MessageFieldGenerator&) = delete;
MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
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 GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
};
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~MessageOneofFieldGenerator();
MessageOneofFieldGenerator(const MessageOneofFieldGenerator&) = delete;
MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) =
delete;
virtual void GenerateCloningCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__

View File

@@ -0,0 +1,109 @@
// 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.
//
// Provides a mechanism for mapping a descriptor to the
// fully-qualified name of the corresponding C# class.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
#include <string>
#include <google/protobuf/port.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class Descriptor;
class EnumDescriptor;
class FileDescriptor;
class ServiceDescriptor;
namespace compiler {
namespace csharp {
// Requires:
// descriptor != NULL
//
// Returns:
// The namespace to use for given file descriptor.
std::string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
// Requires:
// descriptor != NULL
//
// Returns:
// The fully-qualified C# class name.
std::string PROTOC_EXPORT GetClassName(const Descriptor* descriptor);
// 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 PROTOC_EXPORT
GetReflectionClassName(const FileDescriptor* descriptor);
// Generates output file name for given file descriptor. If generate_directories
// is true, the output file will be put under directory corresponding to file's
// namespace. base_namespace can be used to strip some of the top level
// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar",
// the resulting file will be put under directory "Foo" (and not "Bar/Foo").
//
// Requires:
// descriptor != NULL
// error != NULL
//
// Returns:
// The file name to use as output file for given file descriptor. In case
// of failure, this function will return empty string and error parameter
// will contain the error message.
std::string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor,
const std::string file_extension,
const bool generate_directories,
const std::string base_namespace,
std::string* error);
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__

View File

@@ -0,0 +1,81 @@
// 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_OPTIONS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
#include <string>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// Generator options (used by csharp_generator.cc):
struct Options {
Options() :
file_extension(".cs"),
base_namespace(""),
base_namespace_specified(false),
internal_access(false),
serializable(false) {
}
// Extension of the generated file. Defaults to ".cs"
std::string file_extension;
// Base namespace to use to create directory hierarchy. Defaults to "".
// This option allows the simple creation of a conventional C# file layout,
// where directories are created relative to a project-specific base
// namespace. For example, in a project with a base namespace of PetShop, a
// proto of user.proto with a C# namespace of PetShop.Model.Shared would
// generate Model/Shared/User.cs underneath the specified --csharp_out
// directory.
//
// If no base namespace is specified, all files are generated in the
// --csharp_out directory, with no subdirectories created automatically.
std::string base_namespace;
// Whether the base namespace has been explicitly specified by the user.
// This is required as the base namespace can be explicitly set to the empty
// string, meaning "create a full directory hierarchy, starting from the first
// segment of the namespace."
bool base_namespace_specified;
// Whether the generated classes should have accessibility level of "internal".
// Defaults to false that generates "public" classes.
bool internal_access;
// Whether the generated classes should have a global::System.Serializable attribute added
// Defaults to false
bool serializable;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__

View File

@@ -0,0 +1,349 @@
// 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/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_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
// TODO(jonskeet): Make this cleaner...
is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
&& descriptor->type() != FieldDescriptor::TYPE_BYTES;
if (!is_value_type && !SupportsPresenceApi(descriptor_)) {
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) {
// Note: in multiple places, this code assumes that all fields
// that support presence are either nullable, or use a presence field bit.
// Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below.
// Extensions are not generated here either.
// Proto2 allows different default values to be specified. These are retained
// via static fields. They don't particularly need to be, but we don't need
// to change that. In Proto3 the default value we don't generate these
// fields, just using the literal instead.
if (IsProto2(descriptor_->file())) {
// Note: "private readonly static" isn't as idiomatic as
// "private static readonly", but changing this now would create a lot of
// churn in generated code with near-to-zero benefit.
printer->Print(
variables_,
"private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
variables_["default_value_access"] =
variables_["property_name"] + "DefaultValue";
} else {
variables_["default_value_access"] = variables_["default_value"];
}
// Declare the field itself.
printer->Print(
variables_,
"private $type_name$ $name_def_message$;\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
// Most of the work is done in the property:
// Declare the property itself (the same for all options)
printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n");
// Specify the "getter", which may need to check for a presence field.
if (SupportsPresenceApi(descriptor_)) {
if (IsNullable(descriptor_)) {
printer->Print(
variables_,
" get { return $name$_ ?? $default_value_access$; }\n");
} else {
printer->Print(
variables_,
// Note: it's possible that this could be rewritten as a
// conditional ?: expression, but there's no significant benefit
// to changing it.
" get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n");
}
} else {
printer->Print(
variables_,
" get { return $name$_; }\n");
}
// Specify the "setter", which may need to set a field bit as well as the
// value.
printer->Print(" set {\n");
if (presenceIndex_ != -1) {
printer->Print(
variables_,
" $set_has_field$;\n");
}
if (is_value_type) {
printer->Print(
variables_,
" $name$_ = value;\n");
} else {
printer->Print(
variables_,
" $name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
printer->Print(
" }\n"
"}\n");
// The "HasFoo" property, where required.
if (SupportsPresenceApi(descriptor_)) {
printer->Print(variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return ");
if (IsNullable(descriptor_)) {
printer->Print(
variables_,
"$name$_ != null; }\n}\n");
} else {
printer->Print(
variables_,
"$has_field_check$; }\n}\n");
}
}
// The "ClearFoo" method, where required.
if (SupportsPresenceApi(descriptor_)) {
printer->Print(variables_,
"/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n");
if (IsNullable(descriptor_)) {
printer->Print(variables_, " $name$_ = null;\n");
} else {
printer->Print(variables_, " $clear_has_field$;\n");
}
printer->Print("}\n");
}
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($other_has_property_check$) {\n"
" $property_name$ = other.$property_name$;\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// 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.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");
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", StrCat(fixedSize),
"tag_size", variables_["tag_size"]);
}
printer->Outdent();
printer->Print("}\n");
}
void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n";
} else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n";
}
printer->Print(variables_, text);
}
void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
} else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
}
printer->Print(variables_, text);
}
void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(
variables_,
"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$, $default_value$)");
}
void PrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
}
void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
" set {\n");
if (is_value_type) {
printer->Print(
variables_,
" $oneof_name$_ = value;\n");
} else {
printer->Print(
variables_,
" $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
printer->Print(
variables_,
" $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_, "$property_name$ = other.$property_name$;\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_,
"$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
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,97 @@
// 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_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_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 {
struct Options;
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~PrimitiveFieldGenerator();
PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
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 GenerateExtensionCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
protected:
bool is_value_type;
};
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~PrimitiveOneofFieldGenerator();
PrimitiveOneofFieldGenerator(const PrimitiveOneofFieldGenerator&) = delete;
PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) =
delete;
virtual void GenerateCloningCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__

View File

@@ -0,0 +1,330 @@
// 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/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_enum.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
#include <google/protobuf/compiler/csharp/csharp_message.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
const Options* options)
: SourceGeneratorBase(file, options),
file_(file) {
namespace_ = GetFileNamespace(file);
reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
extensionClassname_ = GetExtensionClassUnqualifiedName(file);
}
ReflectionClassGenerator::~ReflectionClassGenerator() {
}
void ReflectionClassGenerator::Generate(io::Printer* printer) {
WriteIntroduction(printer);
WriteDescriptor(printer);
// Close the class declaration.
printer->Outdent();
printer->Print("}\n");
if (file_->extension_count() > 0) {
printer->Print(
"/// <summary>Holder for extension identifiers generated from the top "
"level of $file_name$</summary>\n"
"$access_level$ static partial class $class_name$ {\n",
"access_level", class_access_level(), "class_name", extensionClassname_,
"file_name", file_->name());
printer->Indent();
for (int i = 0; i < file_->extension_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGenerator(file_->extension(i), -1, this->options()));
generator->GenerateExtensionCode(printer);
}
printer->Outdent();
printer->Print(
"}\n"
"\n");
}
// write children: Enums
if (file_->enum_type_count() > 0) {
printer->Print("#region Enums\n");
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator enumGenerator(file_->enum_type(i), this->options());
enumGenerator.Generate(printer);
}
printer->Print("#endregion\n");
printer->Print("\n");
}
// write children: Messages
if (file_->message_type_count() > 0) {
printer->Print("#region Messages\n");
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator messageGenerator(file_->message_type(i), this->options());
messageGenerator.Generate(printer);
}
printer->Print("#endregion\n");
printer->Print("\n");
}
// TODO(jtattermusch): add insertion point for services.
if (!namespace_.empty()) {
printer->Outdent();
printer->Print("}\n");
}
printer->Print("\n");
printer->Print("#endregion Designer generated code\n");
}
void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
printer->Print(
"// <auto-generated>\n"
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $file_name$\n"
"// </auto-generated>\n"
"#pragma warning disable 1591, 0612, 3021\n"
"#region Designer generated code\n"
"\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());
if (!namespace_.empty()) {
printer->Print("namespace $namespace$ {\n", "namespace", namespace_);
printer->Indent();
printer->Print("\n");
}
printer->Print(
"/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
"$access_level$ static partial class $reflection_class_name$ {\n"
"\n",
"file_name", file_->name(),
"access_level", class_access_level(),
"reflection_class_name", reflectionClassname_);
printer->Indent();
}
void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) {
printer->Print(
"#region Descriptor\n"
"/// <summary>File descriptor for $file_name$</summary>\n"
"public static pbr::FileDescriptor Descriptor {\n"
" get { return descriptor; }\n"
"}\n"
"private static pbr::FileDescriptor descriptor;\n"
"\n"
"static $reflection_class_name$() {\n",
"file_name", file_->name(),
"reflection_class_name", reflectionClassname_);
printer->Indent();
printer->Print(
"byte[] descriptorData = global::System.Convert.FromBase64String(\n");
printer->Indent();
printer->Indent();
printer->Print("string.Concat(\n");
printer->Indent();
// TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
std::string base64 = FileDescriptorToBase64(file_);
while (base64.size() > 60) {
printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
base64 = base64.substr(60);
}
printer->Print("\"$base64$\"));\n", "base64", base64);
printer->Outdent();
printer->Outdent();
printer->Outdent();
// -----------------------------------------------------------------
// Invoke InternalBuildGeneratedFileFrom() to build the file.
printer->Print(
"descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n");
printer->Print(" new pbr::FileDescriptor[] { ");
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
"$full_reflection_class_name$.Descriptor, ",
"full_reflection_class_name",
GetReflectionClassName(file_->dependency(i)));
}
printer->Print("},\n"
" new pbr::GeneratedClrTypeInfo(");
// 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_->extension_count() > 0) {
std::vector<std::string> extensions;
for (int i = 0; i < file_->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(file_->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");
}
if (file_->message_type_count() > 0) {
printer->Print("new pbr::GeneratedClrTypeInfo[] {\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->Outdent();
printer->Print("}\n");
printer->Print("#endregion\n\n");
}
// 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 ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
if (IsMapEntryMessage(descriptor)) {
printer->Print("null, ");
return;
}
// Generated message type
printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor));
// Fields
if (descriptor->field_count() > 0) {
std::vector<std::string> fields;
fields.reserve(descriptor->field_count());
for (int i = 0; i < descriptor->field_count(); i++) {
fields.push_back(GetPropertyName(descriptor->field(i)));
}
printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \""));
}
else {
printer->Print("null, ");
}
// Oneofs
if (descriptor->oneof_decl_count() > 0) {
std::vector<std::string> oneofs;
oneofs.reserve(descriptor->oneof_decl_count());
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", Join(oneofs, "\", \""));
}
else {
printer->Print("null, ");
}
// Nested enums
if (descriptor->enum_type_count() > 0) {
std::vector<std::string> enums;
enums.reserve(descriptor->enum_type_count());
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enums.push_back(GetClassName(descriptor->enum_type(i)));
}
printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof("));
}
else {
printer->Print("null, ");
}
// Extensions
if (descriptor->extension_count() > 0) {
std::vector<std::string> extensions;
for (int i = 0; i < descriptor->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(descriptor->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");
}
// 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::GeneratedClrTypeInfo[] { ");
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
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,75 @@
// 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_REFLECTION_CLASS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class ReflectionClassGenerator : public SourceGeneratorBase {
public:
ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
~ReflectionClassGenerator();
ReflectionClassGenerator(const ReflectionClassGenerator&) = delete;
ReflectionClassGenerator& operator=(const ReflectionClassGenerator&) = delete;
void Generate(io::Printer* printer);
private:
const FileDescriptor* file_;
std::string namespace_;
std::string reflectionClassname_;
std::string extensionClassname_;
void WriteIntroduction(io::Printer* printer);
void WriteDescriptor(io::Printer* printer);
void WriteGeneratedCodeInfo(const Descriptor* descriptor,
io::Printer* printer,
bool last);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__

View File

@@ -0,0 +1,148 @@
// 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/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/wire_format.h>
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
}
void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"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_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
}
void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
: "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"hash ^= $name$_.GetHashCode();\n");
}
void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if(!$name$_.Equals(other.$name$_)) return false;\n");
}
void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(variables_,
"PrintField(\"$descriptor_name$\", $name$_, writer);\n");
}
void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$name$_.Clone();\n");
}
void RepeatedEnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, "
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x));\n");
}
void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,79 @@
// 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_REPEATED_ENUM_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_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 {
// 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 presenceIndex,
const Options *options);
~RepeatedEnumFieldGenerator();
RepeatedEnumFieldGenerator(const RepeatedEnumFieldGenerator&) = delete;
RepeatedEnumFieldGenerator& operator=(const RepeatedEnumFieldGenerator&) =
delete;
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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__

View File

@@ -0,0 +1,174 @@
// 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/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_doc_comment.h>
#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 {
namespace compiler {
namespace csharp {
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
}
void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"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_)) {
std::unique_ptr<FieldGeneratorBase> single_generator(
new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
} else {
std::unique_ptr<FieldGeneratorBase> single_generator(
new MessageFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
}
printer->Print(";\n");
printer->Print(
variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
: "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"hash ^= $name$_.GetHashCode();\n");
}
void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if(!$name$_.Equals(other.$name$_)) return false;\n");
}
void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_["field_name"] = GetFieldName(descriptor_);
printer->Print(
variables_,
"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) {
}
void RepeatedMessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, ");
if (IsWrapperType(descriptor_)) {
std::unique_ptr<FieldGeneratorBase> single_generator(
new WrapperFieldGenerator(descriptor_, -1, this->options()));
single_generator->GenerateCodecCode(printer);
} else {
std::unique_ptr<FieldGeneratorBase> single_generator(
new MessageFieldGenerator(descriptor_, -1, this->options()));
single_generator->GenerateCodecCode(printer);
}
printer->Print(");\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,79 @@
// 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_REPEATED_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_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 {
struct Options;
class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
public:
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~RepeatedMessageFieldGenerator();
RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
RepeatedMessageFieldGenerator& operator=(
const RepeatedMessageFieldGenerator&) = delete;
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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__

View File

@@ -0,0 +1,145 @@
// 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/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/wire_format.h>
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
}
void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"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");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
: "$name$_.WriteTo(output, _repeated_$name$_codec);\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_,
"hash ^= $name$_.GetHashCode();\n");
}
void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"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) {
}
void RepeatedPrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, pb::FieldCodec.For$capitalized_type_name$($tag$));\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,75 @@
// 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_REPEATED_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_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 RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
public:
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex, const Options* options);
~RepeatedPrimitiveFieldGenerator();
RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = delete;
RepeatedPrimitiveFieldGenerator& operator=(const RepeatedPrimitiveFieldGenerator&) = delete;
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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void WriteHash(io::Printer* printer);
virtual void WriteEquals(io::Printer* printer);
virtual void WriteToString(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__

View File

@@ -0,0 +1,72 @@
// 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/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_source_generator_base.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
const Options *options)
: descriptor_(descriptor), options_(options) {
}
SourceGeneratorBase::~SourceGeneratorBase() {
}
void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
printer->Print("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]\n");
}
std::string SourceGeneratorBase::class_access_level() {
return this->options()->internal_access ? "internal" : "public";
}
const Options* SourceGeneratorBase::options() {
return this->options_;
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@@ -0,0 +1,72 @@
// 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_SOURCE_GENERATOR_BASE_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
#include <string>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
struct Options;
class SourceGeneratorBase {
protected:
SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
virtual ~SourceGeneratorBase();
SourceGeneratorBase(const SourceGeneratorBase&) = delete;
SourceGeneratorBase& operator=(const SourceGeneratorBase&) = delete;
std::string class_access_level();
const Options* options();
// Write any attributes used to decorate generated function members (methods and properties).
// Should not be used to decorate types.
void WriteGeneratedCodeAttributes(io::Printer* printer);
private:
const FileDescriptor* descriptor_;
const Options *options_;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__

View File

@@ -0,0 +1,308 @@
// 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/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_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
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");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
" $name$_ = value;\n"
" }\n"
"}\n\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $name$_ != null; }\n"
"}\n\n");
printer->Print(
variables_,
"/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" $name$_ = null;\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) {
GenerateParsingCode(printer, true);
}
void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$type_name$ value = _single_$name$_codec.Read(ref input);\n"
"if ($has_not_property_check$ || value != $default_value$) {\n"
" $property_name$ = value;\n"
"}\n"
: "$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) {
GenerateSerializationCode(printer, true);
}
void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "if ($has_property_check$) {\n"
" _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n"
"}\n"
: "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) {
const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode($property_name$);\n";
}
else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode($property_name$);\n";
}
printer->Print(variables_, text);
}
void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
}
else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
}
printer->Print(variables_, text);
}
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$)");
}
}
void WrapperFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: WrapperFieldGenerator(descriptor, presenceIndex, options) {
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");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(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");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
}
void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$property_name$ = _oneof_$name$_codec.Read(ref input);\n"
: "$property_name$ = _oneof_$name$_codec.Read(input);\n");
}
void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
// TODO: I suspect this is wrong...
printer->Print(
variables_,
use_write_context
? "if ($has_property_check$) {\n"
" _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n"
"}\n"
: "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

View File

@@ -0,0 +1,99 @@
// 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 {
struct Options;
class WrapperFieldGenerator : public FieldGeneratorBase {
public:
WrapperFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~WrapperFieldGenerator();
WrapperFieldGenerator(const WrapperFieldGenerator&) = delete;
WrapperFieldGenerator& operator=(const WrapperFieldGenerator&) = delete;
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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
virtual void GenerateExtensionCode(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
};
class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
public:
WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~WrapperOneofFieldGenerator();
WrapperOneofFieldGenerator(const WrapperOneofFieldGenerator&) = delete;
WrapperOneofFieldGenerator& operator=(const WrapperOneofFieldGenerator&) = delete;
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer);
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__