mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
Update protobuf source from v2.3.0 to 2.5.0.
This commit is contained in:
parent
486133fea8
commit
2d3cc15cd4
@ -1,373 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// http://code.google.com/p/protobuf/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Author: kenton@google.com (Kenton Varda)
|
|
||||||
// Based on original Protocol Buffers design by
|
|
||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_enum_field.h>
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
|
||||||
#include <google/protobuf/io/printer.h>
|
|
||||||
#include <google/protobuf/wire_format.h>
|
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
namespace protobuf {
|
|
||||||
namespace compiler {
|
|
||||||
namespace java {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
|
||||||
// repeat code between this and the other field types.
|
|
||||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
|
||||||
map<string, string>* variables) {
|
|
||||||
(*variables)["name"] =
|
|
||||||
UnderscoresToCamelCase(descriptor);
|
|
||||||
(*variables)["capitalized_name"] =
|
|
||||||
UnderscoresToCapitalizedCamelCase(descriptor);
|
|
||||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
|
||||||
(*variables)["type"] = ClassName(descriptor->enum_type());
|
|
||||||
(*variables)["default"] = DefaultValue(descriptor);
|
|
||||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
|
||||||
(*variables)["tag_size"] = SimpleItoa(
|
|
||||||
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
EnumFieldGenerator::
|
|
||||||
EnumFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetEnumVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
EnumFieldGenerator::~EnumFieldGenerator() {}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private boolean has$capitalized_name$;\n"
|
|
||||||
"private $type$ $name$_;\n"
|
|
||||||
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
|
|
||||||
"public $type$ get$capitalized_name$() { return $name$_; }\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"public boolean has$capitalized_name$() {\n"
|
|
||||||
" return result.has$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$() {\n"
|
|
||||||
" return result.get$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$($type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.has$capitalized_name$ = true;\n"
|
|
||||||
" result.$name$_ = value;\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.has$capitalized_name$ = false;\n"
|
|
||||||
" result.$name$_ = $default$;\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (other.has$capitalized_name$()) {\n"
|
|
||||||
" set$capitalized_name$(other.get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
// Nothing to do here for enum types.
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"int rawValue = input.readEnum();\n"
|
|
||||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
|
||||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (value == null) {\n"
|
|
||||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
|
||||||
"} else {\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (value != null) {\n");
|
|
||||||
}
|
|
||||||
printer->Print(variables_,
|
|
||||||
" set$capitalized_name$(value);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" output.writeEnum($number$, get$capitalized_name$().getNumber());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .computeEnumSize($number$, get$capitalized_name$().getNumber());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string EnumFieldGenerator::GetBoxedType() const {
|
|
||||||
return ClassName(descriptor_->enum_type());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
RepeatedEnumFieldGenerator::
|
|
||||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetEnumVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private java.util.List<$type$> $name$_ =\n"
|
|
||||||
" java.util.Collections.emptyList();\n"
|
|
||||||
"public java.util.List<$type$> get$capitalized_name$List() {\n"
|
|
||||||
" return $name$_;\n" // note: unmodifiable list
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() { return $name$_.size(); }\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return $name$_.get(index);\n"
|
|
||||||
"}\n");
|
|
||||||
|
|
||||||
if (descriptor_->options().packed() &&
|
|
||||||
HasGeneratedMethods(descriptor_->containing_type())) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private int $name$MemoizedSerializedSize;\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
// Note: We return an unmodifiable list because otherwise the caller
|
|
||||||
// could hold on to the returned list and modify it after the message
|
|
||||||
// has been built, thus mutating the message which is supposed to be
|
|
||||||
// immutable.
|
|
||||||
"public java.util.List<$type$> get$capitalized_name$List() {\n"
|
|
||||||
" return java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() {\n"
|
|
||||||
" return result.get$capitalized_name$Count();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return result.get$capitalized_name$(index);\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.set(index, value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder add$capitalized_name$($type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.add(value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder addAll$capitalized_name$(\n"
|
|
||||||
" java.lang.Iterable<? extends $type$> values) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" super.addAll(values, result.$name$_);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.$name$_ = java.util.Collections.emptyList();\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
// Initialized inline.
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (!other.$name$_.isEmpty()) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.addAll(other.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
|
|
||||||
" result.$name$_ =\n"
|
|
||||||
" java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
// Read and store the enum
|
|
||||||
printer->Print(variables_,
|
|
||||||
"int rawValue = input.readEnum();\n"
|
|
||||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
|
||||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (value == null) {\n"
|
|
||||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
|
||||||
"} else {\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (value != null) {\n");
|
|
||||||
}
|
|
||||||
printer->Print(variables_,
|
|
||||||
" add$capitalized_name$(value);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
|
||||||
// Wrap GenerateParsingCode's contents with a while loop.
|
|
||||||
|
|
||||||
printer->Print(variables_,
|
|
||||||
"int length = input.readRawVarint32();\n"
|
|
||||||
"int oldLimit = input.pushLimit(length);\n"
|
|
||||||
"while(input.getBytesUntilLimit() > 0) {\n");
|
|
||||||
printer->Indent();
|
|
||||||
|
|
||||||
GenerateParsingCode(printer);
|
|
||||||
|
|
||||||
printer->Outdent();
|
|
||||||
printer->Print(variables_,
|
|
||||||
"}\n"
|
|
||||||
"input.popLimit(oldLimit);\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (get$capitalized_name$List().size() > 0) {\n"
|
|
||||||
" output.writeRawVarint32($tag$);\n"
|
|
||||||
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
|
||||||
"}\n"
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" output.writeEnumNoTag(element.getNumber());\n"
|
|
||||||
"}\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" output.writeEnum($number$, element.getNumber());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedEnumFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"{\n"
|
|
||||||
" int dataSize = 0;\n");
|
|
||||||
printer->Indent();
|
|
||||||
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .computeEnumSizeNoTag(element.getNumber());\n"
|
|
||||||
"}\n");
|
|
||||||
printer->Print(
|
|
||||||
"size += dataSize;\n");
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (!get$capitalized_name$List().isEmpty()) {"
|
|
||||||
" size += $tag_size$;\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .computeRawVarint32Size(dataSize);\n"
|
|
||||||
"}");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"size += $tag_size$ * get$capitalized_name$List().size();\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache the data size for packed fields.
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"$name$MemoizedSerializedSize = dataSize;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Outdent();
|
|
||||||
printer->Print("}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string RepeatedEnumFieldGenerator::GetBoxedType() const {
|
|
||||||
return ClassName(descriptor_->enum_type());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace java
|
|
||||||
} // namespace compiler
|
|
||||||
} // namespace protobuf
|
|
||||||
} // namespace google
|
|
@ -1,335 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// http://code.google.com/p/protobuf/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Author: kenton@google.com (Kenton Varda)
|
|
||||||
// Based on original Protocol Buffers design by
|
|
||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_message_field.h>
|
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
|
||||||
#include <google/protobuf/io/printer.h>
|
|
||||||
#include <google/protobuf/wire_format.h>
|
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
namespace protobuf {
|
|
||||||
namespace compiler {
|
|
||||||
namespace java {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
|
||||||
// repeat code between this and the other field types.
|
|
||||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
|
||||||
map<string, string>* variables) {
|
|
||||||
(*variables)["name"] =
|
|
||||||
UnderscoresToCamelCase(descriptor);
|
|
||||||
(*variables)["capitalized_name"] =
|
|
||||||
UnderscoresToCapitalizedCamelCase(descriptor);
|
|
||||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
|
||||||
(*variables)["type"] = ClassName(descriptor->message_type());
|
|
||||||
(*variables)["group_or_message"] =
|
|
||||||
(GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
|
|
||||||
"Group" : "Message";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
MessageFieldGenerator::
|
|
||||||
MessageFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetMessageVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageFieldGenerator::~MessageFieldGenerator() {}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private boolean has$capitalized_name$;\n"
|
|
||||||
"private $type$ $name$_;\n"
|
|
||||||
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
|
|
||||||
"public $type$ get$capitalized_name$() { return $name$_; }\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"public boolean has$capitalized_name$() {\n"
|
|
||||||
" return result.has$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$() {\n"
|
|
||||||
" return result.get$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$($type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.has$capitalized_name$ = true;\n"
|
|
||||||
" result.$name$_ = value;\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$($type$.Builder builderForValue) {\n"
|
|
||||||
" result.has$capitalized_name$ = true;\n"
|
|
||||||
" result.$name$_ = builderForValue.build();\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder merge$capitalized_name$($type$ value) {\n"
|
|
||||||
" if (result.has$capitalized_name$() &&\n"
|
|
||||||
" result.$name$_ != $type$.getDefaultInstance()) {\n"
|
|
||||||
" result.$name$_ =\n"
|
|
||||||
" $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n"
|
|
||||||
" } else {\n"
|
|
||||||
" result.$name$_ = value;\n"
|
|
||||||
" }\n"
|
|
||||||
" result.has$capitalized_name$ = true;\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.has$capitalized_name$ = false;\n"
|
|
||||||
" result.$name$_ = $type$.getDefaultInstance();\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (other.has$capitalized_name$()) {\n"
|
|
||||||
" merge$capitalized_name$(other.get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
// Nothing to do for singular fields.
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"$type$.Builder subBuilder = $type$.newBuilder();\n"
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" subBuilder.mergeFrom(get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
|
|
||||||
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"input.readMessage(subBuilder, extensionRegistry);\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Print(variables_,
|
|
||||||
"set$capitalized_name$(subBuilder.buildPartial());\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" output.write$group_or_message$($number$, get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string MessageFieldGenerator::GetBoxedType() const {
|
|
||||||
return ClassName(descriptor_->message_type());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
RepeatedMessageFieldGenerator::
|
|
||||||
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetMessageVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private java.util.List<$type$> $name$_ =\n"
|
|
||||||
" java.util.Collections.emptyList();\n"
|
|
||||||
"public java.util.List<$type$> get$capitalized_name$List() {\n"
|
|
||||||
" return $name$_;\n" // note: unmodifiable list
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() { return $name$_.size(); }\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return $name$_.get(index);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
// Note: We return an unmodifiable list because otherwise the caller
|
|
||||||
// could hold on to the returned list and modify it after the message
|
|
||||||
// has been built, thus mutating the message which is supposed to be
|
|
||||||
// immutable.
|
|
||||||
"public java.util.List<$type$> get$capitalized_name$List() {\n"
|
|
||||||
" return java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() {\n"
|
|
||||||
" return result.get$capitalized_name$Count();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return result.get$capitalized_name$(index);\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.set(index, value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$(int index, "
|
|
||||||
"$type$.Builder builderForValue) {\n"
|
|
||||||
" result.$name$_.set(index, builderForValue.build());\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder add$capitalized_name$($type$ value) {\n"
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.add(value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder add$capitalized_name$($type$.Builder builderForValue) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.add(builderForValue.build());\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder addAll$capitalized_name$(\n"
|
|
||||||
" java.lang.Iterable<? extends $type$> values) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" super.addAll(values, result.$name$_);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.$name$_ = java.util.Collections.emptyList();\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
// Initialized inline.
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (!other.$name$_.isEmpty()) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.addAll(other.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
|
|
||||||
" result.$name$_ =\n"
|
|
||||||
" java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"$type$.Builder subBuilder = $type$.newBuilder();\n");
|
|
||||||
|
|
||||||
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"input.readMessage(subBuilder, extensionRegistry);\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Print(variables_,
|
|
||||||
"add$capitalized_name$(subBuilder.buildPartial());\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" output.write$group_or_message$($number$, element);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedMessageFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .compute$group_or_message$Size($number$, element);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string RepeatedMessageFieldGenerator::GetBoxedType() const {
|
|
||||||
return ClassName(descriptor_->message_type());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace java
|
|
||||||
} // namespace compiler
|
|
||||||
} // namespace protobuf
|
|
||||||
} // namespace google
|
|
@ -1,465 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// http://code.google.com/p/protobuf/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Author: kenton@google.com (Kenton Varda)
|
|
||||||
// Based on original Protocol Buffers design by
|
|
||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_primitive_field.h>
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
|
||||||
#include <google/protobuf/io/printer.h>
|
|
||||||
#include <google/protobuf/wire_format.h>
|
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
|
||||||
|
|
||||||
namespace google {
|
|
||||||
namespace protobuf {
|
|
||||||
namespace compiler {
|
|
||||||
namespace java {
|
|
||||||
|
|
||||||
using internal::WireFormat;
|
|
||||||
using internal::WireFormatLite;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const char* PrimitiveTypeName(JavaType type) {
|
|
||||||
switch (type) {
|
|
||||||
case JAVATYPE_INT : return "int";
|
|
||||||
case JAVATYPE_LONG : return "long";
|
|
||||||
case JAVATYPE_FLOAT : return "float";
|
|
||||||
case JAVATYPE_DOUBLE : return "double";
|
|
||||||
case JAVATYPE_BOOLEAN: return "boolean";
|
|
||||||
case JAVATYPE_STRING : return "java.lang.String";
|
|
||||||
case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
|
|
||||||
case JAVATYPE_ENUM : return NULL;
|
|
||||||
case JAVATYPE_MESSAGE: return NULL;
|
|
||||||
|
|
||||||
// No default because we want the compiler to complain if any new
|
|
||||||
// JavaTypes are added.
|
|
||||||
}
|
|
||||||
|
|
||||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsReferenceType(JavaType type) {
|
|
||||||
switch (type) {
|
|
||||||
case JAVATYPE_INT : return false;
|
|
||||||
case JAVATYPE_LONG : return false;
|
|
||||||
case JAVATYPE_FLOAT : return false;
|
|
||||||
case JAVATYPE_DOUBLE : return false;
|
|
||||||
case JAVATYPE_BOOLEAN: return false;
|
|
||||||
case JAVATYPE_STRING : return true;
|
|
||||||
case JAVATYPE_BYTES : return true;
|
|
||||||
case JAVATYPE_ENUM : return true;
|
|
||||||
case JAVATYPE_MESSAGE: return true;
|
|
||||||
|
|
||||||
// No default because we want the compiler to complain if any new
|
|
||||||
// JavaTypes are added.
|
|
||||||
}
|
|
||||||
|
|
||||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GetCapitalizedType(const FieldDescriptor* field) {
|
|
||||||
switch (GetType(field)) {
|
|
||||||
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
|
|
||||||
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
|
|
||||||
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
|
|
||||||
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
|
|
||||||
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
|
|
||||||
case FieldDescriptor::TYPE_INT64 : return "Int64" ;
|
|
||||||
case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
|
|
||||||
case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
|
|
||||||
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
|
|
||||||
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
|
|
||||||
case FieldDescriptor::TYPE_FLOAT : return "Float" ;
|
|
||||||
case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
|
|
||||||
case FieldDescriptor::TYPE_BOOL : return "Bool" ;
|
|
||||||
case FieldDescriptor::TYPE_STRING : return "String" ;
|
|
||||||
case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
|
|
||||||
case FieldDescriptor::TYPE_ENUM : return "Enum" ;
|
|
||||||
case FieldDescriptor::TYPE_GROUP : return "Group" ;
|
|
||||||
case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
|
|
||||||
|
|
||||||
// No default because we want the compiler to complain if any new
|
|
||||||
// types are added.
|
|
||||||
}
|
|
||||||
|
|
||||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
|
||||||
// returns -1.
|
|
||||||
int FixedSize(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 WireFormatLite::kFixed32Size;
|
|
||||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
|
||||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
|
||||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
|
||||||
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
|
||||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
|
||||||
|
|
||||||
case FieldDescriptor::TYPE_BOOL : return 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
|
||||||
map<string, string>* variables) {
|
|
||||||
(*variables)["name"] =
|
|
||||||
UnderscoresToCamelCase(descriptor);
|
|
||||||
(*variables)["capitalized_name"] =
|
|
||||||
UnderscoresToCapitalizedCamelCase(descriptor);
|
|
||||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
|
||||||
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
|
|
||||||
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
|
|
||||||
(*variables)["default"] = DefaultValue(descriptor);
|
|
||||||
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
|
|
||||||
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
|
|
||||||
(*variables)["tag_size"] = SimpleItoa(
|
|
||||||
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
|
||||||
if (IsReferenceType(GetJavaType(descriptor))) {
|
|
||||||
(*variables)["null_check"] =
|
|
||||||
" if (value == null) {\n"
|
|
||||||
" throw new NullPointerException();\n"
|
|
||||||
" }\n";
|
|
||||||
} else {
|
|
||||||
(*variables)["null_check"] = "";
|
|
||||||
}
|
|
||||||
int fixed_size = FixedSize(GetType(descriptor));
|
|
||||||
if (fixed_size != -1) {
|
|
||||||
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
PrimitiveFieldGenerator::
|
|
||||||
PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetPrimitiveVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private boolean has$capitalized_name$;\n"
|
|
||||||
"private $type$ $name$_ = $default$;\n"
|
|
||||||
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
|
|
||||||
"public $type$ get$capitalized_name$() { return $name$_; }\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"public boolean has$capitalized_name$() {\n"
|
|
||||||
" return result.has$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$() {\n"
|
|
||||||
" return result.get$capitalized_name$();\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$($type$ value) {\n"
|
|
||||||
"$null_check$"
|
|
||||||
" result.has$capitalized_name$ = true;\n"
|
|
||||||
" result.$name$_ = value;\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.has$capitalized_name$ = false;\n");
|
|
||||||
JavaType type = GetJavaType(descriptor_);
|
|
||||||
if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
|
|
||||||
// The default value is not a simple literal so we want to avoid executing
|
|
||||||
// it multiple times. Instead, get the default out of the default instance.
|
|
||||||
printer->Print(variables_,
|
|
||||||
" result.$name$_ = getDefaultInstance().get$capitalized_name$();\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
" result.$name$_ = $default$;\n");
|
|
||||||
}
|
|
||||||
printer->Print(variables_,
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
// Initialized inline.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (other.has$capitalized_name$()) {\n"
|
|
||||||
" set$capitalized_name$(other.get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
// Nothing to do here for primitive types.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"set$capitalized_name$(input.read$capitalized_type$());\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" output.write$capitalized_type$($number$, get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (has$capitalized_name$()) {\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .compute$capitalized_type$Size($number$, get$capitalized_name$());\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string PrimitiveFieldGenerator::GetBoxedType() const {
|
|
||||||
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
RepeatedPrimitiveFieldGenerator::
|
|
||||||
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
|
||||||
: descriptor_(descriptor) {
|
|
||||||
SetPrimitiveVariables(descriptor, &variables_);
|
|
||||||
}
|
|
||||||
|
|
||||||
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private java.util.List<$boxed_type$> $name$_ =\n"
|
|
||||||
" java.util.Collections.emptyList();\n"
|
|
||||||
"public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
|
|
||||||
" return $name$_;\n" // note: unmodifiable list
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() { return $name$_.size(); }\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return $name$_.get(index);\n"
|
|
||||||
"}\n");
|
|
||||||
|
|
||||||
if (descriptor_->options().packed() &&
|
|
||||||
HasGeneratedMethods(descriptor_->containing_type())) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"private int $name$MemoizedSerializedSize = -1;\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateBuilderMembers(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
// Note: We return an unmodifiable list because otherwise the caller
|
|
||||||
// could hold on to the returned list and modify it after the message
|
|
||||||
// has been built, thus mutating the message which is supposed to be
|
|
||||||
// immutable.
|
|
||||||
"public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
|
|
||||||
" return java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n"
|
|
||||||
"public int get$capitalized_name$Count() {\n"
|
|
||||||
" return result.get$capitalized_name$Count();\n"
|
|
||||||
"}\n"
|
|
||||||
"public $type$ get$capitalized_name$(int index) {\n"
|
|
||||||
" return result.get$capitalized_name$(index);\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder set$capitalized_name$(int index, $type$ value) {\n"
|
|
||||||
"$null_check$"
|
|
||||||
" result.$name$_.set(index, value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder add$capitalized_name$($type$ value) {\n"
|
|
||||||
"$null_check$"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.add(value);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder addAll$capitalized_name$(\n"
|
|
||||||
" java.lang.Iterable<? extends $boxed_type$> values) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" super.addAll(values, result.$name$_);\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n"
|
|
||||||
"public Builder clear$capitalized_name$() {\n"
|
|
||||||
" result.$name$_ = java.util.Collections.emptyList();\n"
|
|
||||||
" return this;\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateInitializationCode(io::Printer* printer) const {
|
|
||||||
// Initialized inline.
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateMergingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (!other.$name$_.isEmpty()) {\n"
|
|
||||||
" if (result.$name$_.isEmpty()) {\n"
|
|
||||||
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
|
|
||||||
" }\n"
|
|
||||||
" result.$name$_.addAll(other.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateBuildingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
|
|
||||||
" result.$name$_ =\n"
|
|
||||||
" java.util.Collections.unmodifiableList(result.$name$_);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateParsingCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"add$capitalized_name$(input.read$capitalized_type$());\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"int length = input.readRawVarint32();\n"
|
|
||||||
"int limit = input.pushLimit(length);\n"
|
|
||||||
"while (input.getBytesUntilLimit() > 0) {\n"
|
|
||||||
" add$capitalized_name$(input.read$capitalized_type$());\n"
|
|
||||||
"}\n"
|
|
||||||
"input.popLimit(limit);\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateSerializationCode(io::Printer* printer) const {
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (get$capitalized_name$List().size() > 0) {\n"
|
|
||||||
" output.writeRawVarint32($tag$);\n"
|
|
||||||
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
|
||||||
"}\n"
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" output.write$capitalized_type$NoTag(element);\n"
|
|
||||||
"}\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" output.write$capitalized_type$($number$, element);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepeatedPrimitiveFieldGenerator::
|
|
||||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"{\n"
|
|
||||||
" int dataSize = 0;\n");
|
|
||||||
printer->Indent();
|
|
||||||
|
|
||||||
if (FixedSize(GetType(descriptor_)) == -1) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"for ($type$ element : get$capitalized_name$List()) {\n"
|
|
||||||
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .compute$capitalized_type$SizeNoTag(element);\n"
|
|
||||||
"}\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Print(
|
|
||||||
"size += dataSize;\n");
|
|
||||||
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"if (!get$capitalized_name$List().isEmpty()) {\n"
|
|
||||||
" size += $tag_size$;\n"
|
|
||||||
" size += com.google.protobuf.CodedOutputStream\n"
|
|
||||||
" .computeInt32SizeNoTag(dataSize);\n"
|
|
||||||
"}\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"size += $tag_size$ * get$capitalized_name$List().size();\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache the data size for packed fields.
|
|
||||||
if (descriptor_->options().packed()) {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"$name$MemoizedSerializedSize = dataSize;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Outdent();
|
|
||||||
printer->Print("}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
|
|
||||||
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace java
|
|
||||||
} // namespace compiler
|
|
||||||
} // namespace protobuf
|
|
||||||
} // namespace google
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -37,54 +37,70 @@ CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
|
|||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
Makefile.in
|
Makefile.in
|
||||||
|
|
||||||
nobase_include_HEADERS = \
|
nobase_include_HEADERS = \
|
||||||
google/protobuf/stubs/common.h \
|
google/protobuf/stubs/atomicops.h \
|
||||||
google/protobuf/stubs/once.h \
|
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
|
||||||
google/protobuf/descriptor.h \
|
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
|
||||||
google/protobuf/descriptor.pb.h \
|
google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
|
||||||
google/protobuf/descriptor_database.h \
|
google/protobuf/stubs/atomicops_internals_macosx.h \
|
||||||
google/protobuf/dynamic_message.h \
|
google/protobuf/stubs/atomicops_internals_mips_gcc.h \
|
||||||
google/protobuf/extension_set.h \
|
google/protobuf/stubs/atomicops_internals_pnacl.h \
|
||||||
google/protobuf/generated_message_util.h \
|
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
|
||||||
google/protobuf/generated_message_reflection.h \
|
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
|
||||||
google/protobuf/message.h \
|
google/protobuf/stubs/common.h \
|
||||||
google/protobuf/message_lite.h \
|
google/protobuf/stubs/platform_macros.h \
|
||||||
google/protobuf/reflection_ops.h \
|
google/protobuf/stubs/once.h \
|
||||||
google/protobuf/repeated_field.h \
|
google/protobuf/stubs/template_util.h \
|
||||||
google/protobuf/service.h \
|
google/protobuf/stubs/type_traits.h \
|
||||||
google/protobuf/text_format.h \
|
google/protobuf/descriptor.h \
|
||||||
google/protobuf/unknown_field_set.h \
|
google/protobuf/descriptor.pb.h \
|
||||||
google/protobuf/wire_format.h \
|
google/protobuf/descriptor_database.h \
|
||||||
google/protobuf/wire_format_lite.h \
|
google/protobuf/dynamic_message.h \
|
||||||
google/protobuf/wire_format_lite_inl.h \
|
google/protobuf/extension_set.h \
|
||||||
google/protobuf/io/coded_stream.h \
|
google/protobuf/generated_enum_reflection.h \
|
||||||
$(GZHEADERS) \
|
google/protobuf/generated_message_util.h \
|
||||||
google/protobuf/io/printer.h \
|
google/protobuf/generated_message_reflection.h \
|
||||||
google/protobuf/io/tokenizer.h \
|
google/protobuf/message.h \
|
||||||
google/protobuf/io/zero_copy_stream.h \
|
google/protobuf/message_lite.h \
|
||||||
google/protobuf/io/zero_copy_stream_impl.h \
|
google/protobuf/reflection_ops.h \
|
||||||
google/protobuf/io/zero_copy_stream_impl_lite.h \
|
google/protobuf/repeated_field.h \
|
||||||
google/protobuf/compiler/code_generator.h \
|
google/protobuf/service.h \
|
||||||
google/protobuf/compiler/command_line_interface.h \
|
google/protobuf/text_format.h \
|
||||||
google/protobuf/compiler/importer.h \
|
google/protobuf/unknown_field_set.h \
|
||||||
google/protobuf/compiler/parser.h \
|
google/protobuf/wire_format.h \
|
||||||
google/protobuf/compiler/plugin.h \
|
google/protobuf/wire_format_lite.h \
|
||||||
google/protobuf/compiler/plugin.pb.h \
|
google/protobuf/wire_format_lite_inl.h \
|
||||||
google/protobuf/compiler/cpp/cpp_generator.h \
|
google/protobuf/io/coded_stream.h \
|
||||||
google/protobuf/compiler/java/java_generator.h \
|
$(GZHEADERS) \
|
||||||
|
google/protobuf/io/printer.h \
|
||||||
|
google/protobuf/io/tokenizer.h \
|
||||||
|
google/protobuf/io/zero_copy_stream.h \
|
||||||
|
google/protobuf/io/zero_copy_stream_impl.h \
|
||||||
|
google/protobuf/io/zero_copy_stream_impl_lite.h \
|
||||||
|
google/protobuf/compiler/code_generator.h \
|
||||||
|
google/protobuf/compiler/command_line_interface.h \
|
||||||
|
google/protobuf/compiler/importer.h \
|
||||||
|
google/protobuf/compiler/parser.h \
|
||||||
|
google/protobuf/compiler/plugin.h \
|
||||||
|
google/protobuf/compiler/plugin.pb.h \
|
||||||
|
google/protobuf/compiler/cpp/cpp_generator.h \
|
||||||
|
google/protobuf/compiler/java/java_generator.h \
|
||||||
google/protobuf/compiler/python/python_generator.h
|
google/protobuf/compiler/python/python_generator.h
|
||||||
|
|
||||||
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
|
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
|
||||||
|
|
||||||
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
|
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
|
||||||
libprotobuf_lite_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined
|
libprotobuf_lite_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||||
libprotobuf_lite_la_SOURCES = \
|
libprotobuf_lite_la_SOURCES = \
|
||||||
|
google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
|
||||||
|
google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
|
||||||
google/protobuf/stubs/common.cc \
|
google/protobuf/stubs/common.cc \
|
||||||
google/protobuf/stubs/once.cc \
|
google/protobuf/stubs/once.cc \
|
||||||
google/protobuf/stubs/hash.cc \
|
|
||||||
google/protobuf/stubs/hash.h \
|
google/protobuf/stubs/hash.h \
|
||||||
google/protobuf/stubs/map-util.h \
|
google/protobuf/stubs/map-util.h \
|
||||||
google/protobuf/stubs/stl_util-inl.h \
|
google/protobuf/stubs/stl_util.h \
|
||||||
|
google/protobuf/stubs/stringprintf.cc \
|
||||||
|
google/protobuf/stubs/stringprintf.h \
|
||||||
google/protobuf/extension_set.cc \
|
google/protobuf/extension_set.cc \
|
||||||
google/protobuf/generated_message_util.cc \
|
google/protobuf/generated_message_util.cc \
|
||||||
google/protobuf/message_lite.cc \
|
google/protobuf/message_lite.cc \
|
||||||
@ -96,7 +112,7 @@ libprotobuf_lite_la_SOURCES = \
|
|||||||
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||||
|
|
||||||
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
|
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
|
||||||
libprotobuf_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined
|
libprotobuf_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||||
libprotobuf_la_SOURCES = \
|
libprotobuf_la_SOURCES = \
|
||||||
$(libprotobuf_lite_la_SOURCES) \
|
$(libprotobuf_lite_la_SOURCES) \
|
||||||
google/protobuf/stubs/strutil.cc \
|
google/protobuf/stubs/strutil.cc \
|
||||||
@ -124,7 +140,7 @@ libprotobuf_la_SOURCES = \
|
|||||||
google/protobuf/compiler/parser.cc
|
google/protobuf/compiler/parser.cc
|
||||||
|
|
||||||
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
|
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||||
libprotoc_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined
|
libprotoc_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||||
libprotoc_la_SOURCES = \
|
libprotoc_la_SOURCES = \
|
||||||
google/protobuf/compiler/code_generator.cc \
|
google/protobuf/compiler/code_generator.cc \
|
||||||
google/protobuf/compiler/command_line_interface.cc \
|
google/protobuf/compiler/command_line_interface.cc \
|
||||||
@ -151,6 +167,7 @@ libprotoc_la_SOURCES = \
|
|||||||
google/protobuf/compiler/cpp/cpp_message.h \
|
google/protobuf/compiler/cpp/cpp_message.h \
|
||||||
google/protobuf/compiler/cpp/cpp_message_field.cc \
|
google/protobuf/compiler/cpp/cpp_message_field.cc \
|
||||||
google/protobuf/compiler/cpp/cpp_message_field.h \
|
google/protobuf/compiler/cpp/cpp_message_field.h \
|
||||||
|
google/protobuf/compiler/cpp/cpp_options.h \
|
||||||
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
|
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
|
||||||
google/protobuf/compiler/cpp/cpp_primitive_field.h \
|
google/protobuf/compiler/cpp/cpp_primitive_field.h \
|
||||||
google/protobuf/compiler/cpp/cpp_service.cc \
|
google/protobuf/compiler/cpp/cpp_service.cc \
|
||||||
@ -178,6 +195,10 @@ libprotoc_la_SOURCES = \
|
|||||||
google/protobuf/compiler/java/java_primitive_field.h \
|
google/protobuf/compiler/java/java_primitive_field.h \
|
||||||
google/protobuf/compiler/java/java_service.cc \
|
google/protobuf/compiler/java/java_service.cc \
|
||||||
google/protobuf/compiler/java/java_service.h \
|
google/protobuf/compiler/java/java_service.h \
|
||||||
|
google/protobuf/compiler/java/java_string_field.cc \
|
||||||
|
google/protobuf/compiler/java/java_string_field.h \
|
||||||
|
google/protobuf/compiler/java/java_doc_comment.cc \
|
||||||
|
google/protobuf/compiler/java/java_doc_comment.h \
|
||||||
google/protobuf/compiler/python/python_generator.cc
|
google/protobuf/compiler/python/python_generator.cc
|
||||||
|
|
||||||
bin_PROGRAMS = protoc
|
bin_PROGRAMS = protoc
|
||||||
@ -190,12 +211,14 @@ protoc_inputs = \
|
|||||||
google/protobuf/unittest.proto \
|
google/protobuf/unittest.proto \
|
||||||
google/protobuf/unittest_empty.proto \
|
google/protobuf/unittest_empty.proto \
|
||||||
google/protobuf/unittest_import.proto \
|
google/protobuf/unittest_import.proto \
|
||||||
|
google/protobuf/unittest_import_public.proto \
|
||||||
google/protobuf/unittest_mset.proto \
|
google/protobuf/unittest_mset.proto \
|
||||||
google/protobuf/unittest_optimize_for.proto \
|
google/protobuf/unittest_optimize_for.proto \
|
||||||
google/protobuf/unittest_embed_optimize_for.proto \
|
google/protobuf/unittest_embed_optimize_for.proto \
|
||||||
google/protobuf/unittest_custom_options.proto \
|
google/protobuf/unittest_custom_options.proto \
|
||||||
google/protobuf/unittest_lite.proto \
|
google/protobuf/unittest_lite.proto \
|
||||||
google/protobuf/unittest_import_lite.proto \
|
google/protobuf/unittest_import_lite.proto \
|
||||||
|
google/protobuf/unittest_import_public_lite.proto \
|
||||||
google/protobuf/unittest_lite_imports_nonlite.proto \
|
google/protobuf/unittest_lite_imports_nonlite.proto \
|
||||||
google/protobuf/unittest_no_generic_services.proto \
|
google/protobuf/unittest_no_generic_services.proto \
|
||||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
|
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
|
||||||
@ -219,7 +242,9 @@ protoc_lite_outputs = \
|
|||||||
google/protobuf/unittest_lite.pb.cc \
|
google/protobuf/unittest_lite.pb.cc \
|
||||||
google/protobuf/unittest_lite.pb.h \
|
google/protobuf/unittest_lite.pb.h \
|
||||||
google/protobuf/unittest_import_lite.pb.cc \
|
google/protobuf/unittest_import_lite.pb.cc \
|
||||||
google/protobuf/unittest_import_lite.pb.h
|
google/protobuf/unittest_import_lite.pb.h \
|
||||||
|
google/protobuf/unittest_import_public_lite.pb.cc \
|
||||||
|
google/protobuf/unittest_import_public_lite.pb.h
|
||||||
|
|
||||||
protoc_outputs = \
|
protoc_outputs = \
|
||||||
$(protoc_lite_outputs) \
|
$(protoc_lite_outputs) \
|
||||||
@ -229,6 +254,8 @@ protoc_outputs = \
|
|||||||
google/protobuf/unittest_empty.pb.h \
|
google/protobuf/unittest_empty.pb.h \
|
||||||
google/protobuf/unittest_import.pb.cc \
|
google/protobuf/unittest_import.pb.cc \
|
||||||
google/protobuf/unittest_import.pb.h \
|
google/protobuf/unittest_import.pb.h \
|
||||||
|
google/protobuf/unittest_import_public.pb.cc \
|
||||||
|
google/protobuf/unittest_import_public.pb.h \
|
||||||
google/protobuf/unittest_mset.pb.cc \
|
google/protobuf/unittest_mset.pb.cc \
|
||||||
google/protobuf/unittest_mset.pb.h \
|
google/protobuf/unittest_mset.pb.h \
|
||||||
google/protobuf/unittest_optimize_for.pb.cc \
|
google/protobuf/unittest_optimize_for.pb.cc \
|
||||||
@ -289,6 +316,9 @@ protobuf_test_SOURCES = \
|
|||||||
google/protobuf/stubs/once_unittest.cc \
|
google/protobuf/stubs/once_unittest.cc \
|
||||||
google/protobuf/stubs/strutil_unittest.cc \
|
google/protobuf/stubs/strutil_unittest.cc \
|
||||||
google/protobuf/stubs/structurally_valid_unittest.cc \
|
google/protobuf/stubs/structurally_valid_unittest.cc \
|
||||||
|
google/protobuf/stubs/stringprintf_unittest.cc \
|
||||||
|
google/protobuf/stubs/template_util_unittest.cc \
|
||||||
|
google/protobuf/stubs/type_traits_unittest.cc \
|
||||||
google/protobuf/descriptor_database_unittest.cc \
|
google/protobuf/descriptor_database_unittest.cc \
|
||||||
google/protobuf/descriptor_unittest.cc \
|
google/protobuf/descriptor_unittest.cc \
|
||||||
google/protobuf/dynamic_message_unittest.cc \
|
google/protobuf/dynamic_message_unittest.cc \
|
||||||
@ -297,6 +327,7 @@ protobuf_test_SOURCES = \
|
|||||||
google/protobuf/message_unittest.cc \
|
google/protobuf/message_unittest.cc \
|
||||||
google/protobuf/reflection_ops_unittest.cc \
|
google/protobuf/reflection_ops_unittest.cc \
|
||||||
google/protobuf/repeated_field_unittest.cc \
|
google/protobuf/repeated_field_unittest.cc \
|
||||||
|
google/protobuf/repeated_field_reflection_unittest.cc \
|
||||||
google/protobuf/text_format_unittest.cc \
|
google/protobuf/text_format_unittest.cc \
|
||||||
google/protobuf/unknown_field_set_unittest.cc \
|
google/protobuf/unknown_field_set_unittest.cc \
|
||||||
google/protobuf/wire_format_unittest.cc \
|
google/protobuf/wire_format_unittest.cc \
|
||||||
@ -310,9 +341,11 @@ protobuf_test_SOURCES = \
|
|||||||
google/protobuf/compiler/mock_code_generator.h \
|
google/protobuf/compiler/mock_code_generator.h \
|
||||||
google/protobuf/compiler/parser_unittest.cc \
|
google/protobuf/compiler/parser_unittest.cc \
|
||||||
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
|
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
|
||||||
|
google/protobuf/compiler/cpp/cpp_unittest.h \
|
||||||
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
||||||
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
|
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
|
||||||
google/protobuf/compiler/java/java_plugin_unittest.cc \
|
google/protobuf/compiler/java/java_plugin_unittest.cc \
|
||||||
|
google/protobuf/compiler/java/java_doc_comment_unittest.cc \
|
||||||
google/protobuf/compiler/python/python_plugin_unittest.cc \
|
google/protobuf/compiler/python/python_plugin_unittest.cc \
|
||||||
$(COMMON_TEST_SOURCES)
|
$(COMMON_TEST_SOURCES)
|
||||||
nodist_protobuf_test_SOURCES = $(protoc_outputs)
|
nodist_protobuf_test_SOURCES = $(protoc_outputs)
|
File diff suppressed because it is too large
Load Diff
@ -42,14 +42,19 @@ namespace protobuf {
|
|||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
CodeGenerator::~CodeGenerator() {}
|
CodeGenerator::~CodeGenerator() {}
|
||||||
OutputDirectory::~OutputDirectory() {}
|
GeneratorContext::~GeneratorContext() {}
|
||||||
|
|
||||||
io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert(
|
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
|
||||||
const string& filename, const string& insertion_point) {
|
const string& filename, const string& insertion_point) {
|
||||||
GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion.";
|
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
|
||||||
return NULL; // make compiler happy
|
return NULL; // make compiler happy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeneratorContext::ListParsedFiles(
|
||||||
|
vector<const FileDescriptor*>* output) {
|
||||||
|
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
|
||||||
|
}
|
||||||
|
|
||||||
// Parses a set of comma-delimited name/value pairs.
|
// Parses a set of comma-delimited name/value pairs.
|
||||||
void ParseGeneratorParameter(const string& text,
|
void ParseGeneratorParameter(const string& text,
|
||||||
vector<pair<string, string> >* output) {
|
vector<pair<string, string> >* output) {
|
@ -53,7 +53,7 @@ namespace compiler {
|
|||||||
|
|
||||||
// Defined in this file.
|
// Defined in this file.
|
||||||
class CodeGenerator;
|
class CodeGenerator;
|
||||||
class OutputDirectory;
|
class GeneratorContext;
|
||||||
|
|
||||||
// The abstract interface to a class which generates code implementing a
|
// The abstract interface to a class which generates code implementing a
|
||||||
// particular proto file in a particular language. A number of these may
|
// particular proto file in a particular language. A number of these may
|
||||||
@ -76,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGenerator {
|
|||||||
// the problem (e.g. "invalid parameter") and returns false.
|
// the problem (e.g. "invalid parameter") and returns false.
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error) const = 0;
|
string* error) const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -85,11 +85,12 @@ class LIBPROTOC_EXPORT CodeGenerator {
|
|||||||
|
|
||||||
// CodeGenerators generate one or more files in a given directory. This
|
// CodeGenerators generate one or more files in a given directory. This
|
||||||
// abstract interface represents the directory to which the CodeGenerator is
|
// abstract interface represents the directory to which the CodeGenerator is
|
||||||
// to write.
|
// to write and other information about the context in which the Generator
|
||||||
class LIBPROTOC_EXPORT OutputDirectory {
|
// runs.
|
||||||
|
class LIBPROTOC_EXPORT GeneratorContext {
|
||||||
public:
|
public:
|
||||||
inline OutputDirectory() {}
|
inline GeneratorContext() {}
|
||||||
virtual ~OutputDirectory();
|
virtual ~GeneratorContext();
|
||||||
|
|
||||||
// Opens the given file, truncating it if it exists, and returns a
|
// Opens the given file, truncating it if it exists, and returns a
|
||||||
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
|
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
|
||||||
@ -112,10 +113,19 @@ class LIBPROTOC_EXPORT OutputDirectory {
|
|||||||
virtual io::ZeroCopyOutputStream* OpenForInsert(
|
virtual io::ZeroCopyOutputStream* OpenForInsert(
|
||||||
const string& filename, const string& insertion_point);
|
const string& filename, const string& insertion_point);
|
||||||
|
|
||||||
|
// Returns a vector of FileDescriptors for all the files being compiled
|
||||||
|
// in this run. Useful for languages, such as Go, that treat files
|
||||||
|
// differently when compiled as a set rather than individually.
|
||||||
|
virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The type GeneratorContext was once called OutputDirectory. This typedef
|
||||||
|
// provides backward compatibility.
|
||||||
|
typedef GeneratorContext OutputDirectory;
|
||||||
|
|
||||||
// Several code generators treat the parameter argument as holding a
|
// Several code generators treat the parameter argument as holding a
|
||||||
// list of options separated by commas. This helper function parses
|
// list of options separated by commas. This helper function parses
|
||||||
// a set of comma-delimited name/value pairs: e.g.,
|
// a set of comma-delimited name/value pairs: e.g.,
|
@ -48,6 +48,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/hash.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/compiler/importer.h>
|
#include <google/protobuf/compiler/importer.h>
|
||||||
#include <google/protobuf/compiler/code_generator.h>
|
#include <google/protobuf/compiler/code_generator.h>
|
||||||
#include <google/protobuf/compiler/plugin.pb.h>
|
#include <google/protobuf/compiler/plugin.pb.h>
|
||||||
@ -56,14 +59,13 @@
|
|||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <google/protobuf/text_format.h>
|
#include <google/protobuf/text_format.h>
|
||||||
#include <google/protobuf/dynamic_message.h>
|
#include <google/protobuf/dynamic_message.h>
|
||||||
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
#include <google/protobuf/stubs/map-util.h>
|
#include <google/protobuf/stubs/map-util.h>
|
||||||
#include <google/protobuf/stubs/stl_util-inl.h>
|
#include <google/protobuf/stubs/stl_util.h>
|
||||||
#include <google/protobuf/stubs/hash.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@ -144,7 +146,7 @@ void AddTrailingSlash(string* path) {
|
|||||||
bool VerifyDirectoryExists(const string& path) {
|
bool VerifyDirectoryExists(const string& path) {
|
||||||
if (path.empty()) return true;
|
if (path.empty()) return true;
|
||||||
|
|
||||||
if (access(path.c_str(), W_OK) == -1) {
|
if (access(path.c_str(), F_OK) == -1) {
|
||||||
cerr << path << ": " << strerror(errno) << endl;
|
cerr << path << ": " << strerror(errno) << endl;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -182,14 +184,23 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) {
|
|||||||
class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
|
class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
|
||||||
public io::ErrorCollector {
|
public io::ErrorCollector {
|
||||||
public:
|
public:
|
||||||
ErrorPrinter(ErrorFormat format) : format_(format) {}
|
ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
|
||||||
|
: format_(format), tree_(tree) {}
|
||||||
~ErrorPrinter() {}
|
~ErrorPrinter() {}
|
||||||
|
|
||||||
// implements MultiFileErrorCollector ------------------------------
|
// implements MultiFileErrorCollector ------------------------------
|
||||||
void AddError(const string& filename, int line, int column,
|
void AddError(const string& filename, int line, int column,
|
||||||
const string& message) {
|
const string& message) {
|
||||||
|
|
||||||
cerr << filename;
|
// Print full path when running under MSVS
|
||||||
|
string dfile;
|
||||||
|
if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
|
||||||
|
tree_ != NULL &&
|
||||||
|
tree_->VirtualFileToDiskFile(filename, &dfile)) {
|
||||||
|
cerr << dfile;
|
||||||
|
} else {
|
||||||
|
cerr << filename;
|
||||||
|
}
|
||||||
|
|
||||||
// Users typically expect 1-based line/column numbers, so we add 1
|
// Users typically expect 1-based line/column numbers, so we add 1
|
||||||
// to each here.
|
// to each here.
|
||||||
@ -215,16 +226,17 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const ErrorFormat format_;
|
const ErrorFormat format_;
|
||||||
|
DiskSourceTree *tree_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
// An OutputDirectory implementation that buffers files in memory, then dumps
|
// A GeneratorContext implementation that buffers files in memory, then dumps
|
||||||
// them all to disk on demand.
|
// them all to disk on demand.
|
||||||
class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
|
class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
|
||||||
public:
|
public:
|
||||||
MemoryOutputDirectory();
|
GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
|
||||||
~MemoryOutputDirectory();
|
~GeneratorContextImpl();
|
||||||
|
|
||||||
// Write all files in the directory to disk at the given output location,
|
// Write all files in the directory to disk at the given output location,
|
||||||
// which must end in a '/'.
|
// which must end in a '/'.
|
||||||
@ -238,10 +250,13 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
|
|||||||
// format, unless one has already been written.
|
// format, unless one has already been written.
|
||||||
void AddJarManifest();
|
void AddJarManifest();
|
||||||
|
|
||||||
// implements OutputDirectory --------------------------------------
|
// implements GeneratorContext --------------------------------------
|
||||||
io::ZeroCopyOutputStream* Open(const string& filename);
|
io::ZeroCopyOutputStream* Open(const string& filename);
|
||||||
io::ZeroCopyOutputStream* OpenForInsert(
|
io::ZeroCopyOutputStream* OpenForInsert(
|
||||||
const string& filename, const string& insertion_point);
|
const string& filename, const string& insertion_point);
|
||||||
|
void ListParsedFiles(vector<const FileDescriptor*>* output) {
|
||||||
|
*output = parsed_files_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MemoryOutputStream;
|
friend class MemoryOutputStream;
|
||||||
@ -249,14 +264,15 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
|
|||||||
// map instead of hash_map so that files are written in order (good when
|
// map instead of hash_map so that files are written in order (good when
|
||||||
// writing zips).
|
// writing zips).
|
||||||
map<string, string*> files_;
|
map<string, string*> files_;
|
||||||
|
const vector<const FileDescriptor*>& parsed_files_;
|
||||||
bool had_error_;
|
bool had_error_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandLineInterface::MemoryOutputStream
|
class CommandLineInterface::MemoryOutputStream
|
||||||
: public io::ZeroCopyOutputStream {
|
: public io::ZeroCopyOutputStream {
|
||||||
public:
|
public:
|
||||||
MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename);
|
MemoryOutputStream(GeneratorContextImpl* directory, const string& filename);
|
||||||
MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename,
|
MemoryOutputStream(GeneratorContextImpl* directory, const string& filename,
|
||||||
const string& insertion_point);
|
const string& insertion_point);
|
||||||
virtual ~MemoryOutputStream();
|
virtual ~MemoryOutputStream();
|
||||||
|
|
||||||
@ -267,7 +283,7 @@ class CommandLineInterface::MemoryOutputStream
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Where to insert the string when it's done.
|
// Where to insert the string when it's done.
|
||||||
MemoryOutputDirectory* directory_;
|
GeneratorContextImpl* directory_;
|
||||||
string filename_;
|
string filename_;
|
||||||
string insertion_point_;
|
string insertion_point_;
|
||||||
|
|
||||||
@ -280,14 +296,17 @@ class CommandLineInterface::MemoryOutputStream
|
|||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory()
|
CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
|
||||||
: had_error_(false) {}
|
const vector<const FileDescriptor*>& parsed_files)
|
||||||
|
: parsed_files_(parsed_files),
|
||||||
|
had_error_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() {
|
CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
|
||||||
STLDeleteValues(&files_);
|
STLDeleteValues(&files_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk(
|
bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
|
||||||
const string& prefix) {
|
const string& prefix) {
|
||||||
if (had_error_) {
|
if (had_error_) {
|
||||||
return false;
|
return false;
|
||||||
@ -362,7 +381,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip(
|
bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
|
||||||
const string& filename) {
|
const string& filename) {
|
||||||
if (had_error_) {
|
if (had_error_) {
|
||||||
return false;
|
return false;
|
||||||
@ -403,7 +422,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() {
|
void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
|
||||||
string** map_slot = &files_["META-INF/MANIFEST.MF"];
|
string** map_slot = &files_["META-INF/MANIFEST.MF"];
|
||||||
if (*map_slot == NULL) {
|
if (*map_slot == NULL) {
|
||||||
*map_slot = new string(
|
*map_slot = new string(
|
||||||
@ -413,13 +432,13 @@ void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open(
|
io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
|
||||||
const string& filename) {
|
const string& filename) {
|
||||||
return new MemoryOutputStream(this, filename);
|
return new MemoryOutputStream(this, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
io::ZeroCopyOutputStream*
|
io::ZeroCopyOutputStream*
|
||||||
CommandLineInterface::MemoryOutputDirectory::OpenForInsert(
|
CommandLineInterface::GeneratorContextImpl::OpenForInsert(
|
||||||
const string& filename, const string& insertion_point) {
|
const string& filename, const string& insertion_point) {
|
||||||
return new MemoryOutputStream(this, filename, insertion_point);
|
return new MemoryOutputStream(this, filename, insertion_point);
|
||||||
}
|
}
|
||||||
@ -427,14 +446,14 @@ CommandLineInterface::MemoryOutputDirectory::OpenForInsert(
|
|||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
|
CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
|
||||||
MemoryOutputDirectory* directory, const string& filename)
|
GeneratorContextImpl* directory, const string& filename)
|
||||||
: directory_(directory),
|
: directory_(directory),
|
||||||
filename_(filename),
|
filename_(filename),
|
||||||
inner_(new io::StringOutputStream(&data_)) {
|
inner_(new io::StringOutputStream(&data_)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
|
CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
|
||||||
MemoryOutputDirectory* directory, const string& filename,
|
GeneratorContextImpl* directory, const string& filename,
|
||||||
const string& insertion_point)
|
const string& insertion_point)
|
||||||
: directory_(directory),
|
: directory_(directory),
|
||||||
filename_(filename),
|
filename_(filename),
|
||||||
@ -548,6 +567,7 @@ CommandLineInterface::CommandLineInterface()
|
|||||||
: mode_(MODE_COMPILE),
|
: mode_(MODE_COMPILE),
|
||||||
error_format_(ERROR_FORMAT_GCC),
|
error_format_(ERROR_FORMAT_GCC),
|
||||||
imports_in_descriptor_set_(false),
|
imports_in_descriptor_set_(false),
|
||||||
|
source_info_in_descriptor_set_(false),
|
||||||
disallow_services_(false),
|
disallow_services_(false),
|
||||||
inputs_are_proto_path_relative_(false) {}
|
inputs_are_proto_path_relative_(false) {}
|
||||||
CommandLineInterface::~CommandLineInterface() {}
|
CommandLineInterface::~CommandLineInterface() {}
|
||||||
@ -556,9 +576,23 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name,
|
|||||||
CodeGenerator* generator,
|
CodeGenerator* generator,
|
||||||
const string& help_text) {
|
const string& help_text) {
|
||||||
GeneratorInfo info;
|
GeneratorInfo info;
|
||||||
|
info.flag_name = flag_name;
|
||||||
info.generator = generator;
|
info.generator = generator;
|
||||||
info.help_text = help_text;
|
info.help_text = help_text;
|
||||||
generators_[flag_name] = info;
|
generators_by_flag_name_[flag_name] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineInterface::RegisterGenerator(const string& flag_name,
|
||||||
|
const string& option_flag_name,
|
||||||
|
CodeGenerator* generator,
|
||||||
|
const string& help_text) {
|
||||||
|
GeneratorInfo info;
|
||||||
|
info.flag_name = flag_name;
|
||||||
|
info.option_flag_name = option_flag_name;
|
||||||
|
info.generator = generator;
|
||||||
|
info.help_text = help_text;
|
||||||
|
generators_by_flag_name_[flag_name] = info;
|
||||||
|
generators_by_option_name_[option_flag_name] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
|
void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
|
||||||
@ -567,7 +601,14 @@ void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
|
|||||||
|
|
||||||
int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
||||||
Clear();
|
Clear();
|
||||||
if (!ParseArguments(argc, argv)) return 1;
|
switch (ParseArguments(argc, argv)) {
|
||||||
|
case PARSE_ARGUMENT_DONE_AND_EXIT:
|
||||||
|
return 0;
|
||||||
|
case PARSE_ARGUMENT_FAIL:
|
||||||
|
return 1;
|
||||||
|
case PARSE_ARGUMENT_DONE_AND_CONTINUE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the source tree.
|
// Set up the source tree.
|
||||||
DiskSourceTree source_tree;
|
DiskSourceTree source_tree;
|
||||||
@ -583,7 +624,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the Importer.
|
// Allocate the Importer.
|
||||||
ErrorPrinter error_collector(error_format_);
|
ErrorPrinter error_collector(error_format_, &source_tree);
|
||||||
Importer importer(&source_tree, &error_collector);
|
Importer importer(&source_tree, &error_collector);
|
||||||
|
|
||||||
vector<const FileDescriptor*> parsed_files;
|
vector<const FileDescriptor*> parsed_files;
|
||||||
@ -603,11 +644,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We construct a separate OutputDirectory for each output location. Note
|
// We construct a separate GeneratorContext for each output location. Note
|
||||||
// that two code generators may output to the same location, in which case
|
// that two code generators may output to the same location, in which case
|
||||||
// they should share a single OutputDirectory (so that OpenForInsert() works).
|
// they should share a single GeneratorContext so that OpenForInsert() works.
|
||||||
typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap;
|
typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
|
||||||
OutputDirectoryMap output_directories;
|
GeneratorContextMap output_directories;
|
||||||
|
|
||||||
// Generate output.
|
// Generate output.
|
||||||
if (mode_ == MODE_COMPILE) {
|
if (mode_ == MODE_COMPILE) {
|
||||||
@ -617,11 +658,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
|||||||
!HasSuffixString(output_location, ".jar")) {
|
!HasSuffixString(output_location, ".jar")) {
|
||||||
AddTrailingSlash(&output_location);
|
AddTrailingSlash(&output_location);
|
||||||
}
|
}
|
||||||
MemoryOutputDirectory** map_slot = &output_directories[output_location];
|
GeneratorContextImpl** map_slot = &output_directories[output_location];
|
||||||
|
|
||||||
if (*map_slot == NULL) {
|
if (*map_slot == NULL) {
|
||||||
// First time we've seen this output location.
|
// First time we've seen this output location.
|
||||||
*map_slot = new MemoryOutputDirectory;
|
*map_slot = new GeneratorContextImpl(parsed_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
|
if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
|
||||||
@ -632,10 +673,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write all output to disk.
|
// Write all output to disk.
|
||||||
for (OutputDirectoryMap::iterator iter = output_directories.begin();
|
for (GeneratorContextMap::iterator iter = output_directories.begin();
|
||||||
iter != output_directories.end(); ++iter) {
|
iter != output_directories.end(); ++iter) {
|
||||||
const string& location = iter->first;
|
const string& location = iter->first;
|
||||||
MemoryOutputDirectory* directory = iter->second;
|
GeneratorContextImpl* directory = iter->second;
|
||||||
if (HasSuffixString(location, "/")) {
|
if (HasSuffixString(location, "/")) {
|
||||||
if (!directory->WriteAllToDisk(location)) {
|
if (!directory->WriteAllToDisk(location)) {
|
||||||
STLDeleteValues(&output_directories);
|
STLDeleteValues(&output_directories);
|
||||||
@ -695,6 +736,7 @@ void CommandLineInterface::Clear() {
|
|||||||
|
|
||||||
mode_ = MODE_COMPILE;
|
mode_ = MODE_COMPILE;
|
||||||
imports_in_descriptor_set_ = false;
|
imports_in_descriptor_set_ = false;
|
||||||
|
source_info_in_descriptor_set_ = false;
|
||||||
disallow_services_ = false;
|
disallow_services_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,7 +779,8 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
|
CommandLineInterface::ParseArgumentStatus
|
||||||
|
CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
|
||||||
executable_name_ = argv[0];
|
executable_name_ = argv[0];
|
||||||
|
|
||||||
// Iterate through all arguments and parse them.
|
// Iterate through all arguments and parse them.
|
||||||
@ -751,41 +794,50 @@ bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
|
|||||||
if (name == "--decode") {
|
if (name == "--decode") {
|
||||||
cerr << "To decode an unknown message, use --decode_raw." << endl;
|
cerr << "To decode an unknown message, use --decode_raw." << endl;
|
||||||
}
|
}
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
} else {
|
} else {
|
||||||
++i;
|
++i;
|
||||||
value = argv[i];
|
value = argv[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InterpretArgument(name, value)) return false;
|
ParseArgumentStatus status = InterpretArgument(name, value);
|
||||||
|
if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE)
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no --proto_path was given, use the current working directory.
|
// If no --proto_path was given, use the current working directory.
|
||||||
if (proto_path_.empty()) {
|
if (proto_path_.empty()) {
|
||||||
proto_path_.push_back(make_pair("", "."));
|
// Don't use make_pair as the old/default standard library on Solaris
|
||||||
|
// doesn't support it without explicit template parameters, which are
|
||||||
|
// incompatible with C++0x's make_pair.
|
||||||
|
proto_path_.push_back(pair<string, string>("", "."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check some errror cases.
|
// Check some errror cases.
|
||||||
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
|
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
|
||||||
if (decoding_raw && !input_files_.empty()) {
|
if (decoding_raw && !input_files_.empty()) {
|
||||||
cerr << "When using --decode_raw, no input files should be given." << endl;
|
cerr << "When using --decode_raw, no input files should be given." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
} else if (!decoding_raw && input_files_.empty()) {
|
} else if (!decoding_raw && input_files_.empty()) {
|
||||||
cerr << "Missing input file." << endl;
|
cerr << "Missing input file." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
|
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
|
||||||
descriptor_set_name_.empty()) {
|
descriptor_set_name_.empty()) {
|
||||||
cerr << "Missing output directives." << endl;
|
cerr << "Missing output directives." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
|
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
|
||||||
cerr << "--include_imports only makes sense when combined with "
|
cerr << "--include_imports only makes sense when combined with "
|
||||||
"--descriptor_set_out." << endl;
|
"--descriptor_set_out." << endl;
|
||||||
}
|
}
|
||||||
|
if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
|
||||||
|
cerr << "--include_source_info only makes sense when combined with "
|
||||||
|
"--descriptor_set_out." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return PARSE_ARGUMENT_DONE_AND_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineInterface::ParseArgument(const char* arg,
|
bool CommandLineInterface::ParseArgument(const char* arg,
|
||||||
@ -835,6 +887,7 @@ bool CommandLineInterface::ParseArgument(const char* arg,
|
|||||||
if (*name == "-h" || *name == "--help" ||
|
if (*name == "-h" || *name == "--help" ||
|
||||||
*name == "--disallow_services" ||
|
*name == "--disallow_services" ||
|
||||||
*name == "--include_imports" ||
|
*name == "--include_imports" ||
|
||||||
|
*name == "--include_source_info" ||
|
||||||
*name == "--version" ||
|
*name == "--version" ||
|
||||||
*name == "--decode_raw") {
|
*name == "--decode_raw") {
|
||||||
// HACK: These are the only flags that don't take a value.
|
// HACK: These are the only flags that don't take a value.
|
||||||
@ -847,8 +900,9 @@ bool CommandLineInterface::ParseArgument(const char* arg,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineInterface::InterpretArgument(const string& name,
|
CommandLineInterface::ParseArgumentStatus
|
||||||
const string& value) {
|
CommandLineInterface::InterpretArgument(const string& name,
|
||||||
|
const string& value) {
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
// Not a flag. Just a filename.
|
// Not a flag. Just a filename.
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
@ -856,7 +910,7 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
"arguments to " << executable_name_ << ". This is actually "
|
"arguments to " << executable_name_ << ". This is actually "
|
||||||
"sort of hard to do. Congrats. Unfortunately it is not valid "
|
"sort of hard to do. Congrats. Unfortunately it is not valid "
|
||||||
"input so the program is going to die now." << endl;
|
"input so the program is going to die now." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_files_.push_back(value);
|
input_files_.push_back(value);
|
||||||
@ -872,7 +926,7 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
string virtual_path;
|
string virtual_path;
|
||||||
string disk_path;
|
string disk_path;
|
||||||
|
|
||||||
int equals_pos = parts[i].find_first_of('=');
|
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||||
if (equals_pos == string::npos) {
|
if (equals_pos == string::npos) {
|
||||||
virtual_path = "";
|
virtual_path = "";
|
||||||
disk_path = parts[i];
|
disk_path = parts[i];
|
||||||
@ -884,7 +938,7 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
if (disk_path.empty()) {
|
if (disk_path.empty()) {
|
||||||
cerr << "--proto_path passed empty directory name. (Use \".\" for "
|
cerr << "--proto_path passed empty directory name. (Use \".\" for "
|
||||||
"current directory.)" << endl;
|
"current directory.)" << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure disk path exists, warn otherwise.
|
// Make sure disk path exists, warn otherwise.
|
||||||
@ -892,35 +946,45 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
cerr << disk_path << ": warning: directory does not exist." << endl;
|
cerr << disk_path << ": warning: directory does not exist." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_path_.push_back(make_pair(virtual_path, disk_path));
|
// Don't use make_pair as the old/default standard library on Solaris
|
||||||
|
// doesn't support it without explicit template parameters, which are
|
||||||
|
// incompatible with C++0x's make_pair.
|
||||||
|
proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (name == "-o" || name == "--descriptor_set_out") {
|
} else if (name == "-o" || name == "--descriptor_set_out") {
|
||||||
if (!descriptor_set_name_.empty()) {
|
if (!descriptor_set_name_.empty()) {
|
||||||
cerr << name << " may only be passed once." << endl;
|
cerr << name << " may only be passed once." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
cerr << name << " requires a non-empty value." << endl;
|
cerr << name << " requires a non-empty value." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
if (mode_ != MODE_COMPILE) {
|
if (mode_ != MODE_COMPILE) {
|
||||||
cerr << "Cannot use --encode or --decode and generate descriptors at the "
|
cerr << "Cannot use --encode or --decode and generate descriptors at the "
|
||||||
"same time." << endl;
|
"same time." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
descriptor_set_name_ = value;
|
descriptor_set_name_ = value;
|
||||||
|
|
||||||
} else if (name == "--include_imports") {
|
} else if (name == "--include_imports") {
|
||||||
if (imports_in_descriptor_set_) {
|
if (imports_in_descriptor_set_) {
|
||||||
cerr << name << " may only be passed once." << endl;
|
cerr << name << " may only be passed once." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
imports_in_descriptor_set_ = true;
|
imports_in_descriptor_set_ = true;
|
||||||
|
|
||||||
|
} else if (name == "--include_source_info") {
|
||||||
|
if (source_info_in_descriptor_set_) {
|
||||||
|
cerr << name << " may only be passed once." << endl;
|
||||||
|
return PARSE_ARGUMENT_FAIL;
|
||||||
|
}
|
||||||
|
source_info_in_descriptor_set_ = true;
|
||||||
|
|
||||||
} else if (name == "-h" || name == "--help") {
|
} else if (name == "-h" || name == "--help") {
|
||||||
PrintHelpText();
|
PrintHelpText();
|
||||||
return false; // Exit without running compiler.
|
return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
|
||||||
|
|
||||||
} else if (name == "--version") {
|
} else if (name == "--version") {
|
||||||
if (!version_info_.empty()) {
|
if (!version_info_.empty()) {
|
||||||
@ -929,7 +993,7 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
cout << "libprotoc "
|
cout << "libprotoc "
|
||||||
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
|
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
|
||||||
<< endl;
|
<< endl;
|
||||||
return false; // Exit without running compiler.
|
return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
|
||||||
|
|
||||||
} else if (name == "--disallow_services") {
|
} else if (name == "--disallow_services") {
|
||||||
disallow_services_ = true;
|
disallow_services_ = true;
|
||||||
@ -938,12 +1002,12 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
name == "--decode_raw") {
|
name == "--decode_raw") {
|
||||||
if (mode_ != MODE_COMPILE) {
|
if (mode_ != MODE_COMPILE) {
|
||||||
cerr << "Only one of --encode and --decode can be specified." << endl;
|
cerr << "Only one of --encode and --decode can be specified." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
|
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
|
||||||
cerr << "Cannot use " << name
|
cerr << "Cannot use " << name
|
||||||
<< " and generate code or descriptors at the same time." << endl;
|
<< " and generate code or descriptors at the same time." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
|
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
|
||||||
@ -953,10 +1017,10 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
if (name == "--decode") {
|
if (name == "--decode") {
|
||||||
cerr << "To decode an unknown message, use --decode_raw." << endl;
|
cerr << "To decode an unknown message, use --decode_raw." << endl;
|
||||||
}
|
}
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
} else if (!value.empty() && name == "--decode_raw") {
|
} else if (!value.empty() && name == "--decode_raw") {
|
||||||
cerr << "--decode_raw does not take a parameter." << endl;
|
cerr << "--decode_raw does not take a parameter." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
codec_type_ = value;
|
codec_type_ = value;
|
||||||
@ -968,16 +1032,16 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
error_format_ = ERROR_FORMAT_MSVS;
|
error_format_ = ERROR_FORMAT_MSVS;
|
||||||
} else {
|
} else {
|
||||||
cerr << "Unknown error format: " << value << endl;
|
cerr << "Unknown error format: " << value << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (name == "--plugin") {
|
} else if (name == "--plugin") {
|
||||||
if (plugin_prefix_.empty()) {
|
if (plugin_prefix_.empty()) {
|
||||||
cerr << "This compiler does not support plugins." << endl;
|
cerr << "This compiler does not support plugins." << endl;
|
||||||
return false;
|
return PARSE_ARGUMENT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
string name;
|
string plugin_name;
|
||||||
string path;
|
string path;
|
||||||
|
|
||||||
string::size_type equals_pos = value.find_first_of('=');
|
string::size_type equals_pos = value.find_first_of('=');
|
||||||
@ -985,57 +1049,68 @@ bool CommandLineInterface::InterpretArgument(const string& name,
|
|||||||
// Use the basename of the file.
|
// Use the basename of the file.
|
||||||
string::size_type slash_pos = value.find_last_of('/');
|
string::size_type slash_pos = value.find_last_of('/');
|
||||||
if (slash_pos == string::npos) {
|
if (slash_pos == string::npos) {
|
||||||
name = value;
|
plugin_name = value;
|
||||||
} else {
|
} else {
|
||||||
name = value.substr(slash_pos + 1);
|
plugin_name = value.substr(slash_pos + 1);
|
||||||
}
|
}
|
||||||
path = value;
|
path = value;
|
||||||
} else {
|
} else {
|
||||||
name = value.substr(0, equals_pos);
|
plugin_name = value.substr(0, equals_pos);
|
||||||
path = value.substr(equals_pos + 1);
|
path = value.substr(equals_pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins_[name] = path;
|
plugins_[plugin_name] = path;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Some other flag. Look it up in the generators list.
|
// Some other flag. Look it up in the generators list.
|
||||||
const GeneratorInfo* generator_info = FindOrNull(generators_, name);
|
const GeneratorInfo* generator_info =
|
||||||
|
FindOrNull(generators_by_flag_name_, name);
|
||||||
if (generator_info == NULL &&
|
if (generator_info == NULL &&
|
||||||
(plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
|
(plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
|
||||||
cerr << "Unknown flag: " << name << endl;
|
// Check if it's a generator option flag.
|
||||||
return false;
|
generator_info = FindOrNull(generators_by_option_name_, name);
|
||||||
}
|
if (generator_info == NULL) {
|
||||||
|
cerr << "Unknown flag: " << name << endl;
|
||||||
// It's an output flag. Add it to the output directives.
|
return PARSE_ARGUMENT_FAIL;
|
||||||
if (mode_ != MODE_COMPILE) {
|
} else {
|
||||||
cerr << "Cannot use --encode or --decode and generate code at the "
|
string* parameters = &generator_parameters_[generator_info->flag_name];
|
||||||
"same time." << endl;
|
if (!parameters->empty()) {
|
||||||
return false;
|
parameters->append(",");
|
||||||
}
|
}
|
||||||
|
parameters->append(value);
|
||||||
OutputDirective directive;
|
}
|
||||||
directive.name = name;
|
|
||||||
if (generator_info == NULL) {
|
|
||||||
directive.generator = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
directive.generator = generator_info->generator;
|
// It's an output flag. Add it to the output directives.
|
||||||
}
|
if (mode_ != MODE_COMPILE) {
|
||||||
|
cerr << "Cannot use --encode or --decode and generate code at the "
|
||||||
|
"same time." << endl;
|
||||||
|
return PARSE_ARGUMENT_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
// Split value at ':' to separate the generator parameter from the
|
OutputDirective directive;
|
||||||
// filename. However, avoid doing this if the colon is part of a valid
|
directive.name = name;
|
||||||
// Windows-style absolute path.
|
if (generator_info == NULL) {
|
||||||
string::size_type colon_pos = value.find_first_of(':');
|
directive.generator = NULL;
|
||||||
if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
|
} else {
|
||||||
directive.output_location = value;
|
directive.generator = generator_info->generator;
|
||||||
} else {
|
}
|
||||||
directive.parameter = value.substr(0, colon_pos);
|
|
||||||
directive.output_location = value.substr(colon_pos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_directives_.push_back(directive);
|
// Split value at ':' to separate the generator parameter from the
|
||||||
|
// filename. However, avoid doing this if the colon is part of a valid
|
||||||
|
// Windows-style absolute path.
|
||||||
|
string::size_type colon_pos = value.find_first_of(':');
|
||||||
|
if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
|
||||||
|
directive.output_location = value;
|
||||||
|
} else {
|
||||||
|
directive.parameter = value.substr(0, colon_pos);
|
||||||
|
directive.output_location = value.substr(colon_pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_directives_.push_back(directive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return PARSE_ARGUMENT_DONE_AND_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::PrintHelpText() {
|
void CommandLineInterface::PrintHelpText() {
|
||||||
@ -1068,6 +1143,12 @@ void CommandLineInterface::PrintHelpText() {
|
|||||||
" --include_imports When using --descriptor_set_out, also include\n"
|
" --include_imports When using --descriptor_set_out, also include\n"
|
||||||
" all dependencies of the input files in the\n"
|
" all dependencies of the input files in the\n"
|
||||||
" set, so that the set is self-contained.\n"
|
" set, so that the set is self-contained.\n"
|
||||||
|
" --include_source_info When using --descriptor_set_out, do not strip\n"
|
||||||
|
" SourceCodeInfo from the FileDescriptorProto.\n"
|
||||||
|
" This results in vastly larger descriptors that\n"
|
||||||
|
" include information about the original\n"
|
||||||
|
" location of each decl in the source file as\n"
|
||||||
|
" well as surrounding comments.\n"
|
||||||
" --error_format=FORMAT Set the format in which to print errors.\n"
|
" --error_format=FORMAT Set the format in which to print errors.\n"
|
||||||
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
|
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
|
||||||
" (Microsoft Visual Studio format)." << endl;
|
" (Microsoft Visual Studio format)." << endl;
|
||||||
@ -1083,8 +1164,8 @@ void CommandLineInterface::PrintHelpText() {
|
|||||||
" the executable's own name differs." << endl;
|
" the executable's own name differs." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GeneratorMap::iterator iter = generators_.begin();
|
for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
|
||||||
iter != generators_.end(); ++iter) {
|
iter != generators_by_flag_name_.end(); ++iter) {
|
||||||
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
|
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
|
||||||
// but fixing this nicely (e.g. splitting on spaces) is probably more
|
// but fixing this nicely (e.g. splitting on spaces) is probably more
|
||||||
// trouble than it's worth.
|
// trouble than it's worth.
|
||||||
@ -1097,7 +1178,7 @@ void CommandLineInterface::PrintHelpText() {
|
|||||||
bool CommandLineInterface::GenerateOutput(
|
bool CommandLineInterface::GenerateOutput(
|
||||||
const vector<const FileDescriptor*>& parsed_files,
|
const vector<const FileDescriptor*>& parsed_files,
|
||||||
const OutputDirective& output_directive,
|
const OutputDirective& output_directive,
|
||||||
OutputDirectory* output_directory) {
|
GeneratorContext* generator_context) {
|
||||||
// Call the generator.
|
// Call the generator.
|
||||||
string error;
|
string error;
|
||||||
if (output_directive.generator == NULL) {
|
if (output_directive.generator == NULL) {
|
||||||
@ -1112,16 +1193,22 @@ bool CommandLineInterface::GenerateOutput(
|
|||||||
|
|
||||||
if (!GeneratePluginOutput(parsed_files, plugin_name,
|
if (!GeneratePluginOutput(parsed_files, plugin_name,
|
||||||
output_directive.parameter,
|
output_directive.parameter,
|
||||||
output_directory, &error)) {
|
generator_context, &error)) {
|
||||||
cerr << output_directive.name << ": " << error << endl;
|
cerr << output_directive.name << ": " << error << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Regular generator.
|
// Regular generator.
|
||||||
|
string parameters = output_directive.parameter;
|
||||||
|
if (!generator_parameters_[output_directive.name].empty()) {
|
||||||
|
if (!parameters.empty()) {
|
||||||
|
parameters.append(",");
|
||||||
|
}
|
||||||
|
parameters.append(generator_parameters_[output_directive.name]);
|
||||||
|
}
|
||||||
for (int i = 0; i < parsed_files.size(); i++) {
|
for (int i = 0; i < parsed_files.size(); i++) {
|
||||||
if (!output_directive.generator->Generate(
|
if (!output_directive.generator->Generate(parsed_files[i], parameters,
|
||||||
parsed_files[i], output_directive.parameter,
|
generator_context, &error)) {
|
||||||
output_directory, &error)) {
|
|
||||||
// Generator returned an error.
|
// Generator returned an error.
|
||||||
cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
|
cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
|
||||||
<< error << endl;
|
<< error << endl;
|
||||||
@ -1137,7 +1224,7 @@ bool CommandLineInterface::GeneratePluginOutput(
|
|||||||
const vector<const FileDescriptor*>& parsed_files,
|
const vector<const FileDescriptor*>& parsed_files,
|
||||||
const string& plugin_name,
|
const string& plugin_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error) {
|
string* error) {
|
||||||
CodeGeneratorRequest request;
|
CodeGeneratorRequest request;
|
||||||
CodeGeneratorResponse response;
|
CodeGeneratorResponse response;
|
||||||
@ -1150,8 +1237,9 @@ bool CommandLineInterface::GeneratePluginOutput(
|
|||||||
set<const FileDescriptor*> already_seen;
|
set<const FileDescriptor*> already_seen;
|
||||||
for (int i = 0; i < parsed_files.size(); i++) {
|
for (int i = 0; i < parsed_files.size(); i++) {
|
||||||
request.add_file_to_generate(parsed_files[i]->name());
|
request.add_file_to_generate(parsed_files[i]->name());
|
||||||
GetTransitiveDependencies(parsed_files[i], &already_seen,
|
GetTransitiveDependencies(parsed_files[i],
|
||||||
request.mutable_proto_file());
|
true, // Include source code info.
|
||||||
|
&already_seen, request.mutable_proto_file());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke the plugin.
|
// Invoke the plugin.
|
||||||
@ -1180,14 +1268,14 @@ bool CommandLineInterface::GeneratePluginOutput(
|
|||||||
// We reset current_output to NULL first so that the old file is closed
|
// We reset current_output to NULL first so that the old file is closed
|
||||||
// before the new one is opened.
|
// before the new one is opened.
|
||||||
current_output.reset();
|
current_output.reset();
|
||||||
current_output.reset(output_directory->OpenForInsert(
|
current_output.reset(generator_context->OpenForInsert(
|
||||||
output_file.name(), output_file.insertion_point()));
|
output_file.name(), output_file.insertion_point()));
|
||||||
} else if (!output_file.name().empty()) {
|
} else if (!output_file.name().empty()) {
|
||||||
// Starting a new file. Open it.
|
// Starting a new file. Open it.
|
||||||
// We reset current_output to NULL first so that the old file is closed
|
// We reset current_output to NULL first so that the old file is closed
|
||||||
// before the new one is opened.
|
// before the new one is opened.
|
||||||
current_output.reset();
|
current_output.reset();
|
||||||
current_output.reset(output_directory->Open(output_file.name()));
|
current_output.reset(generator_context->Open(output_file.name()));
|
||||||
} else if (current_output == NULL) {
|
} else if (current_output == NULL) {
|
||||||
*error = strings::Substitute(
|
*error = strings::Substitute(
|
||||||
"$0: First file chunk returned by plugin did not specify a file name.",
|
"$0: First file chunk returned by plugin did not specify a file name.",
|
||||||
@ -1281,12 +1369,17 @@ bool CommandLineInterface::WriteDescriptorSet(
|
|||||||
if (imports_in_descriptor_set_) {
|
if (imports_in_descriptor_set_) {
|
||||||
set<const FileDescriptor*> already_seen;
|
set<const FileDescriptor*> already_seen;
|
||||||
for (int i = 0; i < parsed_files.size(); i++) {
|
for (int i = 0; i < parsed_files.size(); i++) {
|
||||||
GetTransitiveDependencies(
|
GetTransitiveDependencies(parsed_files[i],
|
||||||
parsed_files[i], &already_seen, file_set.mutable_file());
|
source_info_in_descriptor_set_,
|
||||||
|
&already_seen, file_set.mutable_file());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < parsed_files.size(); i++) {
|
for (int i = 0; i < parsed_files.size(); i++) {
|
||||||
parsed_files[i]->CopyTo(file_set.add_file());
|
FileDescriptorProto* file_proto = file_set.add_file();
|
||||||
|
parsed_files[i]->CopyTo(file_proto);
|
||||||
|
if (source_info_in_descriptor_set_) {
|
||||||
|
parsed_files[i]->CopySourceCodeInfoTo(file_proto);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,7 +1409,7 @@ bool CommandLineInterface::WriteDescriptorSet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::GetTransitiveDependencies(
|
void CommandLineInterface::GetTransitiveDependencies(
|
||||||
const FileDescriptor* file,
|
const FileDescriptor* file, bool include_source_code_info,
|
||||||
set<const FileDescriptor*>* already_seen,
|
set<const FileDescriptor*>* already_seen,
|
||||||
RepeatedPtrField<FileDescriptorProto>* output) {
|
RepeatedPtrField<FileDescriptorProto>* output) {
|
||||||
if (!already_seen->insert(file).second) {
|
if (!already_seen->insert(file).second) {
|
||||||
@ -1326,11 +1419,16 @@ void CommandLineInterface::GetTransitiveDependencies(
|
|||||||
|
|
||||||
// Add all dependencies.
|
// Add all dependencies.
|
||||||
for (int i = 0; i < file->dependency_count(); i++) {
|
for (int i = 0; i < file->dependency_count(); i++) {
|
||||||
GetTransitiveDependencies(file->dependency(i), already_seen, output);
|
GetTransitiveDependencies(file->dependency(i), include_source_code_info,
|
||||||
|
already_seen, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this file.
|
// Add this file.
|
||||||
file->CopyTo(output->Add());
|
FileDescriptorProto* new_descriptor = output->Add();
|
||||||
|
file->CopyTo(new_descriptor);
|
||||||
|
if (include_source_code_info) {
|
||||||
|
file->CopySourceCodeInfoTo(new_descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ template<typename T> class RepeatedPtrField; // repeated_field.h
|
|||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
class CodeGenerator; // code_generator.h
|
class CodeGenerator; // code_generator.h
|
||||||
class OutputDirectory; // code_generator.h
|
class GeneratorContext; // code_generator.h
|
||||||
class DiskSourceTree; // importer.h
|
class DiskSourceTree; // importer.h
|
||||||
|
|
||||||
// This class implements the command-line interface to the protocol compiler.
|
// This class implements the command-line interface to the protocol compiler.
|
||||||
@ -112,6 +112,19 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
CodeGenerator* generator,
|
CodeGenerator* generator,
|
||||||
const string& help_text);
|
const string& help_text);
|
||||||
|
|
||||||
|
// Register a code generator for a language.
|
||||||
|
// Besides flag_name you can specify another option_flag_name that could be
|
||||||
|
// used to pass extra parameters to the registered code generator.
|
||||||
|
// Suppose you have registered a generator by calling:
|
||||||
|
// command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
|
||||||
|
// Then you could invoke the compiler with a command like:
|
||||||
|
// protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
|
||||||
|
// This will pass "enable_bar,enable_baz" as the parameter to the generator.
|
||||||
|
void RegisterGenerator(const string& flag_name,
|
||||||
|
const string& option_flag_name,
|
||||||
|
CodeGenerator* generator,
|
||||||
|
const string& help_text);
|
||||||
|
|
||||||
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
|
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
|
||||||
// but does not match any registered generator, the compiler will attempt to
|
// but does not match any registered generator, the compiler will attempt to
|
||||||
// find a "plugin" to implement the generator. Plugins are just executables.
|
// find a "plugin" to implement the generator. Plugins are just executables.
|
||||||
@ -174,7 +187,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
class ErrorPrinter;
|
class ErrorPrinter;
|
||||||
class MemoryOutputDirectory;
|
class GeneratorContextImpl;
|
||||||
class MemoryOutputStream;
|
class MemoryOutputStream;
|
||||||
|
|
||||||
// Clear state from previous Run().
|
// Clear state from previous Run().
|
||||||
@ -186,8 +199,15 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
bool MakeInputsBeProtoPathRelative(
|
bool MakeInputsBeProtoPathRelative(
|
||||||
DiskSourceTree* source_tree);
|
DiskSourceTree* source_tree);
|
||||||
|
|
||||||
|
// Return status for ParseArguments() and InterpretArgument().
|
||||||
|
enum ParseArgumentStatus {
|
||||||
|
PARSE_ARGUMENT_DONE_AND_CONTINUE,
|
||||||
|
PARSE_ARGUMENT_DONE_AND_EXIT,
|
||||||
|
PARSE_ARGUMENT_FAIL
|
||||||
|
};
|
||||||
|
|
||||||
// Parse all command-line arguments.
|
// Parse all command-line arguments.
|
||||||
bool ParseArguments(int argc, const char* const argv[]);
|
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
|
||||||
|
|
||||||
// Parses a command-line argument into a name/value pair. Returns
|
// Parses a command-line argument into a name/value pair. Returns
|
||||||
// true if the next argument in the argv should be used as the value,
|
// true if the next argument in the argv should be used as the value,
|
||||||
@ -203,7 +223,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
bool ParseArgument(const char* arg, string* name, string* value);
|
bool ParseArgument(const char* arg, string* name, string* value);
|
||||||
|
|
||||||
// Interprets arguments parsed with ParseArgument.
|
// Interprets arguments parsed with ParseArgument.
|
||||||
bool InterpretArgument(const string& name, const string& value);
|
ParseArgumentStatus InterpretArgument(const string& name,
|
||||||
|
const string& value);
|
||||||
|
|
||||||
// Print the --help text to stderr.
|
// Print the --help text to stderr.
|
||||||
void PrintHelpText();
|
void PrintHelpText();
|
||||||
@ -212,11 +233,11 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
struct OutputDirective; // see below
|
struct OutputDirective; // see below
|
||||||
bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
|
bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||||
const OutputDirective& output_directive,
|
const OutputDirective& output_directive,
|
||||||
OutputDirectory* output_directory);
|
GeneratorContext* generator_context);
|
||||||
bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
|
bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||||
const string& plugin_name,
|
const string& plugin_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error);
|
string* error);
|
||||||
|
|
||||||
// Implements --encode and --decode.
|
// Implements --encode and --decode.
|
||||||
@ -230,9 +251,11 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
// protos will be ordered such that every file is listed before any file that
|
// protos will be ordered such that every file is listed before any file that
|
||||||
// depends on it, so that you can call DescriptorPool::BuildFile() on them
|
// depends on it, so that you can call DescriptorPool::BuildFile() on them
|
||||||
// in order. Any files in *already_seen will not be added, and each file
|
// in order. Any files in *already_seen will not be added, and each file
|
||||||
// added will be inserted into *already_seen.
|
// added will be inserted into *already_seen. If include_source_code_info is
|
||||||
|
// true then include the source code information in the FileDescriptorProtos.
|
||||||
static void GetTransitiveDependencies(
|
static void GetTransitiveDependencies(
|
||||||
const FileDescriptor* file,
|
const FileDescriptor* file,
|
||||||
|
bool include_source_code_info,
|
||||||
set<const FileDescriptor*>* already_seen,
|
set<const FileDescriptor*>* already_seen,
|
||||||
RepeatedPtrField<FileDescriptorProto>* output);
|
RepeatedPtrField<FileDescriptorProto>* output);
|
||||||
|
|
||||||
@ -244,13 +267,21 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
// Version info set with SetVersionInfo().
|
// Version info set with SetVersionInfo().
|
||||||
string version_info_;
|
string version_info_;
|
||||||
|
|
||||||
// Map from flag names to registered generators.
|
// Registered generators.
|
||||||
struct GeneratorInfo {
|
struct GeneratorInfo {
|
||||||
|
string flag_name;
|
||||||
|
string option_flag_name;
|
||||||
CodeGenerator* generator;
|
CodeGenerator* generator;
|
||||||
string help_text;
|
string help_text;
|
||||||
};
|
};
|
||||||
typedef map<string, GeneratorInfo> GeneratorMap;
|
typedef map<string, GeneratorInfo> GeneratorMap;
|
||||||
GeneratorMap generators_;
|
GeneratorMap generators_by_flag_name_;
|
||||||
|
GeneratorMap generators_by_option_name_;
|
||||||
|
// A map from generator names to the parameters specified using the option
|
||||||
|
// flag. For example, if the user invokes the compiler with:
|
||||||
|
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
|
||||||
|
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
|
||||||
|
map<string, string> generator_parameters_;
|
||||||
|
|
||||||
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
||||||
string plugin_prefix_;
|
string plugin_prefix_;
|
||||||
@ -302,6 +333,10 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
|||||||
// the .proto files listed on the command-line are added.
|
// the .proto files listed on the command-line are added.
|
||||||
bool imports_in_descriptor_set_;
|
bool imports_in_descriptor_set_;
|
||||||
|
|
||||||
|
// True if --include_source_info was given, meaning that we should not strip
|
||||||
|
// SourceCodeInfo from the DescriptorSet.
|
||||||
|
bool source_info_in_descriptor_set_;
|
||||||
|
|
||||||
// Was the --disallow_services flag used?
|
// Was the --disallow_services flag used?
|
||||||
bool disallow_services_;
|
bool disallow_services_;
|
||||||
|
|
@ -48,6 +48,7 @@
|
|||||||
#include <google/protobuf/compiler/command_line_interface.h>
|
#include <google/protobuf/compiler/command_line_interface.h>
|
||||||
#include <google/protobuf/compiler/code_generator.h>
|
#include <google/protobuf/compiler/code_generator.h>
|
||||||
#include <google/protobuf/compiler/mock_code_generator.h>
|
#include <google/protobuf/compiler/mock_code_generator.h>
|
||||||
|
#include <google/protobuf/compiler/subprocess.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/unittest.pb.h>
|
#include <google/protobuf/unittest.pb.h>
|
||||||
#include <google/protobuf/testing/file.h>
|
#include <google/protobuf/testing/file.h>
|
||||||
@ -121,6 +122,10 @@ class CommandLineInterfaceTest : public testing::Test {
|
|||||||
// substring.
|
// substring.
|
||||||
void ExpectErrorSubstring(const string& expected_substring);
|
void ExpectErrorSubstring(const string& expected_substring);
|
||||||
|
|
||||||
|
// Like ExpectErrorSubstring, but checks that Run() returned zero.
|
||||||
|
void ExpectErrorSubstringWithZeroReturnCode(
|
||||||
|
const string& expected_substring);
|
||||||
|
|
||||||
// Returns true if ExpectErrorSubstring(expected_substring) would pass, but
|
// Returns true if ExpectErrorSubstring(expected_substring) would pass, but
|
||||||
// does not fail otherwise.
|
// does not fail otherwise.
|
||||||
bool HasAlternateErrorSubstring(const string& expected_substring);
|
bool HasAlternateErrorSubstring(const string& expected_substring);
|
||||||
@ -143,6 +148,10 @@ class CommandLineInterfaceTest : public testing::Test {
|
|||||||
const string& proto_name,
|
const string& proto_name,
|
||||||
const string& message_name,
|
const string& message_name,
|
||||||
const string& output_directory);
|
const string& output_directory);
|
||||||
|
void ExpectGeneratedWithMultipleInputs(const string& generator_name,
|
||||||
|
const string& all_proto_names,
|
||||||
|
const string& proto_name,
|
||||||
|
const string& message_name);
|
||||||
void ExpectGeneratedWithInsertions(const string& generator_name,
|
void ExpectGeneratedWithInsertions(const string& generator_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
const string& insertions,
|
const string& insertions,
|
||||||
@ -190,7 +199,7 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
|
|||||||
// implements CodeGenerator ----------------------------------------
|
// implements CodeGenerator ----------------------------------------
|
||||||
bool Generate(const FileDescriptor* file,
|
bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
called_ = true;
|
called_ = true;
|
||||||
parameter_ = parameter;
|
parameter_ = parameter;
|
||||||
@ -220,7 +229,7 @@ void CommandLineInterfaceTest::SetUp() {
|
|||||||
// Register generators.
|
// Register generators.
|
||||||
CodeGenerator* generator = new MockCodeGenerator("test_generator");
|
CodeGenerator* generator = new MockCodeGenerator("test_generator");
|
||||||
mock_generators_to_delete_.push_back(generator);
|
mock_generators_to_delete_.push_back(generator);
|
||||||
cli_.RegisterGenerator("--test_out", generator, "Test output.");
|
cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output.");
|
||||||
cli_.RegisterGenerator("-t", generator, "Test output.");
|
cli_.RegisterGenerator("-t", generator, "Test output.");
|
||||||
|
|
||||||
generator = new MockCodeGenerator("alt_generator");
|
generator = new MockCodeGenerator("alt_generator");
|
||||||
@ -251,7 +260,6 @@ void CommandLineInterfaceTest::Run(const string& command) {
|
|||||||
|
|
||||||
if (!disallow_plugins_) {
|
if (!disallow_plugins_) {
|
||||||
cli_.AllowPlugins("prefix-");
|
cli_.AllowPlugins("prefix-");
|
||||||
|
|
||||||
const char* possible_paths[] = {
|
const char* possible_paths[] = {
|
||||||
// When building with shared libraries, libtool hides the real executable
|
// When building with shared libraries, libtool hides the real executable
|
||||||
// in .libs and puts a fake wrapper in the current directory.
|
// in .libs and puts a fake wrapper in the current directory.
|
||||||
@ -341,6 +349,12 @@ void CommandLineInterfaceTest::ExpectErrorSubstring(
|
|||||||
EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
|
EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode(
|
||||||
|
const string& expected_substring) {
|
||||||
|
EXPECT_EQ(0, return_code_);
|
||||||
|
EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
|
||||||
|
}
|
||||||
|
|
||||||
bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
|
bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
|
||||||
const string& expected_substring) {
|
const string& expected_substring) {
|
||||||
EXPECT_NE(0, return_code_);
|
EXPECT_NE(0, return_code_);
|
||||||
@ -353,7 +367,8 @@ void CommandLineInterfaceTest::ExpectGenerated(
|
|||||||
const string& proto_name,
|
const string& proto_name,
|
||||||
const string& message_name) {
|
const string& message_name) {
|
||||||
MockCodeGenerator::ExpectGenerated(
|
MockCodeGenerator::ExpectGenerated(
|
||||||
generator_name, parameter, "", proto_name, message_name, temp_directory_);
|
generator_name, parameter, "", proto_name, message_name, proto_name,
|
||||||
|
temp_directory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterfaceTest::ExpectGenerated(
|
void CommandLineInterfaceTest::ExpectGenerated(
|
||||||
@ -363,10 +378,21 @@ void CommandLineInterfaceTest::ExpectGenerated(
|
|||||||
const string& message_name,
|
const string& message_name,
|
||||||
const string& output_directory) {
|
const string& output_directory) {
|
||||||
MockCodeGenerator::ExpectGenerated(
|
MockCodeGenerator::ExpectGenerated(
|
||||||
generator_name, parameter, "", proto_name, message_name,
|
generator_name, parameter, "", proto_name, message_name, proto_name,
|
||||||
temp_directory_ + "/" + output_directory);
|
temp_directory_ + "/" + output_directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
|
||||||
|
const string& generator_name,
|
||||||
|
const string& all_proto_names,
|
||||||
|
const string& proto_name,
|
||||||
|
const string& message_name) {
|
||||||
|
MockCodeGenerator::ExpectGenerated(
|
||||||
|
generator_name, "", "", proto_name, message_name,
|
||||||
|
all_proto_names,
|
||||||
|
temp_directory_);
|
||||||
|
}
|
||||||
|
|
||||||
void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
|
void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
|
||||||
const string& generator_name,
|
const string& generator_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
@ -375,7 +401,7 @@ void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
|
|||||||
const string& message_name) {
|
const string& message_name) {
|
||||||
MockCodeGenerator::ExpectGenerated(
|
MockCodeGenerator::ExpectGenerated(
|
||||||
generator_name, parameter, insertions, proto_name, message_name,
|
generator_name, parameter, insertions, proto_name, message_name,
|
||||||
temp_directory_);
|
proto_name, temp_directory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
|
void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
|
||||||
@ -455,8 +481,44 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) {
|
|||||||
"--proto_path=$tmpdir foo.proto bar.proto");
|
"--proto_path=$tmpdir foo.proto bar.proto");
|
||||||
|
|
||||||
ExpectNoErrors();
|
ExpectNoErrors();
|
||||||
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
|
ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
|
||||||
ExpectGenerated("test_generator", "", "bar.proto", "Bar");
|
"foo.proto", "Foo");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
|
||||||
|
"bar.proto", "Bar");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
|
||||||
|
"foo.proto", "Foo");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
|
||||||
|
"bar.proto", "Bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
|
||||||
|
// Test parsing multiple input files with an import of a separate file.
|
||||||
|
|
||||||
|
CreateTempFile("foo.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message Foo {}\n");
|
||||||
|
CreateTempFile("bar.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"import \"baz.proto\";\n"
|
||||||
|
"message Bar {\n"
|
||||||
|
" optional Baz a = 1;\n"
|
||||||
|
"}\n");
|
||||||
|
CreateTempFile("baz.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message Baz {}\n");
|
||||||
|
|
||||||
|
Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
|
||||||
|
"--proto_path=$tmpdir foo.proto bar.proto");
|
||||||
|
|
||||||
|
ExpectNoErrors();
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
|
||||||
|
"foo.proto", "Foo");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
|
||||||
|
"bar.proto", "Bar");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
|
||||||
|
"foo.proto", "Foo");
|
||||||
|
ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
|
||||||
|
"bar.proto", "Bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, CreateDirectory) {
|
TEST_F(CommandLineInterfaceTest, CreateDirectory) {
|
||||||
@ -492,6 +554,32 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
|
|||||||
ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
|
ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
|
||||||
|
// Test that generator parameters specified with the option flag are
|
||||||
|
// correctly passed to the code generator.
|
||||||
|
|
||||||
|
CreateTempFile("foo.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message Foo {}\n");
|
||||||
|
// Create the "a" and "b" sub-directories.
|
||||||
|
CreateTempDir("a");
|
||||||
|
CreateTempDir("b");
|
||||||
|
|
||||||
|
Run("protocol_compiler "
|
||||||
|
"--test_opt=foo1 "
|
||||||
|
"--test_out=bar:$tmpdir/a "
|
||||||
|
"--test_opt=foo2 "
|
||||||
|
"--test_out=baz:$tmpdir/b "
|
||||||
|
"--test_opt=foo3 "
|
||||||
|
"--proto_path=$tmpdir foo.proto");
|
||||||
|
|
||||||
|
ExpectNoErrors();
|
||||||
|
ExpectGenerated(
|
||||||
|
"test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
|
||||||
|
ExpectGenerated(
|
||||||
|
"test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, Insert) {
|
TEST_F(CommandLineInterfaceTest, Insert) {
|
||||||
// Test running a generator that inserts code into another's output.
|
// Test running a generator that inserts code into another's output.
|
||||||
|
|
||||||
@ -515,7 +603,7 @@ TEST_F(CommandLineInterfaceTest, Insert) {
|
|||||||
"foo.proto", "Foo");
|
"foo.proto", "Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
|
TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
|
||||||
// Test that the output path can be a Windows-style path.
|
// Test that the output path can be a Windows-style path.
|
||||||
@ -727,6 +815,33 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
|
|||||||
if (HasFatalFailure()) return;
|
if (HasFatalFailure()) return;
|
||||||
ASSERT_EQ(1, descriptor_set.file_size());
|
ASSERT_EQ(1, descriptor_set.file_size());
|
||||||
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
||||||
|
// Descriptor set should not have source code info.
|
||||||
|
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
|
||||||
|
CreateTempFile("foo.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message Foo {}\n");
|
||||||
|
CreateTempFile("bar.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"import \"foo.proto\";\n"
|
||||||
|
"message Bar {\n"
|
||||||
|
" optional Foo foo = 1;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
|
||||||
|
"--include_source_info --proto_path=$tmpdir bar.proto");
|
||||||
|
|
||||||
|
ExpectNoErrors();
|
||||||
|
|
||||||
|
FileDescriptorSet descriptor_set;
|
||||||
|
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||||
|
if (HasFatalFailure()) return;
|
||||||
|
ASSERT_EQ(1, descriptor_set.file_size());
|
||||||
|
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
||||||
|
// Source code info included.
|
||||||
|
EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
|
TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
|
||||||
@ -755,6 +870,40 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
|
|||||||
}
|
}
|
||||||
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
|
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
|
||||||
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
|
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
|
||||||
|
// Descriptor set should not have source code info.
|
||||||
|
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
|
||||||
|
EXPECT_FALSE(descriptor_set.file(1).has_source_code_info());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
|
||||||
|
CreateTempFile("foo.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message Foo {}\n");
|
||||||
|
CreateTempFile("bar.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"import \"foo.proto\";\n"
|
||||||
|
"message Bar {\n"
|
||||||
|
" optional Foo foo = 1;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
|
||||||
|
"--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
|
||||||
|
|
||||||
|
ExpectNoErrors();
|
||||||
|
|
||||||
|
FileDescriptorSet descriptor_set;
|
||||||
|
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||||
|
if (HasFatalFailure()) return;
|
||||||
|
ASSERT_EQ(2, descriptor_set.file_size());
|
||||||
|
if (descriptor_set.file(0).name() == "bar.proto") {
|
||||||
|
std::swap(descriptor_set.mutable_file()->mutable_data()[0],
|
||||||
|
descriptor_set.mutable_file()->mutable_data()[1]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
|
||||||
|
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
|
||||||
|
// Source code info included.
|
||||||
|
EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
|
||||||
|
EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -1077,6 +1226,17 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
|
||||||
|
CreateTempFile("foo.proto",
|
||||||
|
"syntax = \"proto2\";\n"
|
||||||
|
"message MockCodeGenerator_HasSourceCodeInfo {}\n");
|
||||||
|
|
||||||
|
Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
|
||||||
|
|
||||||
|
ExpectErrorSubstring(
|
||||||
|
"Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
|
TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
|
||||||
// Test what happens if the plugin isn't found.
|
// Test what happens if the plugin isn't found.
|
||||||
|
|
||||||
@ -1089,9 +1249,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
|
|||||||
"--proto_path=$tmpdir error.proto");
|
"--proto_path=$tmpdir error.proto");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ExpectErrorSubstring(
|
ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " +
|
||||||
"--badplug_out: prefix-gen-badplug: The system cannot find the file "
|
Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
|
||||||
"specified.");
|
|
||||||
#else
|
#else
|
||||||
// Error written to stdout by child process after exec() fails.
|
// Error written to stdout by child process after exec() fails.
|
||||||
ExpectErrorSubstring(
|
ExpectErrorSubstring(
|
||||||
@ -1120,11 +1279,11 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
|
|||||||
TEST_F(CommandLineInterfaceTest, HelpText) {
|
TEST_F(CommandLineInterfaceTest, HelpText) {
|
||||||
Run("test_exec_name --help");
|
Run("test_exec_name --help");
|
||||||
|
|
||||||
ExpectErrorSubstring("Usage: test_exec_name ");
|
ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
|
||||||
ExpectErrorSubstring("--test_out=OUT_DIR");
|
ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
|
||||||
ExpectErrorSubstring("Test output.");
|
ExpectErrorSubstringWithZeroReturnCode("Test output.");
|
||||||
ExpectErrorSubstring("--alt_out=OUT_DIR");
|
ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
|
||||||
ExpectErrorSubstring("Alt output.");
|
ExpectErrorSubstringWithZeroReturnCode("Alt output.");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
|
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
|
||||||
@ -1153,7 +1312,7 @@ TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
|
|||||||
"--proto_path=$tmpdir --error_format=msvs foo.proto");
|
"--proto_path=$tmpdir --error_format=msvs foo.proto");
|
||||||
|
|
||||||
ExpectErrorText(
|
ExpectErrorText(
|
||||||
"foo.proto(2) : error in column=1: Expected top-level statement "
|
"$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement "
|
||||||
"(e.g. \"message\").\n");
|
"(e.g. \"message\").\n");
|
||||||
}
|
}
|
||||||
|
|
@ -48,8 +48,8 @@
|
|||||||
#include <google/protobuf/compiler/importer.h>
|
#include <google/protobuf/compiler/importer.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
#include <google/protobuf/stubs/stl_util-inl.h>
|
|
||||||
#include <google/protobuf/stubs/map-util.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/strutil.h>
|
||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
|
|
||||||
@ -79,10 +79,10 @@ class MockErrorCollector : public MultiFileErrorCollector {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockOutputDirectory : public OutputDirectory {
|
class MockGeneratorContext : public GeneratorContext {
|
||||||
public:
|
public:
|
||||||
MockOutputDirectory() {}
|
MockGeneratorContext() {}
|
||||||
~MockOutputDirectory() {
|
~MockGeneratorContext() {
|
||||||
STLDeleteValues(&files_);
|
STLDeleteValues(&files_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ class MockOutputDirectory : public OutputDirectory {
|
|||||||
"to your CL.";
|
"to your CL.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// implements OutputDirectory --------------------------------------
|
// implements GeneratorContext --------------------------------------
|
||||||
|
|
||||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
||||||
string** map_slot = &files_[filename];
|
string** map_slot = &files_[filename];
|
||||||
@ -130,24 +130,24 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
|
|||||||
ASSERT_TRUE(plugin_proto_file != NULL);
|
ASSERT_TRUE(plugin_proto_file != NULL);
|
||||||
|
|
||||||
CppGenerator generator;
|
CppGenerator generator;
|
||||||
MockOutputDirectory output_directory;
|
MockGeneratorContext context;
|
||||||
string error;
|
string error;
|
||||||
string parameter;
|
string parameter;
|
||||||
parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
|
parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
|
||||||
ASSERT_TRUE(generator.Generate(proto_file, parameter,
|
ASSERT_TRUE(generator.Generate(proto_file, parameter,
|
||||||
&output_directory, &error));
|
&context, &error));
|
||||||
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
|
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
|
||||||
ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
|
ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
|
||||||
&output_directory, &error));
|
&context, &error));
|
||||||
|
|
||||||
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h",
|
context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
|
||||||
"google/protobuf/descriptor.pb.h");
|
"google/protobuf/descriptor.pb.h");
|
||||||
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
|
context.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
|
||||||
"google/protobuf/descriptor.pb.cc");
|
"google/protobuf/descriptor.pb.cc");
|
||||||
output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
|
context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
|
||||||
"google/protobuf/compiler/plugin.pb.h");
|
"google/protobuf/compiler/plugin.pb.h");
|
||||||
output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
|
context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
|
||||||
"google/protobuf/compiler/plugin.pb.cc");
|
"google/protobuf/compiler/plugin.pb.cc");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
@ -46,10 +46,10 @@ namespace compiler {
|
|||||||
namespace cpp {
|
namespace cpp {
|
||||||
|
|
||||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
const string& dllexport_decl)
|
const Options& options)
|
||||||
: descriptor_(descriptor),
|
: descriptor_(descriptor),
|
||||||
classname_(ClassName(descriptor, false)),
|
classname_(ClassName(descriptor, false)),
|
||||||
dllexport_decl_(dllexport_decl) {
|
options_(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumGenerator::~EnumGenerator() {}
|
EnumGenerator::~EnumGenerator() {}
|
||||||
@ -88,10 +88,10 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
|||||||
vars["min_name"] = min_value->name();
|
vars["min_name"] = min_value->name();
|
||||||
vars["max_name"] = max_value->name();
|
vars["max_name"] = max_value->name();
|
||||||
|
|
||||||
if (dllexport_decl_.empty()) {
|
if (options_.dllexport_decl.empty()) {
|
||||||
vars["dllexport"] = "";
|
vars["dllexport"] = "";
|
||||||
} else {
|
} else {
|
||||||
vars["dllexport"] = dllexport_decl_ + " ";
|
vars["dllexport"] = options_.dllexport_decl + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
@ -36,8 +36,10 @@
|
|||||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace io {
|
namespace io {
|
||||||
@ -53,7 +55,7 @@ class EnumGenerator {
|
|||||||
public:
|
public:
|
||||||
// See generator.cc for the meaning of dllexport_decl.
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
explicit EnumGenerator(const EnumDescriptor* descriptor,
|
explicit EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
const string& dllexport_decl);
|
const Options& options);
|
||||||
~EnumGenerator();
|
~EnumGenerator();
|
||||||
|
|
||||||
// Header stuff.
|
// Header stuff.
|
||||||
@ -86,7 +88,7 @@ class EnumGenerator {
|
|||||||
private:
|
private:
|
||||||
const EnumDescriptor* descriptor_;
|
const EnumDescriptor* descriptor_;
|
||||||
string classname_;
|
string classname_;
|
||||||
string dllexport_decl_;
|
Options options_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||||
};
|
};
|
@ -46,8 +46,9 @@ namespace cpp {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables) {
|
map<string, string>* variables,
|
||||||
SetCommonFieldVariables(descriptor, variables);
|
const Options& options) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables, options);
|
||||||
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||||
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
||||||
(*variables)["default"] = SimpleItoa(default_value->number());
|
(*variables)["default"] = SimpleItoa(default_value->number());
|
||||||
@ -58,9 +59,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
EnumFieldGenerator::
|
EnumFieldGenerator::
|
||||||
EnumFieldGenerator(const FieldDescriptor* descriptor)
|
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetEnumVariables(descriptor, &variables_);
|
SetEnumVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumFieldGenerator::~EnumFieldGenerator() {}
|
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||||
@ -84,8 +86,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
|||||||
" return static_cast< $type$ >($name$_);\n"
|
" return static_cast< $type$ >($name$_);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||||
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
" assert($type$_IsValid(value));\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" $name$_ = value;\n"
|
" $name$_ = value;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
@ -152,9 +154,10 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
RepeatedEnumFieldGenerator::
|
RepeatedEnumFieldGenerator::
|
||||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
|
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetEnumVariables(descriptor, &variables_);
|
SetEnumVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||||
@ -187,11 +190,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
|||||||
" return static_cast< $type$ >($name$_.Get(index));\n"
|
" return static_cast< $type$ >($name$_.Get(index));\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
||||||
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
" assert($type$_IsValid(value));\n"
|
||||||
" $name$_.Set(index, value);\n"
|
" $name$_.Set(index, value);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::add_$name$($type$ value) {\n"
|
"inline void $classname$::add_$name$($type$ value) {\n"
|
||||||
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
" assert($type$_IsValid(value));\n"
|
||||||
" $name$_.Add(value);\n"
|
" $name$_.Add(value);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
@ -345,7 +348,9 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
" total_size += $tag_size$ +\n"
|
" total_size += $tag_size$ +\n"
|
||||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||||
"_$name$_cached_byte_size_ = data_size;\n"
|
"_$name$_cached_byte_size_ = data_size;\n"
|
||||||
|
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||||
"total_size += data_size;\n");
|
"total_size += data_size;\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
@ -46,7 +46,8 @@ namespace cpp {
|
|||||||
|
|
||||||
class EnumFieldGenerator : public FieldGenerator {
|
class EnumFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
|
explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~EnumFieldGenerator();
|
~EnumFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
@ -71,7 +72,8 @@ class EnumFieldGenerator : public FieldGenerator {
|
|||||||
|
|
||||||
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~RepeatedEnumFieldGenerator();
|
~RepeatedEnumFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
@ -57,9 +57,9 @@ string ExtendeeClassName(const FieldDescriptor* descriptor) {
|
|||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||||
const string& dllexport_decl)
|
const Options& options)
|
||||||
: descriptor_(descriptor),
|
: descriptor_(descriptor),
|
||||||
dllexport_decl_(dllexport_decl) {
|
options_(options) {
|
||||||
// Construct type_traits_.
|
// Construct type_traits_.
|
||||||
if (descriptor_->is_repeated()) {
|
if (descriptor_->is_repeated()) {
|
||||||
type_traits_ = "Repeated";
|
type_traits_ = "Repeated";
|
||||||
@ -106,8 +106,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
|
|||||||
// export/import specifier.
|
// export/import specifier.
|
||||||
if (descriptor_->extension_scope() == NULL) {
|
if (descriptor_->extension_scope() == NULL) {
|
||||||
vars["qualifier"] = "extern";
|
vars["qualifier"] = "extern";
|
||||||
if (!dllexport_decl_.empty()) {
|
if (!options_.dllexport_decl.empty()) {
|
||||||
vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
|
vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vars["qualifier"] = "static";
|
vars["qualifier"] = "static";
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -56,8 +57,8 @@ namespace cpp {
|
|||||||
class ExtensionGenerator {
|
class ExtensionGenerator {
|
||||||
public:
|
public:
|
||||||
// See generator.cc for the meaning of dllexport_decl.
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
explicit ExtensionGenerator(const FieldDescriptor* descriptor,
|
explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
|
||||||
const string& dllexport_decl);
|
const Options& options);
|
||||||
~ExtensionGenerator();
|
~ExtensionGenerator();
|
||||||
|
|
||||||
// Header stuff.
|
// Header stuff.
|
||||||
@ -72,7 +73,7 @@ class ExtensionGenerator {
|
|||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
string type_traits_;
|
string type_traits_;
|
||||||
string dllexport_decl_;
|
Options options_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
||||||
};
|
};
|
@ -52,7 +52,8 @@ namespace cpp {
|
|||||||
using internal::WireFormat;
|
using internal::WireFormat;
|
||||||
|
|
||||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables) {
|
map<string, string>* variables,
|
||||||
|
const Options& options) {
|
||||||
(*variables)["name"] = FieldName(descriptor);
|
(*variables)["name"] = FieldName(descriptor);
|
||||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
@ -64,6 +65,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
|||||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
? " PROTOBUF_DEPRECATED" : "";
|
? " PROTOBUF_DEPRECATED" : "";
|
||||||
|
|
||||||
|
(*variables)["cppget"] = "Get";
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldGenerator::~FieldGenerator() {}
|
FieldGenerator::~FieldGenerator() {}
|
||||||
@ -80,46 +82,47 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
|
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor),
|
: descriptor_(descriptor),
|
||||||
field_generators_(
|
field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||||
new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
|
||||||
// Construct all the FieldGenerators.
|
// Construct all the FieldGenerators.
|
||||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
|
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
|
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
|
||||||
|
const Options& options) {
|
||||||
if (field->is_repeated()) {
|
if (field->is_repeated()) {
|
||||||
switch (field->cpp_type()) {
|
switch (field->cpp_type()) {
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
return new RepeatedMessageFieldGenerator(field);
|
return new RepeatedMessageFieldGenerator(field, options);
|
||||||
case FieldDescriptor::CPPTYPE_STRING:
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
switch (field->options().ctype()) {
|
switch (field->options().ctype()) {
|
||||||
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
||||||
case FieldOptions::STRING:
|
case FieldOptions::STRING:
|
||||||
return new RepeatedStringFieldGenerator(field);
|
return new RepeatedStringFieldGenerator(field, options);
|
||||||
}
|
}
|
||||||
case FieldDescriptor::CPPTYPE_ENUM:
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
return new RepeatedEnumFieldGenerator(field);
|
return new RepeatedEnumFieldGenerator(field, options);
|
||||||
default:
|
default:
|
||||||
return new RepeatedPrimitiveFieldGenerator(field);
|
return new RepeatedPrimitiveFieldGenerator(field, options);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (field->cpp_type()) {
|
switch (field->cpp_type()) {
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
return new MessageFieldGenerator(field);
|
return new MessageFieldGenerator(field, options);
|
||||||
case FieldDescriptor::CPPTYPE_STRING:
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
switch (field->options().ctype()) {
|
switch (field->options().ctype()) {
|
||||||
default: // StringFieldGenerator handles unknown ctypes.
|
default: // StringFieldGenerator handles unknown ctypes.
|
||||||
case FieldOptions::STRING:
|
case FieldOptions::STRING:
|
||||||
return new StringFieldGenerator(field);
|
return new StringFieldGenerator(field, options);
|
||||||
}
|
}
|
||||||
case FieldDescriptor::CPPTYPE_ENUM:
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
return new EnumFieldGenerator(field);
|
return new EnumFieldGenerator(field, options);
|
||||||
default:
|
default:
|
||||||
return new PrimitiveFieldGenerator(field);
|
return new PrimitiveFieldGenerator(field, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -57,7 +58,8 @@ namespace cpp {
|
|||||||
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||||
// 'deprecation'].
|
// 'deprecation'].
|
||||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables);
|
map<string, string>* variables,
|
||||||
|
const Options& options);
|
||||||
|
|
||||||
class FieldGenerator {
|
class FieldGenerator {
|
||||||
public:
|
public:
|
||||||
@ -114,6 +116,13 @@ class FieldGenerator {
|
|||||||
// Most field types don't need this, so the default implementation is empty.
|
// Most field types don't need this, so the default implementation is empty.
|
||||||
virtual void GenerateDestructorCode(io::Printer* printer) const {}
|
virtual void GenerateDestructorCode(io::Printer* printer) const {}
|
||||||
|
|
||||||
|
// Generate code that allocates the fields's default instance.
|
||||||
|
virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {}
|
||||||
|
|
||||||
|
// Generate code that should be run when ShutdownProtobufLibrary() is called,
|
||||||
|
// to delete all dynamically-allocated objects.
|
||||||
|
virtual void GenerateShutdownCode(io::Printer* printer) const {}
|
||||||
|
|
||||||
// Generate lines to decode this field, which will be placed inside the
|
// Generate lines to decode this field, which will be placed inside the
|
||||||
// message's MergeFromCodedStream() method.
|
// message's MergeFromCodedStream() method.
|
||||||
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
|
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
|
||||||
@ -144,7 +153,7 @@ class FieldGenerator {
|
|||||||
// Convenience class which constructs FieldGenerators for a Descriptor.
|
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||||
class FieldGeneratorMap {
|
class FieldGeneratorMap {
|
||||||
public:
|
public:
|
||||||
explicit FieldGeneratorMap(const Descriptor* descriptor);
|
explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
|
||||||
~FieldGeneratorMap();
|
~FieldGeneratorMap();
|
||||||
|
|
||||||
const FieldGenerator& get(const FieldDescriptor* field) const;
|
const FieldGenerator& get(const FieldDescriptor* field) const;
|
||||||
@ -153,7 +162,8 @@ class FieldGeneratorMap {
|
|||||||
const Descriptor* descriptor_;
|
const Descriptor* descriptor_;
|
||||||
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
||||||
|
|
||||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
|
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||||
|
const Options& options);
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||||
};
|
};
|
@ -51,7 +51,7 @@ namespace cpp {
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
FileGenerator::FileGenerator(const FileDescriptor* file,
|
FileGenerator::FileGenerator(const FileDescriptor* file,
|
||||||
const string& dllexport_decl)
|
const Options& options)
|
||||||
: file_(file),
|
: file_(file),
|
||||||
message_generators_(
|
message_generators_(
|
||||||
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||||
@ -61,26 +61,26 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
|
|||||||
new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
||||||
extension_generators_(
|
extension_generators_(
|
||||||
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||||
dllexport_decl_(dllexport_decl) {
|
options_(options) {
|
||||||
|
|
||||||
for (int i = 0; i < file->message_type_count(); i++) {
|
for (int i = 0; i < file->message_type_count(); i++) {
|
||||||
message_generators_[i].reset(
|
message_generators_[i].reset(
|
||||||
new MessageGenerator(file->message_type(i), dllexport_decl));
|
new MessageGenerator(file->message_type(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file->enum_type_count(); i++) {
|
for (int i = 0; i < file->enum_type_count(); i++) {
|
||||||
enum_generators_[i].reset(
|
enum_generators_[i].reset(
|
||||||
new EnumGenerator(file->enum_type(i), dllexport_decl));
|
new EnumGenerator(file->enum_type(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file->service_count(); i++) {
|
for (int i = 0; i < file->service_count(); i++) {
|
||||||
service_generators_[i].reset(
|
service_generators_[i].reset(
|
||||||
new ServiceGenerator(file->service(i), dllexport_decl));
|
new ServiceGenerator(file->service(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file->extension_count(); i++) {
|
for (int i = 0; i < file->extension_count(); i++) {
|
||||||
extension_generators_[i].reset(
|
extension_generators_[i].reset(
|
||||||
new ExtensionGenerator(file->extension(i), dllexport_decl));
|
new ExtensionGenerator(file->extension(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitStringUsing(file_->package(), ".", &package_parts_);
|
SplitStringUsing(file_->package(), ".", &package_parts_);
|
||||||
@ -104,6 +104,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
"filename", file_->name(),
|
"filename", file_->name(),
|
||||||
"filename_identifier", filename_identifier);
|
"filename_identifier", filename_identifier);
|
||||||
|
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"#include <google/protobuf/stubs/common.h>\n"
|
"#include <google/protobuf/stubs/common.h>\n"
|
||||||
"\n");
|
"\n");
|
||||||
@ -128,13 +129,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
|
|
||||||
// OK, it's now safe to #include other files.
|
// OK, it's now safe to #include other files.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"#include <google/protobuf/generated_message_util.h>\n"
|
"#include <google/protobuf/generated_message_util.h>\n");
|
||||||
|
if (file_->message_type_count() > 0) {
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/message.h>\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/message_lite.h>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printer->Print(
|
||||||
"#include <google/protobuf/repeated_field.h>\n"
|
"#include <google/protobuf/repeated_field.h>\n"
|
||||||
"#include <google/protobuf/extension_set.h>\n");
|
"#include <google/protobuf/extension_set.h>\n");
|
||||||
|
|
||||||
if (HasDescriptorMethods(file_)) {
|
if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"#include <google/protobuf/generated_message_reflection.h>\n");
|
"#include <google/protobuf/generated_enum_reflection.h>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasGenericServices(file_)) {
|
if (HasGenericServices(file_)) {
|
||||||
@ -142,6 +153,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
"#include <google/protobuf/service.h>\n");
|
"#include <google/protobuf/service.h>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/unknown_field_set.h>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
@ -149,9 +165,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
"dependency", StripProto(file_->dependency(i)->name()));
|
"dependency", StripProto(file_->dependency(i)->name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"// @@protoc_insertion_point(includes)\n");
|
"// @@protoc_insertion_point(includes)\n");
|
||||||
|
|
||||||
|
|
||||||
// Open namespace.
|
// Open namespace.
|
||||||
GenerateNamespaceOpeners(printer);
|
GenerateNamespaceOpeners(printer);
|
||||||
|
|
||||||
@ -162,7 +180,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
"// Internal implementation detail -- do not call these.\n"
|
"// Internal implementation detail -- do not call these.\n"
|
||||||
"void $dllexport_decl$ $adddescriptorsname$();\n",
|
"void $dllexport_decl$ $adddescriptorsname$();\n",
|
||||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||||
"dllexport_decl", dllexport_decl_);
|
"dllexport_decl", options_.dllexport_decl);
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
// Note that we don't put dllexport_decl on these because they are only
|
// Note that we don't put dllexport_decl on these because they are only
|
||||||
@ -282,20 +300,27 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
void FileGenerator::GenerateSource(io::Printer* printer) {
|
void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||||
|
"// source: $filename$\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
// The generated code calls accessors that might be deprecated. We don't
|
// The generated code calls accessors that might be deprecated. We don't
|
||||||
// want the compiler to warn in generated code.
|
// want the compiler to warn in generated code.
|
||||||
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
||||||
"#include \"$basename$.pb.h\"\n"
|
"#include \"$basename$.pb.h\"\n"
|
||||||
|
"\n"
|
||||||
|
"#include <algorithm>\n" // for swap()
|
||||||
|
"\n"
|
||||||
|
"#include <google/protobuf/stubs/common.h>\n"
|
||||||
"#include <google/protobuf/stubs/once.h>\n"
|
"#include <google/protobuf/stubs/once.h>\n"
|
||||||
"#include <google/protobuf/io/coded_stream.h>\n"
|
"#include <google/protobuf/io/coded_stream.h>\n"
|
||||||
"#include <google/protobuf/wire_format_lite_inl.h>\n",
|
"#include <google/protobuf/wire_format_lite_inl.h>\n",
|
||||||
|
"filename", file_->name(),
|
||||||
"basename", StripProto(file_->name()));
|
"basename", StripProto(file_->name()));
|
||||||
|
|
||||||
if (HasDescriptorMethods(file_)) {
|
if (HasDescriptorMethods(file_)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"#include <google/protobuf/descriptor.h>\n"
|
"#include <google/protobuf/descriptor.h>\n"
|
||||||
|
"#include <google/protobuf/generated_message_reflection.h>\n"
|
||||||
"#include <google/protobuf/reflection_ops.h>\n"
|
"#include <google/protobuf/reflection_ops.h>\n"
|
||||||
"#include <google/protobuf/wire_format.h>\n");
|
"#include <google/protobuf/wire_format.h>\n");
|
||||||
}
|
}
|
||||||
@ -378,11 +403,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
|||||||
|
|
||||||
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
||||||
// AddDescriptors() is a file-level procedure which adds the encoded
|
// AddDescriptors() is a file-level procedure which adds the encoded
|
||||||
// FileDescriptorProto for this .proto file to the global DescriptorPool
|
// FileDescriptorProto for this .proto file to the global DescriptorPool for
|
||||||
// for generated files (DescriptorPool::generated_pool()). It always runs
|
// generated files (DescriptorPool::generated_pool()). It either runs at
|
||||||
// at static initialization time, so all files will be registered before
|
// static initialization time (by default) or when default_instance() is
|
||||||
// main() starts. This procedure also constructs default instances and
|
// called for the first time (in LITE_RUNTIME mode with
|
||||||
// registers extensions.
|
// GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
|
||||||
|
// constructs default instances and registers extensions.
|
||||||
//
|
//
|
||||||
// Its sibling, AssignDescriptors(), actually pulls the compiled
|
// Its sibling, AssignDescriptors(), actually pulls the compiled
|
||||||
// FileDescriptor from the DescriptorPool and uses it to populate all of
|
// FileDescriptor from the DescriptorPool and uses it to populate all of
|
||||||
@ -486,22 +512,29 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
|||||||
|
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"}\n");
|
"}\n\n");
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
// Now generate the AddDescriptors() function.
|
// Now generate the AddDescriptors() function.
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
"\n"
|
file_, printer,
|
||||||
|
// With static initializers.
|
||||||
|
// Note that we don't need any special synchronization in the following code
|
||||||
|
// because it is called at static init time before any threads exist.
|
||||||
"void $adddescriptorsname$() {\n"
|
"void $adddescriptorsname$() {\n"
|
||||||
// We don't need any special synchronization here because this code is
|
|
||||||
// called at static init time before any threads exist.
|
|
||||||
" static bool already_here = false;\n"
|
" static bool already_here = false;\n"
|
||||||
" if (already_here) return;\n"
|
" if (already_here) return;\n"
|
||||||
" already_here = true;\n"
|
" already_here = true;\n"
|
||||||
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
||||||
"\n",
|
"\n",
|
||||||
|
// Without.
|
||||||
|
"void $adddescriptorsname$_impl() {\n"
|
||||||
|
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
||||||
|
"\n",
|
||||||
|
// Vars.
|
||||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||||
|
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
// Call the AddDescriptors() methods for all of our dependencies, to make
|
// Call the AddDescriptors() methods for all of our dependencies, to make
|
||||||
@ -512,9 +545,9 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
|||||||
vector<string> dependency_package_parts;
|
vector<string> dependency_package_parts;
|
||||||
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
|
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
|
||||||
printer->Print("::");
|
printer->Print("::");
|
||||||
for (int i = 0; i < dependency_package_parts.size(); i++) {
|
for (int j = 0; j < dependency_package_parts.size(); j++) {
|
||||||
printer->Print("$name$::",
|
printer->Print("$name$::",
|
||||||
"name", dependency_package_parts[i]);
|
"name", dependency_package_parts[j]);
|
||||||
}
|
}
|
||||||
// Call its AddDescriptors function.
|
// Call its AddDescriptors function.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
@ -538,10 +571,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
|||||||
static const int kBytesPerLine = 40;
|
static const int kBytesPerLine = 40;
|
||||||
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
||||||
printer->Print("\n \"$data$\"",
|
printer->Print("\n \"$data$\"",
|
||||||
"data", CEscape(file_data.substr(i, kBytesPerLine)));
|
"data",
|
||||||
|
EscapeTrigraphs(
|
||||||
|
CEscape(file_data.substr(i, kBytesPerLine))));
|
||||||
}
|
}
|
||||||
printer->Print(
|
printer->Print(
|
||||||
", $size$);\n",
|
", $size$);\n",
|
||||||
"size", SimpleItoa(file_data.size()));
|
"size", SimpleItoa(file_data.size()));
|
||||||
|
|
||||||
// Call MessageFactory::InternalRegisterGeneratedFile().
|
// Call MessageFactory::InternalRegisterGeneratedFile().
|
||||||
@ -569,17 +604,26 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
|||||||
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||||
|
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n");
|
||||||
|
|
||||||
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
file_, printer,
|
||||||
|
// With static initializers.
|
||||||
"// Force AddDescriptors() to be called at static initialization time.\n"
|
"// Force AddDescriptors() to be called at static initialization time.\n"
|
||||||
"struct StaticDescriptorInitializer_$filename$ {\n"
|
"struct StaticDescriptorInitializer_$filename$ {\n"
|
||||||
" StaticDescriptorInitializer_$filename$() {\n"
|
" StaticDescriptorInitializer_$filename$() {\n"
|
||||||
" $adddescriptorsname$();\n"
|
" $adddescriptorsname$();\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"} static_descriptor_initializer_$filename$_;\n"
|
"} static_descriptor_initializer_$filename$_;\n",
|
||||||
"\n",
|
// Without.
|
||||||
|
"GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
|
||||||
|
"void $adddescriptorsname$() {\n"
|
||||||
|
" ::google::protobuf::::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
|
||||||
|
" &$adddescriptorsname$_impl);\n"
|
||||||
|
"}\n",
|
||||||
|
// Vars.
|
||||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||||
"filename", FilenameIdentifier(file_->name()));
|
"filename", FilenameIdentifier(file_->name()));
|
||||||
}
|
}
|
@ -39,6 +39,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -61,7 +62,7 @@ class FileGenerator {
|
|||||||
public:
|
public:
|
||||||
// See generator.cc for the meaning of dllexport_decl.
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
explicit FileGenerator(const FileDescriptor* file,
|
explicit FileGenerator(const FileDescriptor* file,
|
||||||
const string& dllexport_decl);
|
const Options& options);
|
||||||
~FileGenerator();
|
~FileGenerator();
|
||||||
|
|
||||||
void GenerateHeader(io::Printer* printer);
|
void GenerateHeader(io::Printer* printer);
|
||||||
@ -85,7 +86,7 @@ class FileGenerator {
|
|||||||
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
|
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
|
||||||
vector<string> package_parts_;
|
vector<string> package_parts_;
|
||||||
|
|
||||||
string dllexport_decl_;
|
const Options options_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
||||||
};
|
};
|
@ -53,7 +53,7 @@ CppGenerator::~CppGenerator() {}
|
|||||||
|
|
||||||
bool CppGenerator::Generate(const FileDescriptor* file,
|
bool CppGenerator::Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
vector<pair<string, string> > options;
|
vector<pair<string, string> > options;
|
||||||
ParseGeneratorParameter(parameter, &options);
|
ParseGeneratorParameter(parameter, &options);
|
||||||
@ -78,11 +78,13 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
|||||||
// }
|
// }
|
||||||
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
|
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
|
||||||
// __declspec(dllimport) depending on what is being compiled.
|
// __declspec(dllimport) depending on what is being compiled.
|
||||||
string dllexport_decl;
|
Options file_options;
|
||||||
|
|
||||||
for (int i = 0; i < options.size(); i++) {
|
for (int i = 0; i < options.size(); i++) {
|
||||||
if (options[i].first == "dllexport_decl") {
|
if (options[i].first == "dllexport_decl") {
|
||||||
dllexport_decl = options[i].second;
|
file_options.dllexport_decl = options[i].second;
|
||||||
|
} else if (options[i].first == "safe_boundary_check") {
|
||||||
|
file_options.safe_boundary_check = true;
|
||||||
} else {
|
} else {
|
||||||
*error = "Unknown generator option: " + options[i].first;
|
*error = "Unknown generator option: " + options[i].first;
|
||||||
return false;
|
return false;
|
||||||
@ -95,12 +97,12 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
|||||||
string basename = StripProto(file->name());
|
string basename = StripProto(file->name());
|
||||||
basename.append(".pb");
|
basename.append(".pb");
|
||||||
|
|
||||||
FileGenerator file_generator(file, dllexport_decl);
|
FileGenerator file_generator(file, file_options);
|
||||||
|
|
||||||
// Generate header.
|
// Generate header.
|
||||||
{
|
{
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->Open(basename + ".h"));
|
generator_context->Open(basename + ".h"));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
file_generator.GenerateHeader(&printer);
|
file_generator.GenerateHeader(&printer);
|
||||||
}
|
}
|
||||||
@ -108,7 +110,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
|||||||
// Generate cc file.
|
// Generate cc file.
|
||||||
{
|
{
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->Open(basename + ".cc"));
|
generator_context->Open(basename + ".cc"));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
file_generator.GenerateSource(&printer);
|
file_generator.GenerateSource(&printer);
|
||||||
}
|
}
|
@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator {
|
|||||||
// implements CodeGenerator ----------------------------------------
|
// implements CodeGenerator ----------------------------------------
|
||||||
bool Generate(const FileDescriptor* file,
|
bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error) const;
|
string* error) const;
|
||||||
|
|
||||||
private:
|
private:
|
@ -33,10 +33,12 @@
|
|||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <google/protobuf/stubs/hash.h>
|
#include <google/protobuf/stubs/hash.h>
|
||||||
|
|
||||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
@ -105,6 +107,20 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether the provided descriptor has an extension. This includes its
|
||||||
|
// nested types.
|
||||||
|
bool HasExtension(const Descriptor* descriptor) {
|
||||||
|
if (descriptor->extension_count() > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||||
|
if (HasExtension(descriptor->nested_type(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
const char kThickSeparator[] =
|
const char kThickSeparator[] =
|
||||||
@ -132,7 +148,7 @@ string ClassName(const Descriptor* descriptor, bool qualified) {
|
|||||||
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
|
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
|
||||||
if (enum_descriptor->containing_type() == NULL) {
|
if (enum_descriptor->containing_type() == NULL) {
|
||||||
if (qualified) {
|
if (qualified) {
|
||||||
return DotsToColons(enum_descriptor->full_name());
|
return "::" + DotsToColons(enum_descriptor->full_name());
|
||||||
} else {
|
} else {
|
||||||
return enum_descriptor->name();
|
return enum_descriptor->name();
|
||||||
}
|
}
|
||||||
@ -243,10 +259,23 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
|
|||||||
string DefaultValue(const FieldDescriptor* field) {
|
string DefaultValue(const FieldDescriptor* field) {
|
||||||
switch (field->cpp_type()) {
|
switch (field->cpp_type()) {
|
||||||
case FieldDescriptor::CPPTYPE_INT32:
|
case FieldDescriptor::CPPTYPE_INT32:
|
||||||
|
// gcc rejects the decimal form of kint32min and kint64min.
|
||||||
|
if (field->default_value_int32() == kint32min) {
|
||||||
|
// Make sure we are in a 2's complement system.
|
||||||
|
GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error);
|
||||||
|
return "-0x80000000";
|
||||||
|
}
|
||||||
return SimpleItoa(field->default_value_int32());
|
return SimpleItoa(field->default_value_int32());
|
||||||
case FieldDescriptor::CPPTYPE_UINT32:
|
case FieldDescriptor::CPPTYPE_UINT32:
|
||||||
return SimpleItoa(field->default_value_uint32()) + "u";
|
return SimpleItoa(field->default_value_uint32()) + "u";
|
||||||
case FieldDescriptor::CPPTYPE_INT64:
|
case FieldDescriptor::CPPTYPE_INT64:
|
||||||
|
// See the comments for CPPTYPE_INT32.
|
||||||
|
if (field->default_value_int64() == kint64min) {
|
||||||
|
// Make sure we are in a 2's complement system.
|
||||||
|
GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000),
|
||||||
|
kint64min_value_error);
|
||||||
|
return "GOOGLE_LONGLONG(-0x8000000000000000)";
|
||||||
|
}
|
||||||
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
|
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
|
||||||
case FieldDescriptor::CPPTYPE_UINT64:
|
case FieldDescriptor::CPPTYPE_UINT64:
|
||||||
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
||||||
@ -292,7 +321,9 @@ string DefaultValue(const FieldDescriptor* field) {
|
|||||||
ClassName(field->enum_type(), true),
|
ClassName(field->enum_type(), true),
|
||||||
field->default_value_enum()->number());
|
field->default_value_enum()->number());
|
||||||
case FieldDescriptor::CPPTYPE_STRING:
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
return "\"" + CEscape(field->default_value_string()) + "\"";
|
return "\"" + EscapeTrigraphs(
|
||||||
|
CEscape(field->default_value_string())) +
|
||||||
|
"\"";
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
return FieldMessageTypeName(field) + "::default_instance()";
|
return FieldMessageTypeName(field) + "::default_instance()";
|
||||||
}
|
}
|
||||||
@ -335,6 +366,72 @@ string GlobalShutdownFileName(const string& filename) {
|
|||||||
return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
|
return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Escape C++ trigraphs by escaping question marks to \?
|
||||||
|
string EscapeTrigraphs(const string& to_escape) {
|
||||||
|
return StringReplace(to_escape, "?", "\\?", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StaticInitializersForced(const FileDescriptor* file) {
|
||||||
|
if (HasDescriptorMethods(file) || file->extension_count() > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||||
|
if (HasExtension(file->message_type(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintHandlingOptionalStaticInitializers(
|
||||||
|
const FileDescriptor* file, io::Printer* printer,
|
||||||
|
const char* with_static_init, const char* without_static_init,
|
||||||
|
const char* var1, const string& val1,
|
||||||
|
const char* var2, const string& val2) {
|
||||||
|
map<string, string> vars;
|
||||||
|
if (var1) {
|
||||||
|
vars[var1] = val1;
|
||||||
|
}
|
||||||
|
if (var2) {
|
||||||
|
vars[var2] = val2;
|
||||||
|
}
|
||||||
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
vars, file, printer, with_static_init, without_static_init);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintHandlingOptionalStaticInitializers(
|
||||||
|
const map<string, string>& vars, const FileDescriptor* file,
|
||||||
|
io::Printer* printer, const char* with_static_init,
|
||||||
|
const char* without_static_init) {
|
||||||
|
if (StaticInitializersForced(file)) {
|
||||||
|
printer->Print(vars, with_static_init);
|
||||||
|
} else {
|
||||||
|
printer->Print(vars, (string(
|
||||||
|
"#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
|
||||||
|
without_static_init +
|
||||||
|
"#else\n" +
|
||||||
|
with_static_init +
|
||||||
|
"#endif\n").c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool HasEnumDefinitions(const Descriptor* message_type) {
|
||||||
|
if (message_type->enum_type_count() > 0) return true;
|
||||||
|
for (int i = 0; i < message_type->nested_type_count(); ++i) {
|
||||||
|
if (HasEnumDefinitions(message_type->nested_type(i))) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasEnumDefinitions(const FileDescriptor* file) {
|
||||||
|
if (file->enum_type_count() > 0) return true;
|
||||||
|
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||||
|
if (HasEnumDefinitions(file->message_type(i))) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace cpp
|
} // namespace cpp
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
@ -35,12 +35,18 @@
|
|||||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
class Printer;
|
||||||
|
}
|
||||||
|
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace cpp {
|
namespace cpp {
|
||||||
|
|
||||||
@ -112,24 +118,31 @@ string GlobalAssignDescriptorsName(const string& filename);
|
|||||||
// Return the name of the ShutdownFile() function for a given file.
|
// Return the name of the ShutdownFile() function for a given file.
|
||||||
string GlobalShutdownFileName(const string& filename);
|
string GlobalShutdownFileName(const string& filename);
|
||||||
|
|
||||||
|
// Escape C++ trigraphs by escaping question marks to \?
|
||||||
|
string EscapeTrigraphs(const string& to_escape);
|
||||||
|
|
||||||
// Do message classes in this file keep track of unknown fields?
|
// Do message classes in this file keep track of unknown fields?
|
||||||
inline bool HasUnknownFields(const FileDescriptor *file) {
|
inline bool HasUnknownFields(const FileDescriptor* file) {
|
||||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Does this file have any enum type definitions?
|
||||||
|
bool HasEnumDefinitions(const FileDescriptor* file);
|
||||||
|
|
||||||
// Does this file have generated parsing, serialization, and other
|
// Does this file have generated parsing, serialization, and other
|
||||||
// standard methods for which reflection-based fallback implementations exist?
|
// standard methods for which reflection-based fallback implementations exist?
|
||||||
inline bool HasGeneratedMethods(const FileDescriptor *file) {
|
inline bool HasGeneratedMethods(const FileDescriptor* file) {
|
||||||
return file->options().optimize_for() != FileOptions::CODE_SIZE;
|
return file->options().optimize_for() != FileOptions::CODE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do message classes in this file have descriptor and refelction methods?
|
// Do message classes in this file have descriptor and reflection methods?
|
||||||
inline bool HasDescriptorMethods(const FileDescriptor *file) {
|
inline bool HasDescriptorMethods(const FileDescriptor* file) {
|
||||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should we generate generic services for this file?
|
// Should we generate generic services for this file?
|
||||||
inline bool HasGenericServices(const FileDescriptor *file) {
|
inline bool HasGenericServices(const FileDescriptor* file) {
|
||||||
return file->service_count() > 0 &&
|
return file->service_count() > 0 &&
|
||||||
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
|
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
|
||||||
file->options().cc_generic_services();
|
file->options().cc_generic_services();
|
||||||
@ -147,6 +160,23 @@ inline bool HasFastArraySerialization(const FileDescriptor* file) {
|
|||||||
return file->options().optimize_for() == FileOptions::SPEED;
|
return file->options().optimize_for() == FileOptions::SPEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether we have to generate code with static initializers.
|
||||||
|
bool StaticInitializersForced(const FileDescriptor* file);
|
||||||
|
|
||||||
|
// Prints 'with_static_init' if static initializers have to be used for the
|
||||||
|
// provided file. Otherwise emits both 'with_static_init' and
|
||||||
|
// 'without_static_init' using #ifdef.
|
||||||
|
void PrintHandlingOptionalStaticInitializers(
|
||||||
|
const FileDescriptor* file, io::Printer* printer,
|
||||||
|
const char* with_static_init, const char* without_static_init,
|
||||||
|
const char* var1 = NULL, const string& val1 = "",
|
||||||
|
const char* var2 = NULL, const string& val2 = "");
|
||||||
|
|
||||||
|
void PrintHandlingOptionalStaticInitializers(
|
||||||
|
const map<string, string>& vars, const FileDescriptor* file,
|
||||||
|
io::Printer* printer, const char* with_static_init,
|
||||||
|
const char* without_static_init);
|
||||||
|
|
||||||
|
|
||||||
} // namespace cpp
|
} // namespace cpp
|
||||||
} // namespace compiler
|
} // namespace compiler
|
@ -35,6 +35,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <google/protobuf/stubs/hash.h>
|
#include <google/protobuf/stubs/hash.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <google/protobuf/compiler/cpp/cpp_message.h>
|
#include <google/protobuf/compiler/cpp/cpp_message.h>
|
||||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
@ -47,6 +48,7 @@
|
|||||||
#include <google/protobuf/wire_format.h>
|
#include <google/protobuf/wire_format.h>
|
||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
@ -102,6 +104,13 @@ struct ExtensionRangeSorter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns true if the "required" restriction check should be ignored for the
|
||||||
|
// given field.
|
||||||
|
inline static bool ShouldIgnoreRequiredFieldCheck(
|
||||||
|
const FieldDescriptor* field) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if the message type has any required fields. If it doesn't,
|
// Returns true if the message type has any required fields. If it doesn't,
|
||||||
// we can optimize out calls to its IsInitialized() method.
|
// we can optimize out calls to its IsInitialized() method.
|
||||||
//
|
//
|
||||||
@ -128,7 +137,8 @@ static bool HasRequiredFields(
|
|||||||
if (field->is_required()) {
|
if (field->is_required()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
||||||
|
!ShouldIgnoreRequiredFieldCheck(field)) {
|
||||||
if (HasRequiredFields(field->message_type(), already_seen)) {
|
if (HasRequiredFields(field->message_type(), already_seen)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -143,16 +153,147 @@ static bool HasRequiredFields(const Descriptor* type) {
|
|||||||
return HasRequiredFields(type, &already_seen);
|
return HasRequiredFields(type, &already_seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This returns an estimate of the compiler's alignment for the field. This
|
||||||
|
// can't guarantee to be correct because the generated code could be compiled on
|
||||||
|
// different systems with different alignment rules. The estimates below assume
|
||||||
|
// 64-bit pointers.
|
||||||
|
int EstimateAlignmentSize(const FieldDescriptor* field) {
|
||||||
|
if (field == NULL) return 0;
|
||||||
|
if (field->is_repeated()) return 8;
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_BOOL:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_INT32:
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT32:
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_INT64:
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT64:
|
||||||
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return -1; // Make compiler happy.
|
||||||
|
}
|
||||||
|
|
||||||
|
// FieldGroup is just a helper for OptimizePadding below. It holds a vector of
|
||||||
|
// fields that are grouped together because they have compatible alignment, and
|
||||||
|
// a preferred location in the final field ordering.
|
||||||
|
class FieldGroup {
|
||||||
|
public:
|
||||||
|
FieldGroup()
|
||||||
|
: preferred_location_(0) {}
|
||||||
|
|
||||||
|
// A group with a single field.
|
||||||
|
FieldGroup(float preferred_location, const FieldDescriptor* field)
|
||||||
|
: preferred_location_(preferred_location),
|
||||||
|
fields_(1, field) {}
|
||||||
|
|
||||||
|
// Append the fields in 'other' to this group.
|
||||||
|
void Append(const FieldGroup& other) {
|
||||||
|
if (other.fields_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Preferred location is the average among all the fields, so we weight by
|
||||||
|
// the number of fields on each FieldGroup object.
|
||||||
|
preferred_location_ =
|
||||||
|
(preferred_location_ * fields_.size() +
|
||||||
|
(other.preferred_location_ * other.fields_.size())) /
|
||||||
|
(fields_.size() + other.fields_.size());
|
||||||
|
fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPreferredLocation(float location) { preferred_location_ = location; }
|
||||||
|
const vector<const FieldDescriptor*>& fields() const { return fields_; }
|
||||||
|
|
||||||
|
// FieldGroup objects sort by their preferred location.
|
||||||
|
bool operator<(const FieldGroup& other) const {
|
||||||
|
return preferred_location_ < other.preferred_location_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// "preferred_location_" is an estimate of where this group should go in the
|
||||||
|
// final list of fields. We compute this by taking the average index of each
|
||||||
|
// field in this group in the original ordering of fields. This is very
|
||||||
|
// approximate, but should put this group close to where its member fields
|
||||||
|
// originally went.
|
||||||
|
float preferred_location_;
|
||||||
|
vector<const FieldDescriptor*> fields_;
|
||||||
|
// We rely on the default copy constructor and operator= so this type can be
|
||||||
|
// used in a vector.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reorder 'fields' so that if the fields are output into a c++ class in the new
|
||||||
|
// order, the alignment padding is minimized. We try to do this while keeping
|
||||||
|
// each field as close as possible to its original position so that we don't
|
||||||
|
// reduce cache locality much for function that access each field in order.
|
||||||
|
void OptimizePadding(vector<const FieldDescriptor*>* fields) {
|
||||||
|
// First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
|
||||||
|
vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
|
||||||
|
for (int i = 0; i < fields->size(); ++i) {
|
||||||
|
switch (EstimateAlignmentSize((*fields)[i])) {
|
||||||
|
case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
|
||||||
|
case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
|
||||||
|
case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
|
||||||
|
default:
|
||||||
|
GOOGLE_LOG(FATAL) << "Unknown alignment size.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now group fields aligned to 1 byte into sets of 4, and treat those like a
|
||||||
|
// single field aligned to 4 bytes.
|
||||||
|
for (int i = 0; i < aligned_to_1.size(); i += 4) {
|
||||||
|
FieldGroup field_group;
|
||||||
|
for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
|
||||||
|
field_group.Append(aligned_to_1[j]);
|
||||||
|
}
|
||||||
|
aligned_to_4.push_back(field_group);
|
||||||
|
}
|
||||||
|
// Sort by preferred location to keep fields as close to their original
|
||||||
|
// location as possible.
|
||||||
|
sort(aligned_to_4.begin(), aligned_to_4.end());
|
||||||
|
|
||||||
|
// Now group fields aligned to 4 bytes (or the 4-field groups created above)
|
||||||
|
// into pairs, and treat those like a single field aligned to 8 bytes.
|
||||||
|
for (int i = 0; i < aligned_to_4.size(); i += 2) {
|
||||||
|
FieldGroup field_group;
|
||||||
|
for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
|
||||||
|
field_group.Append(aligned_to_4[j]);
|
||||||
|
}
|
||||||
|
if (i == aligned_to_4.size() - 1) {
|
||||||
|
// Move incomplete 4-byte block to the end.
|
||||||
|
field_group.SetPreferredLocation(fields->size() + 1);
|
||||||
|
}
|
||||||
|
aligned_to_8.push_back(field_group);
|
||||||
|
}
|
||||||
|
// Sort by preferred location to keep fields as close to their original
|
||||||
|
// location as possible.
|
||||||
|
sort(aligned_to_8.begin(), aligned_to_8.end());
|
||||||
|
|
||||||
|
// Now pull out all the FieldDescriptors in order.
|
||||||
|
fields->clear();
|
||||||
|
for (int i = 0; i < aligned_to_8.size(); ++i) {
|
||||||
|
fields->insert(fields->end(),
|
||||||
|
aligned_to_8[i].fields().begin(),
|
||||||
|
aligned_to_8[i].fields().end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
|
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
|
||||||
const string& dllexport_decl)
|
const Options& options)
|
||||||
: descriptor_(descriptor),
|
: descriptor_(descriptor),
|
||||||
classname_(ClassName(descriptor, false)),
|
classname_(ClassName(descriptor, false)),
|
||||||
dllexport_decl_(dllexport_decl),
|
options_(options),
|
||||||
field_generators_(descriptor),
|
field_generators_(descriptor, options),
|
||||||
nested_generators_(new scoped_ptr<MessageGenerator>[
|
nested_generators_(new scoped_ptr<MessageGenerator>[
|
||||||
descriptor->nested_type_count()]),
|
descriptor->nested_type_count()]),
|
||||||
enum_generators_(new scoped_ptr<EnumGenerator>[
|
enum_generators_(new scoped_ptr<EnumGenerator>[
|
||||||
@ -162,17 +303,17 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
|
|||||||
|
|
||||||
for (int i = 0; i < descriptor->nested_type_count(); i++) {
|
for (int i = 0; i < descriptor->nested_type_count(); i++) {
|
||||||
nested_generators_[i].reset(
|
nested_generators_[i].reset(
|
||||||
new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
|
new MessageGenerator(descriptor->nested_type(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
||||||
enum_generators_[i].reset(
|
enum_generators_[i].reset(
|
||||||
new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
|
new EnumGenerator(descriptor->enum_type(i), options));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < descriptor->extension_count(); i++) {
|
for (int i = 0; i < descriptor->extension_count(); i++) {
|
||||||
extension_generators_[i].reset(
|
extension_generators_[i].reset(
|
||||||
new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
|
new ExtensionGenerator(descriptor->extension(i), options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +358,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|||||||
PrintFieldComment(printer, field);
|
PrintFieldComment(printer, field);
|
||||||
|
|
||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
SetCommonFieldVariables(field, &vars);
|
SetCommonFieldVariables(field, &vars, options_);
|
||||||
vars["constant_name"] = FieldConstantName(field);
|
vars["constant_name"] = FieldConstantName(field);
|
||||||
|
|
||||||
if (field->is_repeated()) {
|
if (field->is_repeated()) {
|
||||||
@ -254,7 +395,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|||||||
PrintFieldComment(printer, field);
|
PrintFieldComment(printer, field);
|
||||||
|
|
||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
SetCommonFieldVariables(field, &vars);
|
SetCommonFieldVariables(field, &vars, options_);
|
||||||
|
|
||||||
// Generate has_$name$() or $name$_size().
|
// Generate has_$name$() or $name$_size().
|
||||||
if (field->is_repeated()) {
|
if (field->is_repeated()) {
|
||||||
@ -264,10 +405,20 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|||||||
"}\n");
|
"}\n");
|
||||||
} else {
|
} else {
|
||||||
// Singular field.
|
// Singular field.
|
||||||
|
char buffer[kFastToBufferSize];
|
||||||
|
vars["has_array_index"] = SimpleItoa(field->index() / 32);
|
||||||
|
vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"inline bool $classname$::has_$name$() const {\n"
|
"inline bool $classname$::has_$name$() const {\n"
|
||||||
" return _has_bit($index$);\n"
|
" return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
|
||||||
"}\n");
|
"}\n"
|
||||||
|
"inline void $classname$::set_has_$name$() {\n"
|
||||||
|
" _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::clear_has_$name$() {\n"
|
||||||
|
" _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate clear_$name$()
|
// Generate clear_$name$()
|
||||||
@ -279,7 +430,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
|
|
||||||
if (!field->is_repeated()) {
|
if (!field->is_repeated()) {
|
||||||
printer->Print(vars, " _clear_bit($index$);\n");
|
printer->Print(vars,
|
||||||
|
" clear_has_$name$();\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
@ -303,10 +455,10 @@ GenerateClassDefinition(io::Printer* printer) {
|
|||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
vars["classname"] = classname_;
|
vars["classname"] = classname_;
|
||||||
vars["field_count"] = SimpleItoa(descriptor_->field_count());
|
vars["field_count"] = SimpleItoa(descriptor_->field_count());
|
||||||
if (dllexport_decl_.empty()) {
|
if (options_.dllexport_decl.empty()) {
|
||||||
vars["dllexport"] = "";
|
vars["dllexport"] = "";
|
||||||
} else {
|
} else {
|
||||||
vars["dllexport"] = dllexport_decl_ + " ";
|
vars["dllexport"] = options_.dllexport_decl + " ";
|
||||||
}
|
}
|
||||||
vars["superclass"] = SuperClassName(descriptor_);
|
vars["superclass"] = SuperClassName(descriptor_);
|
||||||
|
|
||||||
@ -350,6 +502,20 @@ GenerateClassDefinition(io::Printer* printer) {
|
|||||||
"static const $classname$& default_instance();\n"
|
"static const $classname$& default_instance();\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
|
if (!StaticInitializersForced(descriptor_->file())) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
|
||||||
|
"// Returns the internal default instance pointer. This function can\n"
|
||||||
|
"// return NULL thus should not be used by the user. This is intended\n"
|
||||||
|
"// for Protobuf internal code. Please use default_instance() declared\n"
|
||||||
|
"// above instead.\n"
|
||||||
|
"static inline const $classname$* internal_default_instance() {\n"
|
||||||
|
" return default_instance_;\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"void Swap($classname$* other);\n"
|
"void Swap($classname$* other);\n"
|
||||||
@ -444,38 +610,91 @@ GenerateClassDefinition(io::Printer* printer) {
|
|||||||
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
|
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
|
||||||
"full_name", descriptor_->full_name());
|
"full_name", descriptor_->full_name());
|
||||||
|
|
||||||
// Generate private members for fields.
|
// Generate private members.
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print(" private:\n");
|
printer->Print(" private:\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
|
if (!descriptor_->field(i)->is_repeated()) {
|
||||||
|
printer->Print(
|
||||||
|
"inline void set_has_$name$();\n",
|
||||||
|
"name", FieldName(descriptor_->field(i)));
|
||||||
|
printer->Print(
|
||||||
|
"inline void clear_has_$name$();\n",
|
||||||
|
"name", FieldName(descriptor_->field(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
|
// To minimize padding, data members are divided into three sections:
|
||||||
|
// (1) members assumed to align to 8 bytes
|
||||||
|
// (2) members corresponding to message fields, re-ordered to optimize
|
||||||
|
// alignment.
|
||||||
|
// (3) members assumed to align to 4 bytes.
|
||||||
|
|
||||||
|
// Members assumed to align to 8 bytes:
|
||||||
|
|
||||||
if (descriptor_->extension_range_count() > 0) {
|
if (descriptor_->extension_range_count() > 0) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"::google::protobuf::internal::ExtensionSet _extensions_;\n");
|
"::google::protobuf::internal::ExtensionSet _extensions_;\n"
|
||||||
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasUnknownFields(descriptor_->file())) {
|
if (HasUnknownFields(descriptor_->file())) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
|
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
|
||||||
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Field members:
|
||||||
|
|
||||||
|
vector<const FieldDescriptor*> fields;
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
|
fields.push_back(descriptor_->field(i));
|
||||||
|
}
|
||||||
|
OptimizePadding(&fields);
|
||||||
|
for (int i = 0; i < fields.size(); ++i) {
|
||||||
|
field_generators_.get(fields[i]).GeneratePrivateMembers(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members assumed to align to 4 bytes:
|
||||||
|
|
||||||
// TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
|
// TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"mutable int _cached_size_;\n"
|
"\n"
|
||||||
"\n");
|
"mutable int _cached_size_;\n");
|
||||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
|
||||||
field_generators_.get(descriptor_->field(i))
|
// Generate _has_bits_.
|
||||||
.GeneratePrivateMembers(printer);
|
if (descriptor_->field_count() > 0) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"
|
||||||
|
"\n");
|
||||||
|
} else {
|
||||||
|
// Zero-size arrays aren't technically allowed, and MSVC in particular
|
||||||
|
// doesn't like them. We still need to declare these arrays to make
|
||||||
|
// other code compile. Since this is an uncommon case, we'll just declare
|
||||||
|
// them with size 1 and waste some space. Oh well.
|
||||||
|
printer->Print(
|
||||||
|
"::google::protobuf::uint32 _has_bits_[1];\n"
|
||||||
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
|
// Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
|
||||||
// friends so that they can access private static variables like
|
// friends so that they can access private static variables like
|
||||||
// default_instance_ and reflection_.
|
// default_instance_ and reflection_.
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
"friend void $dllexport_decl$ $adddescriptorsname$();\n",
|
"friend void $dllexport_decl$ $adddescriptorsname$();\n",
|
||||||
"dllexport_decl", dllexport_decl_,
|
// Without.
|
||||||
|
"friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
|
||||||
|
// Vars.
|
||||||
|
"dllexport_decl", options_.dllexport_decl,
|
||||||
"adddescriptorsname",
|
"adddescriptorsname",
|
||||||
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"friend void $assigndescriptorsname$();\n"
|
"friend void $assigndescriptorsname$();\n"
|
||||||
"friend void $shutdownfilename$();\n"
|
"friend void $shutdownfilename$();\n"
|
||||||
@ -484,32 +703,7 @@ GenerateClassDefinition(io::Printer* printer) {
|
|||||||
GlobalAssignDescriptorsName(descriptor_->file()->name()),
|
GlobalAssignDescriptorsName(descriptor_->file()->name()),
|
||||||
"shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
|
"shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
|
||||||
|
|
||||||
// Generate offsets and _has_bits_ boilerplate.
|
|
||||||
if (descriptor_->field_count() > 0) {
|
|
||||||
printer->Print(vars,
|
|
||||||
"::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n");
|
|
||||||
} else {
|
|
||||||
// Zero-size arrays aren't technically allowed, and MSVC in particular
|
|
||||||
// doesn't like them. We still need to declare these arrays to make
|
|
||||||
// other code compile. Since this is an uncommon case, we'll just declare
|
|
||||||
// them with size 1 and waste some space. Oh well.
|
|
||||||
printer->Print(
|
|
||||||
"::google::protobuf::uint32 _has_bits_[1];\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"\n"
|
|
||||||
"// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n"
|
|
||||||
"inline bool _has_bit(int index) const {\n"
|
|
||||||
" return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n"
|
|
||||||
"}\n"
|
|
||||||
"inline void _set_bit(int index) {\n"
|
|
||||||
" _has_bits_[index / 32] |= (1u << (index % 32));\n"
|
|
||||||
"}\n"
|
|
||||||
"inline void _clear_bit(int index) {\n"
|
|
||||||
" _has_bits_[index / 32] &= ~(1u << (index % 32));\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"void InitAsDefaultInstance();\n"
|
"void InitAsDefaultInstance();\n"
|
||||||
"static $classname$* default_instance_;\n",
|
"static $classname$* default_instance_;\n",
|
||||||
"classname", classname_);
|
"classname", classname_);
|
||||||
@ -589,9 +783,11 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
|
|||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
" -1,\n");
|
" -1,\n");
|
||||||
}
|
}
|
||||||
|
printer->Print(
|
||||||
|
" ::google::protobuf::DescriptorPool::generated_pool(),\n");
|
||||||
|
printer->Print(vars,
|
||||||
|
" ::google::protobuf::MessageFactory::generated_factory(),\n");
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
" ::google::protobuf::DescriptorPool::generated_pool(),\n"
|
|
||||||
" ::google::protobuf::MessageFactory::generated_factory(),\n"
|
|
||||||
" sizeof($classname$));\n");
|
" sizeof($classname$));\n");
|
||||||
|
|
||||||
// Handle nested types.
|
// Handle nested types.
|
||||||
@ -620,6 +816,13 @@ GenerateTypeRegistrations(io::Printer* printer) {
|
|||||||
|
|
||||||
void MessageGenerator::
|
void MessageGenerator::
|
||||||
GenerateDefaultInstanceAllocator(io::Printer* printer) {
|
GenerateDefaultInstanceAllocator(io::Printer* printer) {
|
||||||
|
// Construct the default instances of all fields, as they will be used
|
||||||
|
// when creating the default instance of the entire message.
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
|
field_generators_.get(descriptor_->field(i))
|
||||||
|
.GenerateDefaultInstanceAllocator(printer);
|
||||||
|
}
|
||||||
|
|
||||||
// Construct the default instance. We can't call InitAsDefaultInstance() yet
|
// Construct the default instance. We can't call InitAsDefaultInstance() yet
|
||||||
// because we need to make sure all default instances that this one might
|
// because we need to make sure all default instances that this one might
|
||||||
// depend on are constructed first.
|
// depend on are constructed first.
|
||||||
@ -663,6 +866,12 @@ GenerateShutdownCode(io::Printer* printer) {
|
|||||||
"classname", classname_);
|
"classname", classname_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle default instances of fields.
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
|
field_generators_.get(descriptor_->field(i))
|
||||||
|
.GenerateShutdownCode(printer);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle nested types.
|
// Handle nested types.
|
||||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||||
nested_generators_[i]->GenerateShutdownCode(printer);
|
nested_generators_[i]->GenerateShutdownCode(printer);
|
||||||
@ -817,8 +1026,12 @@ GenerateSharedDestructorCode(io::Printer* printer) {
|
|||||||
.GenerateDestructorCode(printer);
|
.GenerateDestructorCode(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
"if (this != default_instance_) {\n");
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
|
"if (this != default_instance_) {\n",
|
||||||
|
// Without.
|
||||||
|
"if (this != &default_instance()) {\n");
|
||||||
|
|
||||||
// We need to delete all embedded messages.
|
// We need to delete all embedded messages.
|
||||||
// TODO(kenton): If we make unset messages point at default instances
|
// TODO(kenton): If we make unset messages point at default instances
|
||||||
@ -870,10 +1083,16 @@ GenerateStructors(io::Printer* printer) {
|
|||||||
|
|
||||||
if (!field->is_repeated() &&
|
if (!field->is_repeated() &&
|
||||||
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
" $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
|
descriptor_->file(), printer,
|
||||||
"name", FieldName(field),
|
// With static initializers.
|
||||||
"type", FieldMessageTypeName(field));
|
" $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
|
||||||
|
// Without.
|
||||||
|
" $name$_ = const_cast< $type$*>(\n"
|
||||||
|
" $type$::internal_default_instance());\n",
|
||||||
|
// Vars.
|
||||||
|
"name", FieldName(field),
|
||||||
|
"type", FieldMessageTypeName(field));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printer->Print(
|
printer->Print(
|
||||||
@ -929,8 +1148,20 @@ GenerateStructors(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"const $classname$& $classname$::default_instance() {\n"
|
"const $classname$& $classname$::default_instance() {\n",
|
||||||
" if (default_instance_ == NULL) $adddescriptorsname$();"
|
"classname", classname_);
|
||||||
|
|
||||||
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
|
" if (default_instance_ == NULL) $adddescriptorsname$();\n",
|
||||||
|
// Without.
|
||||||
|
" $adddescriptorsname$();\n",
|
||||||
|
// Vars.
|
||||||
|
"adddescriptorsname",
|
||||||
|
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
" return *default_instance_;\n"
|
" return *default_instance_;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -942,7 +1173,6 @@ GenerateStructors(io::Printer* printer) {
|
|||||||
"classname", classname_,
|
"classname", classname_,
|
||||||
"adddescriptorsname",
|
"adddescriptorsname",
|
||||||
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageGenerator::
|
void MessageGenerator::
|
||||||
@ -961,9 +1191,6 @@ GenerateClear(io::Printer* printer) {
|
|||||||
const FieldDescriptor* field = descriptor_->field(i);
|
const FieldDescriptor* field = descriptor_->field(i);
|
||||||
|
|
||||||
if (!field->is_repeated()) {
|
if (!field->is_repeated()) {
|
||||||
map<string, string> vars;
|
|
||||||
vars["index"] = SimpleItoa(field->index());
|
|
||||||
|
|
||||||
// We can use the fact that _has_bits_ is a giant bitfield to our
|
// We can use the fact that _has_bits_ is a giant bitfield to our
|
||||||
// advantage: We can check up to 32 bits at a time for equality to
|
// advantage: We can check up to 32 bits at a time for equality to
|
||||||
// zero, and skip the whole range if so. This can improve the speed
|
// zero, and skip the whole range if so. This can improve the speed
|
||||||
@ -975,8 +1202,9 @@ GenerateClear(io::Printer* printer) {
|
|||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
}
|
}
|
||||||
printer->Print(vars,
|
printer->Print(
|
||||||
"if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
|
"if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
|
||||||
|
"index", SimpleItoa(field->index()));
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
}
|
}
|
||||||
last_index = i;
|
last_index = i;
|
||||||
@ -989,7 +1217,9 @@ GenerateClear(io::Printer* printer) {
|
|||||||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
|
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
|
||||||
|
|
||||||
if (should_check_bit) {
|
if (should_check_bit) {
|
||||||
printer->Print(vars, "if (_has_bit($index$)) {\n");
|
printer->Print(
|
||||||
|
"if (has_$name$()) {\n",
|
||||||
|
"name", FieldName(field));
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1129,24 +1359,23 @@ GenerateMergeFrom(io::Printer* printer) {
|
|||||||
const FieldDescriptor* field = descriptor_->field(i);
|
const FieldDescriptor* field = descriptor_->field(i);
|
||||||
|
|
||||||
if (!field->is_repeated()) {
|
if (!field->is_repeated()) {
|
||||||
map<string, string> vars;
|
|
||||||
vars["index"] = SimpleItoa(field->index());
|
|
||||||
|
|
||||||
// See above in GenerateClear for an explanation of this.
|
// See above in GenerateClear for an explanation of this.
|
||||||
if (i / 8 != last_index / 8 || last_index < 0) {
|
if (i / 8 != last_index / 8 || last_index < 0) {
|
||||||
if (last_index >= 0) {
|
if (last_index >= 0) {
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
}
|
}
|
||||||
printer->Print(vars,
|
printer->Print(
|
||||||
"if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
|
"if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
|
||||||
|
"index", SimpleItoa(field->index()));
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
last_index = i;
|
last_index = i;
|
||||||
|
|
||||||
printer->Print(vars,
|
printer->Print(
|
||||||
"if (from._has_bit($index$)) {\n");
|
"if (from.has_$name$()) {\n",
|
||||||
|
"name", FieldName(field));
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
field_generators_.get(field).GenerateMergingCode(printer);
|
field_generators_.get(field).GenerateMergingCode(printer);
|
||||||
@ -1214,11 +1443,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
|||||||
// Special-case MessageSet.
|
// Special-case MessageSet.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"bool $classname$::MergePartialFromCodedStream(\n"
|
"bool $classname$::MergePartialFromCodedStream(\n"
|
||||||
" ::google::protobuf::io::CodedInputStream* input) {\n"
|
" ::google::protobuf::io::CodedInputStream* input) {\n",
|
||||||
" return _extensions_.ParseMessageSet(input, default_instance_,\n"
|
|
||||||
" mutable_unknown_fields());\n"
|
|
||||||
"}\n",
|
|
||||||
"classname", classname_);
|
"classname", classname_);
|
||||||
|
|
||||||
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
|
" return _extensions_.ParseMessageSet(input, default_instance_,\n"
|
||||||
|
" mutable_unknown_fields());\n",
|
||||||
|
// Without.
|
||||||
|
" return _extensions_.ParseMessageSet(input, &default_instance(),\n"
|
||||||
|
" mutable_unknown_fields());\n",
|
||||||
|
// Vars.
|
||||||
|
"classname", classname_);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"}\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1378,12 +1618,21 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
printer->Print(") {\n");
|
printer->Print(") {\n");
|
||||||
if (HasUnknownFields(descriptor_->file())) {
|
if (HasUnknownFields(descriptor_->file())) {
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
" DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
|
" DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
|
||||||
|
" mutable_unknown_fields()));\n",
|
||||||
|
// Without.
|
||||||
|
" DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
|
||||||
" mutable_unknown_fields()));\n");
|
" mutable_unknown_fields()));\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(
|
PrintHandlingOptionalStaticInitializers(
|
||||||
" DO_(_extensions_.ParseField(tag, input, default_instance_));\n");
|
descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
|
" DO_(_extensions_.ParseField(tag, input, default_instance_));\n",
|
||||||
|
// Without.
|
||||||
|
" DO_(_extensions_.ParseField(tag, input, &default_instance()));\n");
|
||||||
}
|
}
|
||||||
printer->Print(
|
printer->Print(
|
||||||
" continue;\n"
|
" continue;\n"
|
||||||
@ -1423,8 +1672,8 @@ void MessageGenerator::GenerateSerializeOneField(
|
|||||||
|
|
||||||
if (!field->is_repeated()) {
|
if (!field->is_repeated()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"if (_has_bit($index$)) {\n",
|
"if (has_$name$()) {\n",
|
||||||
"index", SimpleItoa(field->index()));
|
"name", FieldName(field));
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1734,6 +1983,7 @@ GenerateIsInitialized(io::Printer* printer) {
|
|||||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
const FieldDescriptor* field = descriptor_->field(i);
|
const FieldDescriptor* field = descriptor_->field(i);
|
||||||
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
||||||
|
!ShouldIgnoreRequiredFieldCheck(field) &&
|
||||||
HasRequiredFields(field->message_type())) {
|
HasRequiredFields(field->message_type())) {
|
||||||
if (field->is_repeated()) {
|
if (field->is_repeated()) {
|
||||||
printer->Print(
|
printer->Print(
|
@ -38,6 +38,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -57,7 +58,7 @@ class MessageGenerator {
|
|||||||
public:
|
public:
|
||||||
// See generator.cc for the meaning of dllexport_decl.
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
explicit MessageGenerator(const Descriptor* descriptor,
|
explicit MessageGenerator(const Descriptor* descriptor,
|
||||||
const string& dllexport_decl);
|
const Options& options);
|
||||||
~MessageGenerator();
|
~MessageGenerator();
|
||||||
|
|
||||||
// Header stuff.
|
// Header stuff.
|
||||||
@ -153,7 +154,7 @@ class MessageGenerator {
|
|||||||
|
|
||||||
const Descriptor* descriptor_;
|
const Descriptor* descriptor_;
|
||||||
string classname_;
|
string classname_;
|
||||||
string dllexport_decl_;
|
Options options_;
|
||||||
FieldGeneratorMap field_generators_;
|
FieldGeneratorMap field_generators_;
|
||||||
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
|
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
|
||||||
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
@ -45,8 +45,9 @@ namespace cpp {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables) {
|
map<string, string>* variables,
|
||||||
SetCommonFieldVariables(descriptor, variables);
|
const Options& options) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables, options);
|
||||||
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||||
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
||||||
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
||||||
@ -59,9 +60,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
MessageFieldGenerator::
|
MessageFieldGenerator::
|
||||||
MessageFieldGenerator(const FieldDescriptor* descriptor)
|
MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetMessageVariables(descriptor, &variables_);
|
SetMessageVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageFieldGenerator::~MessageFieldGenerator() {}
|
MessageFieldGenerator::~MessageFieldGenerator() {}
|
||||||
@ -75,19 +77,44 @@ void MessageFieldGenerator::
|
|||||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"inline const $type$& $name$() const$deprecation$;\n"
|
"inline const $type$& $name$() const$deprecation$;\n"
|
||||||
"inline $type$* mutable_$name$()$deprecation$;\n");
|
"inline $type$* mutable_$name$()$deprecation$;\n"
|
||||||
|
"inline $type$* release_$name$()$deprecation$;\n"
|
||||||
|
"inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFieldGenerator::
|
void MessageFieldGenerator::
|
||||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"inline const $type$& $classname$::$name$() const {\n"
|
"inline const $type$& $classname$::$name$() const {\n");
|
||||||
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
|
|
||||||
|
PrintHandlingOptionalStaticInitializers(
|
||||||
|
variables_, descriptor_->file(), printer,
|
||||||
|
// With static initializers.
|
||||||
|
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
|
||||||
|
// Without.
|
||||||
|
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" if ($name$_ == NULL) $name$_ = new $type$;\n"
|
" if ($name$_ == NULL) $name$_ = new $type$;\n"
|
||||||
" return $name$_;\n"
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline $type$* $classname$::release_$name$() {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" $type$* temp = $name$_;\n"
|
||||||
|
" $name$_ = NULL;\n"
|
||||||
|
" return temp;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
|
||||||
|
" delete $name$_;\n"
|
||||||
|
" $name$_ = $name$;\n"
|
||||||
|
" if ($name$) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" } else {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,9 +179,10 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
RepeatedMessageFieldGenerator::
|
RepeatedMessageFieldGenerator::
|
||||||
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
|
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetMessageVariables(descriptor, &variables_);
|
SetMessageVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
||||||
@ -182,7 +210,7 @@ void RepeatedMessageFieldGenerator::
|
|||||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"inline const $type$& $classname$::$name$(int index) const {\n"
|
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||||
" return $name$_.Get(index);\n"
|
" return $name$_.$cppget$(index);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||||
" return $name$_.Mutable(index);\n"
|
" return $name$_.Mutable(index);\n"
|
@ -46,7 +46,8 @@ namespace cpp {
|
|||||||
|
|
||||||
class MessageFieldGenerator : public FieldGenerator {
|
class MessageFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
|
explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~MessageFieldGenerator();
|
~MessageFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
@ -71,7 +72,8 @@ class MessageFieldGenerator : public FieldGenerator {
|
|||||||
|
|
||||||
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~RepeatedMessageFieldGenerator();
|
~RepeatedMessageFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
@ -28,36 +28,31 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// Author: kenton@google.com (Kenton Varda)
|
// Author: rennie@google.com (Jeffrey Rennie)
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
class ZipWriter {
|
// Generator options:
|
||||||
public:
|
struct Options {
|
||||||
ZipWriter(io::ZeroCopyOutputStream* raw_output);
|
Options() : safe_boundary_check(false) {
|
||||||
~ZipWriter();
|
}
|
||||||
|
string dllexport_decl;
|
||||||
bool Write(const string& filename, const string& contents);
|
bool safe_boundary_check;
|
||||||
bool WriteDirectory();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct FileInfo {
|
|
||||||
string name;
|
|
||||||
uint32 offset;
|
|
||||||
uint32 size;
|
|
||||||
uint32 crc32;
|
|
||||||
};
|
|
||||||
|
|
||||||
io::ZeroCopyOutputStream* raw_output_;
|
|
||||||
vector<FileInfo> files_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google
|
} // namespace cpp
|
||||||
} // namespace protobuf
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
|
@ -56,24 +56,24 @@ class TestGenerator : public CodeGenerator {
|
|||||||
|
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
TryInsert("test.pb.h", "includes", output_directory);
|
TryInsert("test.pb.h", "includes", context);
|
||||||
TryInsert("test.pb.h", "namespace_scope", output_directory);
|
TryInsert("test.pb.h", "namespace_scope", context);
|
||||||
TryInsert("test.pb.h", "global_scope", output_directory);
|
TryInsert("test.pb.h", "global_scope", context);
|
||||||
TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory);
|
TryInsert("test.pb.h", "class_scope:foo.Bar", context);
|
||||||
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory);
|
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
|
||||||
|
|
||||||
TryInsert("test.pb.cc", "includes", output_directory);
|
TryInsert("test.pb.cc", "includes", context);
|
||||||
TryInsert("test.pb.cc", "namespace_scope", output_directory);
|
TryInsert("test.pb.cc", "namespace_scope", context);
|
||||||
TryInsert("test.pb.cc", "global_scope", output_directory);
|
TryInsert("test.pb.cc", "global_scope", context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryInsert(const string& filename, const string& insertion_point,
|
void TryInsert(const string& filename, const string& insertion_point,
|
||||||
OutputDirectory* output_directory) const {
|
GeneratorContext* context) const {
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->OpenForInsert(filename, insertion_point));
|
context->OpenForInsert(filename, insertion_point));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||||
}
|
}
|
@ -80,8 +80,9 @@ int FixedSize(FieldDescriptor::Type type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables) {
|
map<string, string>* variables,
|
||||||
SetCommonFieldVariables(descriptor, variables);
|
const Options& options) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables, options);
|
||||||
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
||||||
(*variables)["default"] = DefaultValue(descriptor);
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||||
@ -99,9 +100,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
PrimitiveFieldGenerator::
|
PrimitiveFieldGenerator::
|
||||||
PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetPrimitiveVariables(descriptor, &variables_);
|
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
||||||
@ -125,7 +127,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
|||||||
" return $name$_;\n"
|
" return $name$_;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::set_$name$($type$ value) {\n"
|
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" $name$_ = value;\n"
|
" $name$_ = value;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
@ -156,7 +158,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
|||||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||||
" $type$, $wire_format_field_type$>(\n"
|
" $type$, $wire_format_field_type$>(\n"
|
||||||
" input, &$name$_)));\n"
|
" input, &$name$_)));\n"
|
||||||
"_set_bit($index$);\n");
|
"set_has_$name$();\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimitiveFieldGenerator::
|
void PrimitiveFieldGenerator::
|
||||||
@ -190,9 +192,10 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
RepeatedPrimitiveFieldGenerator::
|
RepeatedPrimitiveFieldGenerator::
|
||||||
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetPrimitiveVariables(descriptor, &variables_);
|
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||||
|
|
||||||
if (descriptor->options().packed()) {
|
if (descriptor->options().packed()) {
|
||||||
variables_["packed_reader"] = "ReadPackedPrimitive";
|
variables_["packed_reader"] = "ReadPackedPrimitive";
|
||||||
@ -366,7 +369,9 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
" total_size += $tag_size$ +\n"
|
" total_size += $tag_size$ +\n"
|
||||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||||
"_$name$_cached_byte_size_ = data_size;\n"
|
"_$name$_cached_byte_size_ = data_size;\n"
|
||||||
|
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||||
"total_size += data_size;\n");
|
"total_size += data_size;\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
@ -46,7 +46,8 @@ namespace cpp {
|
|||||||
|
|
||||||
class PrimitiveFieldGenerator : public FieldGenerator {
|
class PrimitiveFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~PrimitiveFieldGenerator();
|
~PrimitiveFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
@ -71,7 +72,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
|
|||||||
|
|
||||||
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~RepeatedPrimitiveFieldGenerator();
|
~RepeatedPrimitiveFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
@ -43,14 +43,14 @@ namespace compiler {
|
|||||||
namespace cpp {
|
namespace cpp {
|
||||||
|
|
||||||
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
|
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||||
const string& dllexport_decl)
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
vars_["classname"] = descriptor_->name();
|
vars_["classname"] = descriptor_->name();
|
||||||
vars_["full_name"] = descriptor_->full_name();
|
vars_["full_name"] = descriptor_->full_name();
|
||||||
if (dllexport_decl.empty()) {
|
if (options.dllexport_decl.empty()) {
|
||||||
vars_["dllexport"] = "";
|
vars_["dllexport"] = "";
|
||||||
} else {
|
} else {
|
||||||
vars_["dllexport"] = dllexport_decl + " ";
|
vars_["dllexport"] = options.dllexport_decl + " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +38,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@ -55,7 +56,7 @@ class ServiceGenerator {
|
|||||||
public:
|
public:
|
||||||
// See generator.cc for the meaning of dllexport_decl.
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
|
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||||
const string& dllexport_decl);
|
const Options& options);
|
||||||
~ServiceGenerator();
|
~ServiceGenerator();
|
||||||
|
|
||||||
// Header stuff.
|
// Header stuff.
|
@ -46,10 +46,15 @@ namespace cpp {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void SetStringVariables(const FieldDescriptor* descriptor,
|
void SetStringVariables(const FieldDescriptor* descriptor,
|
||||||
map<string, string>* variables) {
|
map<string, string>* variables,
|
||||||
SetCommonFieldVariables(descriptor, variables);
|
const Options& options) {
|
||||||
(*variables)["default"] =
|
SetCommonFieldVariables(descriptor, variables, options);
|
||||||
"\"" + CEscape(descriptor->default_value_string()) + "\"";
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["default_length"] =
|
||||||
|
SimpleItoa(descriptor->default_value_string().length());
|
||||||
|
(*variables)["default_variable"] = descriptor->default_value_string().empty()
|
||||||
|
? "&::google::protobuf::internal::kEmptyString"
|
||||||
|
: "_default_" + FieldName(descriptor) + "_";
|
||||||
(*variables)["pointer_type"] =
|
(*variables)["pointer_type"] =
|
||||||
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
||||||
}
|
}
|
||||||
@ -59,18 +64,20 @@ void SetStringVariables(const FieldDescriptor* descriptor,
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
StringFieldGenerator::
|
StringFieldGenerator::
|
||||||
StringFieldGenerator(const FieldDescriptor* descriptor)
|
StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetStringVariables(descriptor, &variables_);
|
SetStringVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringFieldGenerator::~StringFieldGenerator() {}
|
StringFieldGenerator::~StringFieldGenerator() {}
|
||||||
|
|
||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
GeneratePrivateMembers(io::Printer* printer) const {
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_, "::std::string* $name$_;\n");
|
||||||
"::std::string* $name$_;\n"
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
"static const ::std::string _default_$name$_;\n");
|
printer->Print(variables_, "static ::std::string* $default_variable$;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
@ -105,7 +112,10 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
|||||||
"inline void set_$name$(const char* value)$deprecation$;\n"
|
"inline void set_$name$(const char* value)$deprecation$;\n"
|
||||||
"inline void set_$name$(const $pointer_type$* value, size_t size)"
|
"inline void set_$name$(const $pointer_type$* value, size_t size)"
|
||||||
"$deprecation$;\n"
|
"$deprecation$;\n"
|
||||||
"inline ::std::string* mutable_$name$()$deprecation$;\n");
|
"inline ::std::string* mutable_$name$()$deprecation$;\n"
|
||||||
|
"inline ::std::string* release_$name$()$deprecation$;\n"
|
||||||
|
"inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
|
||||||
|
|
||||||
|
|
||||||
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
@ -121,51 +131,71 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
|||||||
" return *$name$_;\n"
|
" return *$name$_;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
|
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" if ($name$_ == &_default_$name$_) {\n"
|
" if ($name$_ == $default_variable$) {\n"
|
||||||
" $name$_ = new ::std::string;\n"
|
" $name$_ = new ::std::string;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" $name$_->assign(value);\n"
|
" $name$_->assign(value);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline void $classname$::set_$name$(const char* value) {\n"
|
"inline void $classname$::set_$name$(const char* value) {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" if ($name$_ == &_default_$name$_) {\n"
|
" if ($name$_ == $default_variable$) {\n"
|
||||||
" $name$_ = new ::std::string;\n"
|
" $name$_ = new ::std::string;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" $name$_->assign(value);\n"
|
" $name$_->assign(value);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline "
|
"inline "
|
||||||
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
|
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" if ($name$_ == &_default_$name$_) {\n"
|
" if ($name$_ == $default_variable$) {\n"
|
||||||
" $name$_ = new ::std::string;\n"
|
" $name$_ = new ::std::string;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
|
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline ::std::string* $classname$::mutable_$name$() {\n"
|
"inline ::std::string* $classname$::mutable_$name$() {\n"
|
||||||
" _set_bit($index$);\n"
|
" set_has_$name$();\n"
|
||||||
" if ($name$_ == &_default_$name$_) {\n");
|
" if ($name$_ == $default_variable$) {\n");
|
||||||
if (descriptor_->default_value_string().empty()) {
|
if (descriptor_->default_value_string().empty()) {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
" $name$_ = new ::std::string;\n");
|
" $name$_ = new ::std::string;\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
" $name$_ = new ::std::string(_default_$name$_);\n");
|
" $name$_ = new ::std::string(*$default_variable$);\n");
|
||||||
}
|
}
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
" }\n"
|
" }\n"
|
||||||
" return $name$_;\n"
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::std::string* $classname$::release_$name$() {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" if ($name$_ == $default_variable$) {\n"
|
||||||
|
" return NULL;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ::std::string* temp = $name$_;\n"
|
||||||
|
" $name$_ = const_cast< ::std::string*>($default_variable$);\n"
|
||||||
|
" return temp;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||||
|
" if ($name$_ != $default_variable$) {\n"
|
||||||
|
" delete $name$_;\n"
|
||||||
|
" }\n"
|
||||||
|
" if ($name$) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" $name$_ = $name$;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" $name$_ = const_cast< ::std::string*>($default_variable$);\n"
|
||||||
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
|
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
if (descriptor_->default_value_string().empty()) {
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
|
// Initialized in GenerateDefaultInstanceAllocator.
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"const ::std::string $classname$::_default_$name$_;\n");
|
"::std::string* $classname$::$default_variable$ = NULL;\n");
|
||||||
} else {
|
|
||||||
printer->Print(variables_,
|
|
||||||
"const ::std::string $classname$::_default_$name$_($default$);\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,13 +203,13 @@ void StringFieldGenerator::
|
|||||||
GenerateClearingCode(io::Printer* printer) const {
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
if (descriptor_->default_value_string().empty()) {
|
if (descriptor_->default_value_string().empty()) {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"if ($name$_ != &_default_$name$_) {\n"
|
"if ($name$_ != $default_variable$) {\n"
|
||||||
" $name$_->clear();\n"
|
" $name$_->clear();\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"if ($name$_ != &_default_$name$_) {\n"
|
"if ($name$_ != $default_variable$) {\n"
|
||||||
" $name$_->assign(_default_$name$_);\n"
|
" $name$_->assign(*$default_variable$);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,17 +227,34 @@ GenerateSwappingCode(io::Printer* printer) const {
|
|||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
GenerateConstructorCode(io::Printer* printer) const {
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n");
|
"$name$_ = const_cast< ::std::string*>($default_variable$);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
GenerateDestructorCode(io::Printer* printer) const {
|
GenerateDestructorCode(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"if ($name$_ != &_default_$name$_) {\n"
|
"if ($name$_ != $default_variable$) {\n"
|
||||||
" delete $name$_;\n"
|
" delete $name$_;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateDefaultInstanceAllocator(io::Printer* printer) const {
|
||||||
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$classname$::$default_variable$ =\n"
|
||||||
|
" new ::std::string($default$, $default_length$);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateShutdownCode(io::Printer* printer) const {
|
||||||
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"delete $classname$::$default_variable$;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StringFieldGenerator::
|
void StringFieldGenerator::
|
||||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
@ -262,9 +309,10 @@ GenerateByteSize(io::Printer* printer) const {
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
RepeatedStringFieldGenerator::
|
RepeatedStringFieldGenerator::
|
||||||
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
|
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options)
|
||||||
: descriptor_(descriptor) {
|
: descriptor_(descriptor) {
|
||||||
SetStringVariables(descriptor, &variables_);
|
SetStringVariables(descriptor, &variables_, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
||||||
@ -317,7 +365,7 @@ void RepeatedStringFieldGenerator::
|
|||||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||||
" return $name$_.Get(index);\n"
|
" return $name$_.$cppget$(index);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
|
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
|
||||||
" return $name$_.Mutable(index);\n"
|
" return $name$_.Mutable(index);\n"
|
||||||
@ -387,7 +435,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
|||||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
printer->Print(variables_,
|
printer->Print(variables_,
|
||||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
" this->$name$(0).data(), this->$name$(0).length(),\n"
|
" this->$name$(this->$name$_size() - 1).data(),\n"
|
||||||
|
" this->$name$(this->$name$_size() - 1).length(),\n"
|
||||||
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -46,7 +46,8 @@ namespace cpp {
|
|||||||
|
|
||||||
class StringFieldGenerator : public FieldGenerator {
|
class StringFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit StringFieldGenerator(const FieldDescriptor* descriptor);
|
explicit StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~StringFieldGenerator();
|
~StringFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
@ -59,6 +60,8 @@ class StringFieldGenerator : public FieldGenerator {
|
|||||||
void GenerateSwappingCode(io::Printer* printer) const;
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
void GenerateConstructorCode(io::Printer* printer) const;
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
void GenerateDestructorCode(io::Printer* printer) const;
|
void GenerateDestructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
|
||||||
|
void GenerateShutdownCode(io::Printer* printer) const;
|
||||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
@ -73,7 +76,8 @@ class StringFieldGenerator : public FieldGenerator {
|
|||||||
|
|
||||||
class RepeatedStringFieldGenerator : public FieldGenerator {
|
class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const Options& options);
|
||||||
~RepeatedStringFieldGenerator();
|
~RepeatedStringFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
@ -36,6 +36,10 @@
|
|||||||
// though the same identifiers are used internally by the C++ code generator.
|
// though the same identifiers are used internally by the C++ code generator.
|
||||||
|
|
||||||
|
|
||||||
|
// Some generic_services option(s) added automatically.
|
||||||
|
// See: http://go/proto2-generic-services-default
|
||||||
|
option cc_generic_services = true; // auto-added
|
||||||
|
|
||||||
// We don't put this in a package within proto2 because we need to make sure
|
// We don't put this in a package within proto2 because we need to make sure
|
||||||
// that the generated code doesn't depend on being in the proto2 namespace.
|
// that the generated code doesn't depend on being in the proto2 namespace.
|
||||||
package protobuf_unittest;
|
package protobuf_unittest;
|
||||||
@ -99,9 +103,19 @@ message TestConflictingSymbolNames {
|
|||||||
message DO {}
|
message DO {}
|
||||||
optional DO do = 32;
|
optional DO do = 32;
|
||||||
|
|
||||||
|
// Some template parameter names for extensions.
|
||||||
|
optional int32 field_type = 33;
|
||||||
|
optional bool is_packed = 34;
|
||||||
|
|
||||||
extensions 1000 to max;
|
extensions 1000 to max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TestConflictingSymbolNamesExtension {
|
||||||
|
extend TestConflictingSymbolNames {
|
||||||
|
repeated int32 repeated_int32_ext = 20423638 [packed=true];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message DummyMessage {}
|
message DummyMessage {}
|
||||||
|
|
||||||
service TestConflictingMethodNames {
|
service TestConflictingMethodNames {
|
@ -44,6 +44,8 @@
|
|||||||
// correctly and produces the interfaces we expect, which is why this test
|
// correctly and produces the interfaces we expect, which is why this test
|
||||||
// is written this way.
|
// is written this way.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_unittest.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <google/protobuf/unittest.pb.h>
|
#include <google/protobuf/unittest.pb.h>
|
||||||
@ -64,7 +66,7 @@
|
|||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
#include <google/protobuf/testing/googletest.h>
|
#include <google/protobuf/testing/googletest.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <google/protobuf/stubs/stl_util-inl.h>
|
#include <google/protobuf/stubs/stl_util.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -74,6 +76,8 @@ namespace cpp {
|
|||||||
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
|
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
|
||||||
namespace cpp_unittest {
|
namespace cpp_unittest {
|
||||||
|
|
||||||
|
namespace protobuf_unittest = ::protobuf_unittest;
|
||||||
|
|
||||||
|
|
||||||
class MockErrorCollector : public MultiFileErrorCollector {
|
class MockErrorCollector : public MultiFileErrorCollector {
|
||||||
public:
|
public:
|
||||||
@ -167,6 +171,22 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) {
|
|||||||
EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
|
EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, Trigraph) {
|
||||||
|
const unittest::TestExtremeDefaultValues& extreme_default =
|
||||||
|
unittest::TestExtremeDefaultValues::default_instance();
|
||||||
|
|
||||||
|
EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
|
||||||
|
const unittest::TestExtremeDefaultValues& extreme_default =
|
||||||
|
unittest::TestExtremeDefaultValues::default_instance();
|
||||||
|
EXPECT_EQ(-0x80000000, kint32min);
|
||||||
|
EXPECT_EQ(GOOGLE_LONGLONG(-0x8000000000000000), kint64min);
|
||||||
|
EXPECT_EQ(kint32min, extreme_default.really_small_int32());
|
||||||
|
EXPECT_EQ(kint64min, extreme_default.really_small_int64());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(GeneratedMessageTest, Accessors) {
|
TEST(GeneratedMessageTest, Accessors) {
|
||||||
// Set every field to a unique value then go back and check all those
|
// Set every field to a unique value then go back and check all those
|
||||||
// values.
|
// values.
|
||||||
@ -195,6 +215,98 @@ TEST(GeneratedMessageTest, MutableStringDefault) {
|
|||||||
EXPECT_EQ("hello", *message.mutable_default_string());
|
EXPECT_EQ("hello", *message.mutable_default_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, StringDefaults) {
|
||||||
|
unittest::TestExtremeDefaultValues message;
|
||||||
|
// Check if '\000' can be used in default string value.
|
||||||
|
EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
|
||||||
|
EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, ReleaseString) {
|
||||||
|
// Check that release_foo() starts out NULL, and gives us a value
|
||||||
|
// that we can delete after it's been set.
|
||||||
|
unittest::TestAllTypes message;
|
||||||
|
|
||||||
|
EXPECT_EQ(NULL, message.release_default_string());
|
||||||
|
EXPECT_FALSE(message.has_default_string());
|
||||||
|
EXPECT_EQ("hello", message.default_string());
|
||||||
|
|
||||||
|
message.set_default_string("blah");
|
||||||
|
EXPECT_TRUE(message.has_default_string());
|
||||||
|
string* str = message.release_default_string();
|
||||||
|
EXPECT_FALSE(message.has_default_string());
|
||||||
|
ASSERT_TRUE(str != NULL);
|
||||||
|
EXPECT_EQ("blah", *str);
|
||||||
|
delete str;
|
||||||
|
|
||||||
|
EXPECT_EQ(NULL, message.release_default_string());
|
||||||
|
EXPECT_FALSE(message.has_default_string());
|
||||||
|
EXPECT_EQ("hello", message.default_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, ReleaseMessage) {
|
||||||
|
// Check that release_foo() starts out NULL, and gives us a value
|
||||||
|
// that we can delete after it's been set.
|
||||||
|
unittest::TestAllTypes message;
|
||||||
|
|
||||||
|
EXPECT_EQ(NULL, message.release_optional_nested_message());
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
|
||||||
|
message.mutable_optional_nested_message()->set_bb(1);
|
||||||
|
unittest::TestAllTypes::NestedMessage* nest =
|
||||||
|
message.release_optional_nested_message();
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
ASSERT_TRUE(nest != NULL);
|
||||||
|
EXPECT_EQ(1, nest->bb());
|
||||||
|
delete nest;
|
||||||
|
|
||||||
|
EXPECT_EQ(NULL, message.release_optional_nested_message());
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, SetAllocatedString) {
|
||||||
|
// Check that set_allocated_foo() works for strings.
|
||||||
|
unittest::TestAllTypes message;
|
||||||
|
|
||||||
|
EXPECT_FALSE(message.has_optional_string());
|
||||||
|
const string kHello("hello");
|
||||||
|
message.set_optional_string(kHello);
|
||||||
|
EXPECT_TRUE(message.has_optional_string());
|
||||||
|
|
||||||
|
message.set_allocated_optional_string(NULL);
|
||||||
|
EXPECT_FALSE(message.has_optional_string());
|
||||||
|
EXPECT_EQ("", message.optional_string());
|
||||||
|
|
||||||
|
message.set_allocated_optional_string(new string(kHello));
|
||||||
|
EXPECT_TRUE(message.has_optional_string());
|
||||||
|
EXPECT_EQ(kHello, message.optional_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GeneratedMessageTest, SetAllocatedMessage) {
|
||||||
|
// Check that set_allocated_foo() can be called in all cases.
|
||||||
|
unittest::TestAllTypes message;
|
||||||
|
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
|
||||||
|
message.mutable_optional_nested_message()->set_bb(1);
|
||||||
|
EXPECT_TRUE(message.has_optional_nested_message());
|
||||||
|
|
||||||
|
message.set_allocated_optional_nested_message(NULL);
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
|
||||||
|
&message.optional_nested_message());
|
||||||
|
|
||||||
|
message.mutable_optional_nested_message()->set_bb(1);
|
||||||
|
unittest::TestAllTypes::NestedMessage* nest =
|
||||||
|
message.release_optional_nested_message();
|
||||||
|
ASSERT_TRUE(nest != NULL);
|
||||||
|
EXPECT_FALSE(message.has_optional_nested_message());
|
||||||
|
|
||||||
|
message.set_allocated_optional_nested_message(nest);
|
||||||
|
EXPECT_TRUE(message.has_optional_nested_message());
|
||||||
|
EXPECT_EQ(1, message.optional_nested_message().bb());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(GeneratedMessageTest, Clear) {
|
TEST(GeneratedMessageTest, Clear) {
|
||||||
// Set every field to a unique value, clear the message, then check that
|
// Set every field to a unique value, clear the message, then check that
|
||||||
// it is cleared.
|
// it is cleared.
|
||||||
@ -269,7 +381,6 @@ TEST(GeneratedMessageTest, StringCharStarLength) {
|
|||||||
EXPECT_EQ("wx", message.repeated_string(0));
|
EXPECT_EQ("wx", message.repeated_string(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(GeneratedMessageTest, CopyFrom) {
|
TEST(GeneratedMessageTest, CopyFrom) {
|
||||||
unittest::TestAllTypes message1, message2;
|
unittest::TestAllTypes message1, message2;
|
||||||
|
|
||||||
@ -376,10 +487,12 @@ TEST(GeneratedMessageTest, CopyAssignmentOperator) {
|
|||||||
TestUtil::ExpectAllFieldsSet(message2);
|
TestUtil::ExpectAllFieldsSet(message2);
|
||||||
|
|
||||||
// Make sure that self-assignment does something sane.
|
// Make sure that self-assignment does something sane.
|
||||||
message2 = message2;
|
message2.operator=(message2);
|
||||||
TestUtil::ExpectAllFieldsSet(message2);
|
TestUtil::ExpectAllFieldsSet(message2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
|
||||||
|
!defined(GOOGLE_PROTOBUF_NO_RTTI)
|
||||||
TEST(GeneratedMessageTest, UpcastCopyFrom) {
|
TEST(GeneratedMessageTest, UpcastCopyFrom) {
|
||||||
// Test the CopyFrom method that takes in the generic const Message&
|
// Test the CopyFrom method that takes in the generic const Message&
|
||||||
// parameter.
|
// parameter.
|
||||||
@ -392,6 +505,7 @@ TEST(GeneratedMessageTest, UpcastCopyFrom) {
|
|||||||
|
|
||||||
TestUtil::ExpectAllFieldsSet(message2);
|
TestUtil::ExpectAllFieldsSet(message2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
|
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
|
||||||
|
|
||||||
@ -443,7 +557,9 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
|
|||||||
TestUtil::ExpectAllFieldsSet(message1);
|
TestUtil::ExpectAllFieldsSet(message1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GTEST_HAS_DEATH_TEST
|
#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
|
||||||
|
!defined(GOOGLE_PROTOBUF_NO_RTTI)
|
||||||
|
#ifdef PROTOBUF_HAS_DEATH_TEST
|
||||||
|
|
||||||
TEST(GeneratedMessageTest, MergeFromSelf) {
|
TEST(GeneratedMessageTest, MergeFromSelf) {
|
||||||
unittest::TestAllTypes message;
|
unittest::TestAllTypes message;
|
||||||
@ -452,7 +568,8 @@ TEST(GeneratedMessageTest, MergeFromSelf) {
|
|||||||
"&from");
|
"&from");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
|
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI
|
||||||
|
|
||||||
// Test the generated SerializeWithCachedSizesToArray(),
|
// Test the generated SerializeWithCachedSizesToArray(),
|
||||||
TEST(GeneratedMessageTest, SerializationToArray) {
|
TEST(GeneratedMessageTest, SerializationToArray) {
|
||||||
@ -645,6 +762,13 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
|
|||||||
|
|
||||||
message.set_friend_(5);
|
message.set_friend_(5);
|
||||||
EXPECT_EQ(5, message.friend_());
|
EXPECT_EQ(5, message.friend_());
|
||||||
|
|
||||||
|
// Instantiate extension template functions to test conflicting template
|
||||||
|
// parameter names.
|
||||||
|
typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
|
||||||
|
message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
|
||||||
|
EXPECT_EQ(123,
|
||||||
|
message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
|
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
|
||||||
@ -718,6 +842,7 @@ TEST(GeneratedMessageTest, TestSpaceUsed) {
|
|||||||
|
|
||||||
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
|
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
|
||||||
|
|
||||||
|
|
||||||
TEST(GeneratedMessageTest, FieldConstantValues) {
|
TEST(GeneratedMessageTest, FieldConstantValues) {
|
||||||
unittest::TestRequired message;
|
unittest::TestRequired message;
|
||||||
EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
|
EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
|
||||||
@ -809,20 +934,19 @@ TEST(GeneratedEnumTest, MinAndMax) {
|
|||||||
EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
|
EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
|
||||||
|
|
||||||
// Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
|
// Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
|
||||||
void* nullptr = 0; // NULL may be integer-type, not pointer-type.
|
void* null_pointer = 0; // NULL may be integer-type, not pointer-type.
|
||||||
EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MIN);
|
EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN);
|
||||||
EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MAX);
|
EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX);
|
||||||
EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
|
EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
|
||||||
|
|
||||||
EXPECT_NE(nullptr, &unittest::ForeignEnum_MIN);
|
EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN);
|
||||||
EXPECT_NE(nullptr, &unittest::ForeignEnum_MAX);
|
EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
|
||||||
EXPECT_NE(nullptr, &unittest::ForeignEnum_ARRAYSIZE);
|
EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
|
||||||
|
|
||||||
// Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
|
// Make sure we can use _MIN and _MAX as switch cases.
|
||||||
switch (unittest::SPARSE_A) {
|
switch (unittest::SPARSE_A) {
|
||||||
case unittest::TestSparseEnum_MIN:
|
case unittest::TestSparseEnum_MIN:
|
||||||
case unittest::TestSparseEnum_MAX:
|
case unittest::TestSparseEnum_MAX:
|
||||||
case unittest::TestSparseEnum_ARRAYSIZE:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1079,7 +1203,7 @@ TEST_F(GeneratedServiceTest, CallMethod) {
|
|||||||
TEST_F(GeneratedServiceTest, CallMethodTypeFailure) {
|
TEST_F(GeneratedServiceTest, CallMethodTypeFailure) {
|
||||||
// Verify death if we call Foo() with Bar's message types.
|
// Verify death if we call Foo() with Bar's message types.
|
||||||
|
|
||||||
#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet
|
#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet
|
||||||
EXPECT_DEBUG_DEATH(
|
EXPECT_DEBUG_DEATH(
|
||||||
mock_service_.CallMethod(foo_, &mock_controller_,
|
mock_service_.CallMethod(foo_, &mock_controller_,
|
||||||
&foo_request_, &bar_response_, done_.get()),
|
&foo_request_, &bar_response_, done_.get()),
|
||||||
@ -1090,7 +1214,7 @@ TEST_F(GeneratedServiceTest, CallMethodTypeFailure) {
|
|||||||
mock_service_.CallMethod(foo_, &mock_controller_,
|
mock_service_.CallMethod(foo_, &mock_controller_,
|
||||||
&bar_request_, &foo_response_, done_.get()),
|
&bar_request_, &foo_response_, done_.get()),
|
||||||
"dynamic_cast");
|
"dynamic_cast");
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GeneratedServiceTest, GetPrototypes) {
|
TEST_F(GeneratedServiceTest, GetPrototypes) {
|
@ -0,0 +1,51 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
|
||||||
|
// any problems with the generated class names. We use this header to ensure
|
||||||
|
// unittest.cc will declare the namespace prior to other includes, while obeying
|
||||||
|
// normal include ordering.
|
||||||
|
//
|
||||||
|
// When generating a class name of "foo.Bar" we must ensure we prefix the class
|
||||||
|
// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
|
||||||
|
// trigger that case here by declaring google::protobuf::protobuf_unittest.
|
||||||
|
//
|
||||||
|
// See ClassName in helpers.h for more details.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace protobuf_unittest {}
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
|
@ -231,7 +231,12 @@ static string CanonicalizePath(string path) {
|
|||||||
// The Win32 API accepts forward slashes as a path delimiter even though
|
// The Win32 API accepts forward slashes as a path delimiter even though
|
||||||
// backslashes are standard. Let's avoid confusion and use only forward
|
// backslashes are standard. Let's avoid confusion and use only forward
|
||||||
// slashes.
|
// slashes.
|
||||||
path = StringReplace(path, "\\", "/", true);
|
if (HasPrefixString(path, "\\\\")) {
|
||||||
|
// Avoid converting two leading backslashes.
|
||||||
|
path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true);
|
||||||
|
} else {
|
||||||
|
path = StringReplace(path, "\\", "/", true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vector<string> parts;
|
vector<string> parts;
|
@ -280,8 +280,9 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
|
|||||||
string virtual_path;
|
string virtual_path;
|
||||||
string disk_path;
|
string disk_path;
|
||||||
|
|
||||||
inline Mapping(const string& virtual_path, const string& disk_path)
|
inline Mapping(const string& virtual_path_param,
|
||||||
: virtual_path(virtual_path), disk_path(disk_path) {}
|
const string& disk_path_param)
|
||||||
|
: virtual_path(virtual_path_param), disk_path(disk_path_param) {}
|
||||||
};
|
};
|
||||||
vector<Mapping> mappings_;
|
vector<Mapping> mappings_;
|
||||||
|
|
@ -0,0 +1,236 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
string EscapeJavadoc(const string& input) {
|
||||||
|
string result;
|
||||||
|
result.reserve(input.size() * 2);
|
||||||
|
|
||||||
|
char prev = '*';
|
||||||
|
|
||||||
|
for (string::size_type i = 0; i < input.size(); i++) {
|
||||||
|
char c = input[i];
|
||||||
|
switch (c) {
|
||||||
|
case '*':
|
||||||
|
// Avoid "/*".
|
||||||
|
if (prev == '/') {
|
||||||
|
result.append("*");
|
||||||
|
} else {
|
||||||
|
result.push_back(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
// Avoid "*/".
|
||||||
|
if (prev == '*') {
|
||||||
|
result.append("/");
|
||||||
|
} else {
|
||||||
|
result.push_back(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
// "{@" starts Javadoc markup.
|
||||||
|
if (prev == '{') {
|
||||||
|
result.append("@");
|
||||||
|
} else {
|
||||||
|
result.push_back(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
// Avoid interpretation as HTML.
|
||||||
|
result.append("<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
// Avoid interpretation as HTML.
|
||||||
|
result.append(">");
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
// Avoid interpretation as HTML.
|
||||||
|
result.append("&");
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
// Java interprets Unicode escape sequences anywhere!
|
||||||
|
result.append("\");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.push_back(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteDocCommentBodyForLocation(
|
||||||
|
io::Printer* printer, const SourceLocation& location) {
|
||||||
|
string comments = location.leading_comments.empty() ?
|
||||||
|
location.trailing_comments : location.leading_comments;
|
||||||
|
if (!comments.empty()) {
|
||||||
|
// TODO(kenton): Ideally we should parse the comment text as Markdown and
|
||||||
|
// write it back as HTML, but this requires a Markdown parser. For now
|
||||||
|
// we just use <pre> to get fixed-width text formatting.
|
||||||
|
|
||||||
|
// If the comment itself contains block comment start or end markers,
|
||||||
|
// HTML-escape them so that they don't accidentally close the doc comment.
|
||||||
|
comments = EscapeJavadoc(comments);
|
||||||
|
|
||||||
|
vector<string> lines;
|
||||||
|
SplitStringAllowEmpty(comments, "\n", &lines);
|
||||||
|
while (!lines.empty() && lines.back().empty()) {
|
||||||
|
lines.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
" *\n"
|
||||||
|
" * <pre>\n");
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
// Most lines should start with a space. Watch out for lines that start
|
||||||
|
// with a /, since putting that right after the leading asterisk will
|
||||||
|
// close the comment.
|
||||||
|
if (!lines[i].empty() && lines[i][0] == '/') {
|
||||||
|
printer->Print(" * $line$\n", "line", lines[i]);
|
||||||
|
} else {
|
||||||
|
printer->Print(" *$line$\n", "line", lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printer->Print(" * </pre>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename DescriptorType>
|
||||||
|
static void WriteDocCommentBody(
|
||||||
|
io::Printer* printer, const DescriptorType* descriptor) {
|
||||||
|
SourceLocation location;
|
||||||
|
if (descriptor->GetSourceLocation(&location)) {
|
||||||
|
WriteDocCommentBodyForLocation(printer, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FirstLineOf(const string& value) {
|
||||||
|
string result = value;
|
||||||
|
|
||||||
|
string::size_type pos = result.find_first_of('\n');
|
||||||
|
if (pos != string::npos) {
|
||||||
|
result.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If line ends in an opening brace, make it "{ ... }" so it looks nice.
|
||||||
|
if (!result.empty() && result[result.size() - 1] == '{') {
|
||||||
|
result.append(" ... }");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * Protobuf type {@code $fullname$}\n",
|
||||||
|
"fullname", EscapeJavadoc(message->full_name()));
|
||||||
|
WriteDocCommentBody(printer, message);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
|
||||||
|
// In theory we should have slightly different comments for setters, getters,
|
||||||
|
// etc., but in practice everyone already knows the difference between these
|
||||||
|
// so it's redundant information.
|
||||||
|
|
||||||
|
// We use the field declaration as the first line of the comment, e.g.:
|
||||||
|
// optional string foo = 5;
|
||||||
|
// This communicates a lot of information about the field in a small space.
|
||||||
|
// If the field is a group, the debug string might end with {.
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * <code>$def$</code>\n",
|
||||||
|
"def", EscapeJavadoc(FirstLineOf(field->DebugString())));
|
||||||
|
WriteDocCommentBody(printer, field);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * Protobuf enum {@code $fullname$}\n",
|
||||||
|
"fullname", EscapeJavadoc(enum_->full_name()));
|
||||||
|
WriteDocCommentBody(printer, enum_);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteEnumValueDocComment(io::Printer* printer,
|
||||||
|
const EnumValueDescriptor* value) {
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * <code>$def$</code>\n",
|
||||||
|
"def", EscapeJavadoc(FirstLineOf(value->DebugString())));
|
||||||
|
WriteDocCommentBody(printer, value);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteServiceDocComment(io::Printer* printer,
|
||||||
|
const ServiceDescriptor* service) {
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * Protobuf service {@code $fullname$}\n",
|
||||||
|
"fullname", EscapeJavadoc(service->full_name()));
|
||||||
|
WriteDocCommentBody(printer, service);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMethodDocComment(io::Printer* printer,
|
||||||
|
const MethodDescriptor* method) {
|
||||||
|
printer->Print(
|
||||||
|
"/**\n"
|
||||||
|
" * <code>$def$</code>\n",
|
||||||
|
"def", EscapeJavadoc(FirstLineOf(method->DebugString())));
|
||||||
|
WriteDocCommentBody(printer, method);
|
||||||
|
printer->Print(" */\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,69 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
|
||||||
|
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
class Printer; // printer.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
|
||||||
|
void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
|
||||||
|
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
|
||||||
|
void WriteEnumValueDocComment(io::Printer* printer,
|
||||||
|
const EnumValueDescriptor* value);
|
||||||
|
void WriteServiceDocComment(io::Printer* printer,
|
||||||
|
const ServiceDescriptor* service);
|
||||||
|
void WriteMethodDocComment(io::Printer* printer,
|
||||||
|
const MethodDescriptor* method);
|
||||||
|
|
||||||
|
// Exposed for testing only.
|
||||||
|
LIBPROTOC_EXPORT string EscapeJavadoc(const string& input);
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
|
@ -0,0 +1,66 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(JavaDocCommentTest, Escaping) {
|
||||||
|
EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz"));
|
||||||
|
EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz"));
|
||||||
|
EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}"));
|
||||||
|
EXPECT_EQ("<i>&</i>", EscapeJavadoc("<i>&</i>"));
|
||||||
|
EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(kenton): It's hard to write a robust test of the doc comments -- we
|
||||||
|
// can only really compare the output against a golden value, which is a
|
||||||
|
// fairly tedious and fragile testing strategy. If we want to go that route,
|
||||||
|
// it probably makes sense to bite the bullet and write a test that compares
|
||||||
|
// the whole generated output for unittest.proto against a golden value, with
|
||||||
|
// a very simple script that can be run to regenerate it with the latest code.
|
||||||
|
// This would mean that updates to the golden file would have to be included
|
||||||
|
// in any change to the code generator, which would actually be fairly useful
|
||||||
|
// as it allows the reviewer to see clearly how the generated code is
|
||||||
|
// changing.
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -36,6 +36,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_enum.h>
|
#include <google/protobuf/compiler/java/java_enum.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
@ -67,6 +68,7 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
|
|||||||
EnumGenerator::~EnumGenerator() {}
|
EnumGenerator::~EnumGenerator() {}
|
||||||
|
|
||||||
void EnumGenerator::Generate(io::Printer* printer) {
|
void EnumGenerator::Generate(io::Printer* printer) {
|
||||||
|
WriteEnumDocComment(printer, descriptor_);
|
||||||
if (HasDescriptorMethods(descriptor_)) {
|
if (HasDescriptorMethods(descriptor_)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"public enum $classname$\n"
|
"public enum $classname$\n"
|
||||||
@ -85,6 +87,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
vars["name"] = canonical_values_[i]->name();
|
vars["name"] = canonical_values_[i]->name();
|
||||||
vars["index"] = SimpleItoa(canonical_values_[i]->index());
|
vars["index"] = SimpleItoa(canonical_values_[i]->index());
|
||||||
vars["number"] = SimpleItoa(canonical_values_[i]->number());
|
vars["number"] = SimpleItoa(canonical_values_[i]->number());
|
||||||
|
WriteEnumValueDocComment(printer, canonical_values_[i]);
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"$name$($index$, $number$),\n");
|
"$name$($index$, $number$),\n");
|
||||||
}
|
}
|
||||||
@ -100,10 +103,21 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
vars["classname"] = descriptor_->name();
|
vars["classname"] = descriptor_->name();
|
||||||
vars["name"] = aliases_[i].value->name();
|
vars["name"] = aliases_[i].value->name();
|
||||||
vars["canonical_name"] = aliases_[i].canonical_value->name();
|
vars["canonical_name"] = aliases_[i].canonical_value->name();
|
||||||
|
WriteEnumValueDocComment(printer, aliases_[i].value);
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"public static final $classname$ $name$ = $canonical_name$;\n");
|
"public static final $classname$ $name$ = $canonical_name$;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["name"] = descriptor_->value(i)->name();
|
||||||
|
vars["number"] = SimpleItoa(descriptor_->value(i)->number());
|
||||||
|
WriteEnumValueDocComment(printer, descriptor_->value(i));
|
||||||
|
printer->Print(vars,
|
||||||
|
"public static final int $name$_VALUE = $number$;\n");
|
||||||
|
}
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
@ -138,7 +152,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
" internalValueMap =\n"
|
" internalValueMap =\n"
|
||||||
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
|
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
|
||||||
" public $classname$ findValueByNumber(int number) {\n"
|
" public $classname$ findValueByNumber(int number) {\n"
|
||||||
" return $classname$.valueOf(number)\n;"
|
" return $classname$.valueOf(number);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
"\n",
|
"\n",
|
||||||
@ -178,18 +192,30 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
printer->Print(
|
printer->Print(
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"private static final $classname$[] VALUES = {\n"
|
"private static final $classname$[] VALUES = ",
|
||||||
" ",
|
|
||||||
"classname", descriptor_->name());
|
"classname", descriptor_->name());
|
||||||
|
|
||||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
if (CanUseEnumValues()) {
|
||||||
printer->Print("$name$, ",
|
// If the constants we are going to output are exactly the ones we
|
||||||
"name", descriptor_->value(i)->name());
|
// have declared in the Java enum in the same order, then we can use
|
||||||
|
// the values() method that the Java compiler automatically generates
|
||||||
|
// for every enum.
|
||||||
|
printer->Print("values();\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(
|
||||||
|
"{\n"
|
||||||
|
" ");
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
printer->Print("$name$, ",
|
||||||
|
"name", descriptor_->value(i)->name());
|
||||||
|
}
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"\n"
|
"\n"
|
||||||
"};\n"
|
|
||||||
"public static $classname$ valueOf(\n"
|
"public static $classname$ valueOf(\n"
|
||||||
" com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
|
" com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
|
||||||
" if (desc.getType() != getDescriptor()) {\n"
|
" if (desc.getType() != getDescriptor()) {\n"
|
||||||
@ -197,31 +223,26 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
" \"EnumValueDescriptor is not for this type.\");\n"
|
" \"EnumValueDescriptor is not for this type.\");\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" return VALUES[desc.getIndex()];\n"
|
" return VALUES[desc.getIndex()];\n"
|
||||||
"}\n",
|
"}\n"
|
||||||
|
"\n",
|
||||||
"classname", descriptor_->name());
|
"classname", descriptor_->name());
|
||||||
|
|
||||||
|
// index is only used for reflection; lite implementation does not need it
|
||||||
|
printer->Print("private final int index;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"private final int index;\n"
|
"private final int value;\n\n"
|
||||||
"private final int value;\n"
|
"private $classname$(int index, int value) {\n",
|
||||||
"private $classname$(int index, int value) {\n"
|
|
||||||
" this.index = index;\n"
|
|
||||||
" this.value = value;\n"
|
|
||||||
"}\n",
|
|
||||||
"classname", descriptor_->name());
|
"classname", descriptor_->name());
|
||||||
|
|
||||||
if (HasDescriptorMethods(descriptor_)) {
|
if (HasDescriptorMethods(descriptor_)) {
|
||||||
// Force the static initialization code for the file to run, since it may
|
printer->Print(" this.index = index;\n");
|
||||||
// initialize static variables declared in this class.
|
|
||||||
printer->Print(
|
|
||||||
"\n"
|
|
||||||
"static {\n"
|
|
||||||
" $file$.getDescriptor();\n"
|
|
||||||
"}\n",
|
|
||||||
"file", ClassName(descriptor_->file()));
|
|
||||||
}
|
}
|
||||||
|
printer->Print(
|
||||||
|
" this.value = value;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"\n"
|
"\n"
|
||||||
@ -232,6 +253,18 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
|||||||
printer->Print("}\n\n");
|
printer->Print("}\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EnumGenerator::CanUseEnumValues() {
|
||||||
|
if (canonical_values_.size() != descriptor_->value_count()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace java
|
} // namespace java
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
@ -73,6 +73,8 @@ class EnumGenerator {
|
|||||||
};
|
};
|
||||||
vector<Alias> aliases_;
|
vector<Alias> aliases_;
|
||||||
|
|
||||||
|
bool CanUseEnumValues();
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||||
};
|
};
|
||||||
|
|
@ -0,0 +1,603 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_enum_field.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||||
|
// repeat code between this and the other field types.
|
||||||
|
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
(*variables)["name"] =
|
||||||
|
UnderscoresToCamelCase(descriptor);
|
||||||
|
(*variables)["capitalized_name"] =
|
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||||
|
(*variables)["constant_name"] = FieldConstantName(descriptor);
|
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
|
(*variables)["type"] = ClassName(descriptor->enum_type());
|
||||||
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||||
|
(*variables)["tag_size"] = SimpleItoa(
|
||||||
|
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
||||||
|
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
|
||||||
|
// by the proto compiler
|
||||||
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
|
? "@java.lang.Deprecated " : "";
|
||||||
|
(*variables)["on_changed"] =
|
||||||
|
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
|
||||||
|
|
||||||
|
// For singular messages and builders, one bit is used for the hasField bit.
|
||||||
|
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_has_field_bit_builder"] =
|
||||||
|
GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repated builders, one bit is used for whether the array is immutable.
|
||||||
|
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repeated fields, one bit is used for whether the array is immutable
|
||||||
|
// in the parsing constructor.
|
||||||
|
(*variables)["get_mutable_bit_parser"] =
|
||||||
|
GenerateGetBitMutableLocal(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_parser"] =
|
||||||
|
GenerateSetBitMutableLocal(builderBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_from_local"] =
|
||||||
|
GenerateGetBitFromLocal(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_to_local"] =
|
||||||
|
GenerateSetBitToLocal(messageBitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
EnumFieldGenerator::
|
||||||
|
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||||
|
|
||||||
|
int EnumFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EnumFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$boolean has$capitalized_name$();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $type$ $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_message$;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $type$ $name$_ = $default$;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_builder$;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
|
||||||
|
" if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
" }\n"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $clear_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = $default$;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for enums
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = $default$;\n"
|
||||||
|
"$clear_has_field_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (other.has$capitalized_name$()) {\n"
|
||||||
|
" set$capitalized_name$(other.get$capitalized_name$());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_from_local$) {\n"
|
||||||
|
" $set_has_field_bit_to_local$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int rawValue = input.readEnum();\n"
|
||||||
|
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||||
|
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||||
|
"} else {\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (value != null) {\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $set_has_field_bit_message$;\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
// noop for enums
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" output.writeEnum($number$, $name$_.getNumber());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeEnumSize($number$, $name$_.getNumber());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result &&\n"
|
||||||
|
" (get$capitalized_name$() == other.get$capitalized_name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
"hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string EnumFieldGenerator::GetBoxedType() const {
|
||||||
|
return ClassName(descriptor_->enum_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator::
|
||||||
|
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||||
|
|
||||||
|
int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$int get$capitalized_name$Count();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$(int index);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private java.util.List<$type$> $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
|
||||||
|
" return $name$_;\n" // note: unmodifiable list
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed() &&
|
||||||
|
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private int $name$MemoizedSerializedSize;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
// One field is the list and the other field keeps track of whether the
|
||||||
|
// list is immutable. If it's immutable, the invariant is that it must
|
||||||
|
// either an instance of Collections.emptyList() or it's an ArrayList
|
||||||
|
// wrapped in a Collections.unmodifiableList() wrapper and nobody else has
|
||||||
|
// a refererence to the underlying ArrayList. This invariant allows us to
|
||||||
|
// share instances of lists between protocol buffers avoiding expensive
|
||||||
|
// memory allocations. Note, immutable is a strong guarantee here -- not
|
||||||
|
// just that the list cannot be modified via the reference but that the
|
||||||
|
// list can never be modified.
|
||||||
|
"private java.util.List<$type$> $name$_ =\n"
|
||||||
|
" java.util.Collections.emptyList();\n"
|
||||||
|
|
||||||
|
"private void ensure$capitalized_name$IsMutable() {\n"
|
||||||
|
" if (!$get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
|
||||||
|
" $set_mutable_bit_builder$;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
// Note: We return an unmodifiable list because otherwise the caller
|
||||||
|
// could hold on to the returned list and modify it after the message
|
||||||
|
// has been built, thus mutating the message which is supposed to be
|
||||||
|
// immutable.
|
||||||
|
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
|
||||||
|
" return java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" int index, $type$ value) {\n"
|
||||||
|
" if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
" }\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.set(index, value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
|
||||||
|
" if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
" }\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.add(value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder addAll$capitalized_name$(\n"
|
||||||
|
" java.lang.Iterable<? extends $type$> values) {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" super.addAll(values, $name$_);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $name$_ = java.util.Collections.emptyList();\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for enums
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = java.util.Collections.emptyList();\n"
|
||||||
|
"$clear_mutable_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
// The code below does two optimizations:
|
||||||
|
// 1. If the other list is empty, there's nothing to do. This ensures we
|
||||||
|
// don't allocate a new array if we already have an immutable one.
|
||||||
|
// 2. If the other list is non-empty and our current list is empty, we can
|
||||||
|
// reuse the other list which is guaranteed to be immutable.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!other.$name$_.isEmpty()) {\n"
|
||||||
|
" if ($name$_.isEmpty()) {\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.addAll(other.$name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
// The code below ensures that the result has an immutable list. If our
|
||||||
|
// list is immutable, we can just reuse it. If not, we make it immutable.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
// Read and store the enum
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int rawValue = input.readEnum();\n"
|
||||||
|
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||||
|
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||||
|
"} else {\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (value != null) {\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" if (!$get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$type$>();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
" }\n"
|
||||||
|
" $name$_.add(value);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
||||||
|
// Wrap GenerateParsingCode's contents with a while loop.
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int length = input.readRawVarint32();\n"
|
||||||
|
"int oldLimit = input.pushLimit(length);\n"
|
||||||
|
"while(input.getBytesUntilLimit() > 0) {\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
GenerateParsingCode(printer);
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(variables_,
|
||||||
|
"}\n"
|
||||||
|
"input.popLimit(oldLimit);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$List().size() > 0) {\n"
|
||||||
|
" output.writeRawVarint32($tag$);\n"
|
||||||
|
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
||||||
|
"}\n"
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.writeEnumNoTag($name$_.get(i).getNumber());\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.writeEnum($number$, $name$_.get(i).getNumber());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"{\n"
|
||||||
|
" int dataSize = 0;\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(
|
||||||
|
"size += dataSize;\n");
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!get$capitalized_name$List().isEmpty()) {"
|
||||||
|
" size += $tag_size$;\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeRawVarint32Size(dataSize);\n"
|
||||||
|
"}");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"size += $tag_size$ * $name$_.size();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the data size for packed fields.
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$MemoizedSerializedSize = dataSize;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$List()\n"
|
||||||
|
" .equals(other.get$capitalized_name$List());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$Count() > 0) {\n"
|
||||||
|
" hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
" hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string RepeatedEnumFieldGenerator::GetBoxedType() const {
|
||||||
|
return ClassName(descriptor_->enum_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -46,49 +46,71 @@ namespace java {
|
|||||||
|
|
||||||
class EnumFieldGenerator : public FieldGenerator {
|
class EnumFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
|
explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~EnumFieldGenerator();
|
~EnumFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~RepeatedEnumFieldGenerator();
|
~RepeatedEnumFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
||||||
};
|
};
|
@ -33,6 +33,7 @@
|
|||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_extension.h>
|
#include <google/protobuf/compiler/java/java_extension.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
@ -86,105 +87,121 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor)
|
|||||||
|
|
||||||
ExtensionGenerator::~ExtensionGenerator() {}
|
ExtensionGenerator::~ExtensionGenerator() {}
|
||||||
|
|
||||||
void ExtensionGenerator::Generate(io::Printer* printer) {
|
// Initializes the vars referenced in the generated code templates.
|
||||||
map<string, string> vars;
|
void InitTemplateVars(const FieldDescriptor* descriptor,
|
||||||
vars["name"] = UnderscoresToCamelCase(descriptor_);
|
const string& scope,
|
||||||
vars["containing_type"] = ClassName(descriptor_->containing_type());
|
map<string, string>* vars_pointer) {
|
||||||
vars["number"] = SimpleItoa(descriptor_->number());
|
map<string, string> &vars = *vars_pointer;
|
||||||
vars["constant_name"] = FieldConstantName(descriptor_);
|
vars["scope"] = scope;
|
||||||
vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
|
vars["name"] = UnderscoresToCamelCase(descriptor);
|
||||||
|
vars["containing_type"] = ClassName(descriptor->containing_type());
|
||||||
JavaType java_type = GetJavaType(descriptor_);
|
vars["number"] = SimpleItoa(descriptor->number());
|
||||||
string singular_type;
|
vars["constant_name"] = FieldConstantName(descriptor);
|
||||||
switch (java_type) {
|
vars["index"] = SimpleItoa(descriptor->index());
|
||||||
case JAVATYPE_MESSAGE:
|
vars["default"] =
|
||||||
vars["type"] = ClassName(descriptor_->message_type());
|
descriptor->is_repeated() ? "" : DefaultValue(descriptor);
|
||||||
break;
|
vars["type_constant"] = TypeName(GetType(descriptor));
|
||||||
case JAVATYPE_ENUM:
|
vars["packed"] = descriptor->options().packed() ? "true" : "false";
|
||||||
vars["type"] = ClassName(descriptor_->enum_type());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vars["type"] = BoxedPrimitiveTypeName(java_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Print(vars,
|
|
||||||
"public static final int $constant_name$ = $number$;\n");
|
|
||||||
if (descriptor_->is_repeated()) {
|
|
||||||
printer->Print(vars,
|
|
||||||
"public static final\n"
|
|
||||||
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
|
|
||||||
" $containing_type$,\n"
|
|
||||||
" java.util.List<$type$>> $name$ =\n"
|
|
||||||
" com.google.protobuf.GeneratedMessage$lite$\n"
|
|
||||||
" .newGeneratedExtension();\n");
|
|
||||||
} else {
|
|
||||||
printer->Print(vars,
|
|
||||||
"public static final\n"
|
|
||||||
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
|
|
||||||
" $containing_type$,\n"
|
|
||||||
" $type$> $name$ =\n"
|
|
||||||
" com.google.protobuf.GeneratedMessage$lite$\n"
|
|
||||||
" .newGeneratedExtension();\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
|
|
||||||
map<string, string> vars;
|
|
||||||
vars["name"] = UnderscoresToCamelCase(descriptor_);
|
|
||||||
vars["scope"] = scope_;
|
|
||||||
vars["index"] = SimpleItoa(descriptor_->index());
|
|
||||||
vars["extendee"] = ClassName(descriptor_->containing_type());
|
|
||||||
vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
|
|
||||||
vars["number"] = SimpleItoa(descriptor_->number());
|
|
||||||
vars["type_constant"] = TypeName(GetType(descriptor_));
|
|
||||||
vars["packed"] = descriptor_->options().packed() ? "true" : "false";
|
|
||||||
vars["enum_map"] = "null";
|
vars["enum_map"] = "null";
|
||||||
vars["prototype"] = "null";
|
vars["prototype"] = "null";
|
||||||
|
|
||||||
JavaType java_type = GetJavaType(descriptor_);
|
JavaType java_type = GetJavaType(descriptor);
|
||||||
string singular_type;
|
string singular_type;
|
||||||
switch (java_type) {
|
switch (java_type) {
|
||||||
case JAVATYPE_MESSAGE:
|
case JAVATYPE_MESSAGE:
|
||||||
vars["type"] = ClassName(descriptor_->message_type());
|
singular_type = ClassName(descriptor->message_type());
|
||||||
vars["prototype"] = ClassName(descriptor_->message_type()) +
|
vars["prototype"] = singular_type + ".getDefaultInstance()";
|
||||||
".getDefaultInstance()";
|
|
||||||
break;
|
break;
|
||||||
case JAVATYPE_ENUM:
|
case JAVATYPE_ENUM:
|
||||||
vars["type"] = ClassName(descriptor_->enum_type());
|
singular_type = ClassName(descriptor->enum_type());
|
||||||
vars["enum_map"] = ClassName(descriptor_->enum_type()) +
|
vars["enum_map"] = singular_type + ".internalGetValueMap()";
|
||||||
".internalGetValueMap()";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vars["type"] = BoxedPrimitiveTypeName(java_type);
|
singular_type = BoxedPrimitiveTypeName(java_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
vars["type"] = descriptor->is_repeated() ?
|
||||||
|
"java.util.List<" + singular_type + ">" : singular_type;
|
||||||
|
vars["singular_type"] = singular_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtensionGenerator::Generate(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
InitTemplateVars(descriptor_, scope_, &vars);
|
||||||
|
printer->Print(vars,
|
||||||
|
"public static final int $constant_name$ = $number$;\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
if (HasDescriptorMethods(descriptor_->file())) {
|
if (HasDescriptorMethods(descriptor_->file())) {
|
||||||
printer->Print(vars,
|
// Non-lite extensions
|
||||||
"$scope$.$name$.internalInit(\n"
|
if (descriptor_->extension_scope() == NULL) {
|
||||||
" $scope$.getDescriptor().getExtensions().get($index$),\n"
|
// Non-nested
|
||||||
" $type$.class);\n");
|
printer->Print(
|
||||||
} else {
|
vars,
|
||||||
if (descriptor_->is_repeated()) {
|
"public static final\n"
|
||||||
printer->Print(vars,
|
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||||
"$scope$.$name$.internalInitRepeated(\n"
|
" $containing_type$,\n"
|
||||||
" $extendee$.getDefaultInstance(),\n"
|
" $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
|
||||||
" $prototype$,\n"
|
" .newFileScopedGeneratedExtension(\n"
|
||||||
" $enum_map$,\n"
|
" $singular_type$.class,\n"
|
||||||
" $number$,\n"
|
" $prototype$);\n");
|
||||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
|
|
||||||
" $packed$);\n");
|
|
||||||
} else {
|
} else {
|
||||||
printer->Print(vars,
|
// Nested
|
||||||
"$scope$.$name$.internalInitSingular(\n"
|
printer->Print(
|
||||||
" $extendee$.getDefaultInstance(),\n"
|
vars,
|
||||||
" $default$,\n"
|
"public static final\n"
|
||||||
" $prototype$,\n"
|
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||||
" $enum_map$,\n"
|
" $containing_type$,\n"
|
||||||
" $number$,\n"
|
" $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
|
||||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
|
" .newMessageScopedGeneratedExtension(\n"
|
||||||
|
" $scope$.getDefaultInstance(),\n"
|
||||||
|
" $index$,\n"
|
||||||
|
" $singular_type$.class,\n"
|
||||||
|
" $prototype$);\n");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Lite extensions
|
||||||
|
if (descriptor_->is_repeated()) {
|
||||||
|
printer->Print(
|
||||||
|
vars,
|
||||||
|
"public static final\n"
|
||||||
|
" com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
|
||||||
|
" $containing_type$,\n"
|
||||||
|
" $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
|
||||||
|
" .newRepeatedGeneratedExtension(\n"
|
||||||
|
" $containing_type$.getDefaultInstance(),\n"
|
||||||
|
" $prototype$,\n"
|
||||||
|
" $enum_map$,\n"
|
||||||
|
" $number$,\n"
|
||||||
|
" com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
|
||||||
|
" $packed$);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(
|
||||||
|
vars,
|
||||||
|
"public static final\n"
|
||||||
|
" com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
|
||||||
|
" $containing_type$,\n"
|
||||||
|
" $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
|
||||||
|
" .newSingularGeneratedExtension(\n"
|
||||||
|
" $containing_type$.getDefaultInstance(),\n"
|
||||||
|
" $default$,\n"
|
||||||
|
" $prototype$,\n"
|
||||||
|
" $enum_map$,\n"
|
||||||
|
" $number$,\n"
|
||||||
|
" com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateNonNestedInitializationCode(
|
||||||
|
io::Printer* printer) {
|
||||||
|
if (descriptor_->extension_scope() == NULL &&
|
||||||
|
HasDescriptorMethods(descriptor_->file())) {
|
||||||
|
// Only applies to non-nested, non-lite extensions.
|
||||||
|
printer->Print(
|
||||||
|
"$name$.internalInit(descriptor.getExtensions().get($index$));\n",
|
||||||
|
"name", UnderscoresToCamelCase(descriptor_),
|
||||||
|
"index", SimpleItoa(descriptor_->index()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ class ExtensionGenerator {
|
|||||||
~ExtensionGenerator();
|
~ExtensionGenerator();
|
||||||
|
|
||||||
void Generate(io::Printer* printer);
|
void Generate(io::Printer* printer);
|
||||||
void GenerateInitializationCode(io::Printer* printer);
|
void GenerateNonNestedInitializationCode(io::Printer* printer);
|
||||||
void GenerateRegistrationCode(io::Printer* printer);
|
void GenerateRegistrationCode(io::Printer* printer);
|
||||||
|
|
||||||
private:
|
private:
|
@ -37,6 +37,7 @@
|
|||||||
#include <google/protobuf/compiler/java/java_primitive_field.h>
|
#include <google/protobuf/compiler/java/java_primitive_field.h>
|
||||||
#include <google/protobuf/compiler/java/java_enum_field.h>
|
#include <google/protobuf/compiler/java/java_enum_field.h>
|
||||||
#include <google/protobuf/compiler/java/java_message_field.h>
|
#include <google/protobuf/compiler/java/java_message_field.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_string_field.h>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@ -63,33 +64,57 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
|
|||||||
extension_generators_(
|
extension_generators_(
|
||||||
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
|
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
|
||||||
|
|
||||||
// Construct all the FieldGenerators.
|
// Construct all the FieldGenerators and assign them bit indices for their
|
||||||
|
// bit fields.
|
||||||
|
int messageBitIndex = 0;
|
||||||
|
int builderBitIndex = 0;
|
||||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
|
FieldGenerator* generator = MakeGenerator(descriptor->field(i),
|
||||||
|
messageBitIndex, builderBitIndex);
|
||||||
|
field_generators_[i].reset(generator);
|
||||||
|
messageBitIndex += generator->GetNumBitsForMessage();
|
||||||
|
builderBitIndex += generator->GetNumBitsForBuilder();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < descriptor->extension_count(); i++) {
|
for (int i = 0; i < descriptor->extension_count(); i++) {
|
||||||
extension_generators_[i].reset(MakeGenerator(descriptor->extension(i)));
|
FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
|
||||||
|
messageBitIndex, builderBitIndex);
|
||||||
|
extension_generators_[i].reset(generator);
|
||||||
|
messageBitIndex += generator->GetNumBitsForMessage();
|
||||||
|
builderBitIndex += generator->GetNumBitsForBuilder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
|
FieldGenerator* FieldGeneratorMap::MakeGenerator(
|
||||||
|
const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
|
||||||
if (field->is_repeated()) {
|
if (field->is_repeated()) {
|
||||||
switch (GetJavaType(field)) {
|
switch (GetJavaType(field)) {
|
||||||
case JAVATYPE_MESSAGE:
|
case JAVATYPE_MESSAGE:
|
||||||
return new RepeatedMessageFieldGenerator(field);
|
return new RepeatedMessageFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
case JAVATYPE_ENUM:
|
case JAVATYPE_ENUM:
|
||||||
return new RepeatedEnumFieldGenerator(field);
|
return new RepeatedEnumFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
|
case JAVATYPE_STRING:
|
||||||
|
return new RepeatedStringFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
default:
|
default:
|
||||||
return new RepeatedPrimitiveFieldGenerator(field);
|
return new RepeatedPrimitiveFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (GetJavaType(field)) {
|
switch (GetJavaType(field)) {
|
||||||
case JAVATYPE_MESSAGE:
|
case JAVATYPE_MESSAGE:
|
||||||
return new MessageFieldGenerator(field);
|
return new MessageFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
case JAVATYPE_ENUM:
|
case JAVATYPE_ENUM:
|
||||||
return new EnumFieldGenerator(field);
|
return new EnumFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
|
case JAVATYPE_STRING:
|
||||||
|
return new StringFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
default:
|
default:
|
||||||
return new PrimitiveFieldGenerator(field);
|
return new PrimitiveFieldGenerator(
|
||||||
|
field, messageBitIndex, builderBitIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -55,15 +55,25 @@ class FieldGenerator {
|
|||||||
FieldGenerator() {}
|
FieldGenerator() {}
|
||||||
virtual ~FieldGenerator();
|
virtual ~FieldGenerator();
|
||||||
|
|
||||||
|
virtual int GetNumBitsForMessage() const = 0;
|
||||||
|
virtual int GetNumBitsForBuilder() const = 0;
|
||||||
|
virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateMembers(io::Printer* printer) const = 0;
|
virtual void GenerateMembers(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
|
virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
|
virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
|
||||||
|
virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
|
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
|
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
||||||
|
virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
|
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
|
||||||
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
|
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
|
||||||
|
virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
|
||||||
|
const = 0;
|
||||||
|
|
||||||
|
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
|
||||||
|
virtual void GenerateHashCode(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
virtual string GetBoxedType() const = 0;
|
virtual string GetBoxedType() const = 0;
|
||||||
|
|
||||||
@ -85,7 +95,8 @@ class FieldGeneratorMap {
|
|||||||
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
||||||
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
|
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
|
||||||
|
|
||||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
|
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||||
};
|
};
|
@ -42,6 +42,7 @@
|
|||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/dynamic_message.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@ -51,18 +52,24 @@ namespace java {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Recursively searches the given message to see if it contains any extensions.
|
|
||||||
bool UsesExtensions(const Message& message) {
|
// Recursively searches the given message to collect extensions.
|
||||||
|
// Returns true if all the extensions can be recognized. The extensions will be
|
||||||
|
// appended in to the extensions parameter.
|
||||||
|
// Returns false when there are unknown fields, in which case the data in the
|
||||||
|
// extensions output parameter is not reliable and should be discarded.
|
||||||
|
bool CollectExtensions(const Message& message,
|
||||||
|
vector<const FieldDescriptor*>* extensions) {
|
||||||
const Reflection* reflection = message.GetReflection();
|
const Reflection* reflection = message.GetReflection();
|
||||||
|
|
||||||
// We conservatively assume that unknown fields are extensions.
|
// There are unknown fields that could be extensions, thus this call fails.
|
||||||
if (reflection->GetUnknownFields(message).field_count() > 0) return true;
|
if (reflection->GetUnknownFields(message).field_count() > 0) return false;
|
||||||
|
|
||||||
vector<const FieldDescriptor*> fields;
|
vector<const FieldDescriptor*> fields;
|
||||||
reflection->ListFields(message, &fields);
|
reflection->ListFields(message, &fields);
|
||||||
|
|
||||||
for (int i = 0; i < fields.size(); i++) {
|
for (int i = 0; i < fields.size(); i++) {
|
||||||
if (fields[i]->is_extension()) return true;
|
if (fields[i]->is_extension()) extensions->push_back(fields[i]);
|
||||||
|
|
||||||
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
|
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
|
||||||
if (fields[i]->is_repeated()) {
|
if (fields[i]->is_repeated()) {
|
||||||
@ -70,16 +77,56 @@ bool UsesExtensions(const Message& message) {
|
|||||||
for (int j = 0; j < size; j++) {
|
for (int j = 0; j < size; j++) {
|
||||||
const Message& sub_message =
|
const Message& sub_message =
|
||||||
reflection->GetRepeatedMessage(message, fields[i], j);
|
reflection->GetRepeatedMessage(message, fields[i], j);
|
||||||
if (UsesExtensions(sub_message)) return true;
|
if (!CollectExtensions(sub_message, extensions)) return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const Message& sub_message = reflection->GetMessage(message, fields[i]);
|
const Message& sub_message = reflection->GetMessage(message, fields[i]);
|
||||||
if (UsesExtensions(sub_message)) return true;
|
if (!CollectExtensions(sub_message, extensions)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds all extensions in the given message and its sub-messages. If the
|
||||||
|
// message contains unknown fields (which could be extensions), then those
|
||||||
|
// extensions are defined in alternate_pool.
|
||||||
|
// The message will be converted to a DynamicMessage backed by alternate_pool
|
||||||
|
// in order to handle this case.
|
||||||
|
void CollectExtensions(const FileDescriptorProto& file_proto,
|
||||||
|
const DescriptorPool& alternate_pool,
|
||||||
|
vector<const FieldDescriptor*>* extensions,
|
||||||
|
const string& file_data) {
|
||||||
|
if (!CollectExtensions(file_proto, extensions)) {
|
||||||
|
// There are unknown fields in the file_proto, which are probably
|
||||||
|
// extensions. We need to parse the data into a dynamic message based on the
|
||||||
|
// builder-pool to find out all extensions.
|
||||||
|
const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
|
||||||
|
file_proto.GetDescriptor()->full_name());
|
||||||
|
GOOGLE_CHECK(file_proto_desc)
|
||||||
|
<< "Find unknown fields in FileDescriptorProto when building "
|
||||||
|
<< file_proto.name()
|
||||||
|
<< ". It's likely that those fields are custom options, however, "
|
||||||
|
"descriptor.proto is not in the transitive dependencies. "
|
||||||
|
"This normally should not happen. Please report a bug.";
|
||||||
|
DynamicMessageFactory factory;
|
||||||
|
scoped_ptr<Message> dynamic_file_proto(
|
||||||
|
factory.GetPrototype(file_proto_desc)->New());
|
||||||
|
GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
|
||||||
|
GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
|
||||||
|
|
||||||
|
// Collect the extensions again from the dynamic message. There should be no
|
||||||
|
// more unknown fields this time, i.e. all the custom options should be
|
||||||
|
// parsed as extensions now.
|
||||||
|
extensions->clear();
|
||||||
|
GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
|
||||||
|
<< "Find unknown fields in FileDescriptorProto when building "
|
||||||
|
<< file_proto.name()
|
||||||
|
<< ". It's likely that those fields are custom options, however, "
|
||||||
|
"those options cannot be recognized in the builder pool. "
|
||||||
|
"This normally should not happen. Please report a bug.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +135,8 @@ bool UsesExtensions(const Message& message) {
|
|||||||
FileGenerator::FileGenerator(const FileDescriptor* file)
|
FileGenerator::FileGenerator(const FileDescriptor* file)
|
||||||
: file_(file),
|
: file_(file),
|
||||||
java_package_(FileJavaPackage(file)),
|
java_package_(FileJavaPackage(file)),
|
||||||
classname_(FileClassName(file)) {}
|
classname_(FileClassName(file)) {
|
||||||
|
}
|
||||||
|
|
||||||
FileGenerator::~FileGenerator() {}
|
FileGenerator::~FileGenerator() {}
|
||||||
|
|
||||||
@ -179,7 +227,9 @@ void FileGenerator::Generate(io::Printer* printer) {
|
|||||||
EnumGenerator(file_->enum_type(i)).Generate(printer);
|
EnumGenerator(file_->enum_type(i)).Generate(printer);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
MessageGenerator(file_->message_type(i)).Generate(printer);
|
MessageGenerator messageGenerator(file_->message_type(i));
|
||||||
|
messageGenerator.GenerateInterface(printer);
|
||||||
|
messageGenerator.Generate(printer);
|
||||||
}
|
}
|
||||||
if (HasGenericServices(file_)) {
|
if (HasGenericServices(file_)) {
|
||||||
for (int i = 0; i < file_->service_count(); i++) {
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
@ -215,24 +265,11 @@ void FileGenerator::Generate(io::Printer* printer) {
|
|||||||
.GenerateStaticVariableInitializers(printer);
|
.GenerateStaticVariableInitializers(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file_->extension_count(); i++) {
|
|
||||||
// TODO(kenton): Reuse ExtensionGenerator objects?
|
|
||||||
ExtensionGenerator(file_->extension(i))
|
|
||||||
.GenerateInitializationCode(printer);
|
|
||||||
}
|
|
||||||
|
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dummy function we can use to force the static initialization block to
|
|
||||||
// run. Needed by inner classes. Cannot be private due to
|
|
||||||
// java_multiple_files option.
|
|
||||||
printer->Print(
|
|
||||||
"\n"
|
|
||||||
"public static void internalForceInit() {}\n");
|
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"\n"
|
"\n"
|
||||||
"// @@protoc_insertion_point(outer_class_scope)\n");
|
"// @@protoc_insertion_point(outer_class_scope)\n");
|
||||||
@ -310,24 +347,38 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
|
|||||||
MessageGenerator(file_->message_type(i))
|
MessageGenerator(file_->message_type(i))
|
||||||
.GenerateStaticVariableInitializers(printer);
|
.GenerateStaticVariableInitializers(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file_->extension_count(); i++) {
|
for (int i = 0; i < file_->extension_count(); i++) {
|
||||||
// TODO(kenton): Reuse ExtensionGenerator objects?
|
// TODO(kenton): Reuse ExtensionGenerator objects?
|
||||||
ExtensionGenerator(file_->extension(i))
|
ExtensionGenerator(file_->extension(i))
|
||||||
.GenerateInitializationCode(printer);
|
.GenerateNonNestedInitializationCode(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UsesExtensions(file_proto)) {
|
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
|
||||||
// Must construct an ExtensionRegistry containing all possible extensions
|
// generate, when processing the ".proto" files. We call this DescriptorPool
|
||||||
|
// the parsed pool (a.k.a. file_->pool()).
|
||||||
|
//
|
||||||
|
// Note that when users try to extend the (.*)DescriptorProto in their
|
||||||
|
// ".proto" files, it does not affect the pre-built FileDescriptorProto class
|
||||||
|
// in proto compiler. When we put the descriptor data in the file_proto, those
|
||||||
|
// extensions become unknown fields.
|
||||||
|
//
|
||||||
|
// Now we need to find out all the extension value to the (.*)DescriptorProto
|
||||||
|
// in the file_proto message, and prepare an ExtensionRegistry to return.
|
||||||
|
//
|
||||||
|
// To find those extensions, we need to parse the data into a dynamic message
|
||||||
|
// of the FileDescriptor based on the builder-pool, then we can use
|
||||||
|
// reflections to find all extension fields
|
||||||
|
vector<const FieldDescriptor*> extensions;
|
||||||
|
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
|
||||||
|
|
||||||
|
if (extensions.size() > 0) {
|
||||||
|
// Must construct an ExtensionRegistry containing all existing extensions
|
||||||
// and return it.
|
// and return it.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"com.google.protobuf.ExtensionRegistry registry =\n"
|
"com.google.protobuf.ExtensionRegistry registry =\n"
|
||||||
" com.google.protobuf.ExtensionRegistry.newInstance();\n"
|
" com.google.protobuf.ExtensionRegistry.newInstance();\n");
|
||||||
"registerAllExtensions(registry);\n");
|
for (int i = 0; i < extensions.size(); i++) {
|
||||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
|
||||||
printer->Print(
|
|
||||||
"$dependency$.registerAllExtensions(registry);\n",
|
|
||||||
"dependency", ClassName(file_->dependency(i)));
|
|
||||||
}
|
}
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"return registry;\n");
|
"return registry;\n");
|
||||||
@ -372,18 +423,21 @@ template<typename GeneratorClass, typename DescriptorClass>
|
|||||||
static void GenerateSibling(const string& package_dir,
|
static void GenerateSibling(const string& package_dir,
|
||||||
const string& java_package,
|
const string& java_package,
|
||||||
const DescriptorClass* descriptor,
|
const DescriptorClass* descriptor,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
vector<string>* file_list) {
|
vector<string>* file_list,
|
||||||
string filename = package_dir + descriptor->name() + ".java";
|
const string& name_suffix,
|
||||||
|
void (GeneratorClass::*pfn)(io::Printer* printer)) {
|
||||||
|
string filename = package_dir + descriptor->name() + name_suffix + ".java";
|
||||||
file_list->push_back(filename);
|
file_list->push_back(filename);
|
||||||
|
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||||
output_directory->Open(filename));
|
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
|
|
||||||
printer.Print(
|
printer.Print(
|
||||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||||
"\n");
|
"// source: $filename$\n"
|
||||||
|
"\n",
|
||||||
|
"filename", descriptor->file()->name());
|
||||||
if (!java_package.empty()) {
|
if (!java_package.empty()) {
|
||||||
printer.Print(
|
printer.Print(
|
||||||
"package $package$;\n"
|
"package $package$;\n"
|
||||||
@ -391,28 +445,36 @@ static void GenerateSibling(const string& package_dir,
|
|||||||
"package", java_package);
|
"package", java_package);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorClass(descriptor).Generate(&printer);
|
GeneratorClass generator(descriptor);
|
||||||
|
(generator.*pfn)(&printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileGenerator::GenerateSiblings(const string& package_dir,
|
void FileGenerator::GenerateSiblings(const string& package_dir,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
vector<string>* file_list) {
|
vector<string>* file_list) {
|
||||||
if (file_->options().java_multiple_files()) {
|
if (file_->options().java_multiple_files()) {
|
||||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
GenerateSibling<EnumGenerator>(package_dir, java_package_,
|
GenerateSibling<EnumGenerator>(package_dir, java_package_,
|
||||||
file_->enum_type(i),
|
file_->enum_type(i),
|
||||||
output_directory, file_list);
|
context, file_list, "",
|
||||||
|
&EnumGenerator::Generate);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
GenerateSibling<MessageGenerator>(package_dir, java_package_,
|
GenerateSibling<MessageGenerator>(package_dir, java_package_,
|
||||||
file_->message_type(i),
|
file_->message_type(i),
|
||||||
output_directory, file_list);
|
context, file_list, "OrBuilder",
|
||||||
|
&MessageGenerator::GenerateInterface);
|
||||||
|
GenerateSibling<MessageGenerator>(package_dir, java_package_,
|
||||||
|
file_->message_type(i),
|
||||||
|
context, file_list, "",
|
||||||
|
&MessageGenerator::Generate);
|
||||||
}
|
}
|
||||||
if (HasGenericServices(file_)) {
|
if (HasGenericServices(file_)) {
|
||||||
for (int i = 0; i < file_->service_count(); i++) {
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
GenerateSibling<ServiceGenerator>(package_dir, java_package_,
|
GenerateSibling<ServiceGenerator>(package_dir, java_package_,
|
||||||
file_->service(i),
|
file_->service(i),
|
||||||
output_directory, file_list);
|
context, file_list, "",
|
||||||
|
&ServiceGenerator::Generate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -46,7 +46,7 @@ namespace protobuf {
|
|||||||
class Printer; // printer.h
|
class Printer; // printer.h
|
||||||
}
|
}
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
class OutputDirectory; // code_generator.h
|
class GeneratorContext; // code_generator.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,12 +70,13 @@ class FileGenerator {
|
|||||||
// files other than the outer file (i.e. one for each message, enum, and
|
// files other than the outer file (i.e. one for each message, enum, and
|
||||||
// service type).
|
// service type).
|
||||||
void GenerateSiblings(const string& package_dir,
|
void GenerateSiblings(const string& package_dir,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
vector<string>* file_list);
|
vector<string>* file_list);
|
||||||
|
|
||||||
const string& java_package() { return java_package_; }
|
const string& java_package() { return java_package_; }
|
||||||
const string& classname() { return classname_; }
|
const string& classname() { return classname_; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns whether the dependency should be included in the output file.
|
// Returns whether the dependency should be included in the output file.
|
||||||
// Always returns true for opensource, but used internally at Google to help
|
// Always returns true for opensource, but used internally at Google to help
|
||||||
@ -86,6 +87,7 @@ class FileGenerator {
|
|||||||
string java_package_;
|
string java_package_;
|
||||||
string classname_;
|
string classname_;
|
||||||
|
|
||||||
|
|
||||||
void GenerateEmbeddedDescriptor(io::Printer* printer);
|
void GenerateEmbeddedDescriptor(io::Printer* printer);
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
@ -51,11 +51,8 @@ JavaGenerator::~JavaGenerator() {}
|
|||||||
|
|
||||||
bool JavaGenerator::Generate(const FileDescriptor* file,
|
bool JavaGenerator::Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
vector<pair<string, string> > options;
|
|
||||||
ParseGeneratorParameter(parameter, &options);
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// parse generator options
|
// parse generator options
|
||||||
|
|
||||||
@ -63,6 +60,10 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
|||||||
// per line.
|
// per line.
|
||||||
string output_list_file;
|
string output_list_file;
|
||||||
|
|
||||||
|
|
||||||
|
vector<pair<string, string> > options;
|
||||||
|
ParseGeneratorParameter(parameter, &options);
|
||||||
|
|
||||||
for (int i = 0; i < options.size(); i++) {
|
for (int i = 0; i < options.size(); i++) {
|
||||||
if (options[i].first == "output_list_file") {
|
if (options[i].first == "output_list_file") {
|
||||||
output_list_file = options[i].second;
|
output_list_file = options[i].second;
|
||||||
@ -72,18 +73,23 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
if (file->options().optimize_for() == FileOptions::LITE_RUNTIME &&
|
||||||
|
file->options().java_generate_equals_and_hash()) {
|
||||||
|
*error = "The \"java_generate_equals_and_hash\" option is incompatible "
|
||||||
|
"with \"optimize_for = LITE_RUNTIME\". You must optimize for "
|
||||||
|
"SPEED or CODE_SIZE if you want to use this option.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FileGenerator file_generator(file);
|
FileGenerator file_generator(file);
|
||||||
if (!file_generator.Validate(error)) {
|
if (!file_generator.Validate(error)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string package_dir =
|
string package_dir = JavaPackageToDir(file_generator.java_package());
|
||||||
StringReplace(file_generator.java_package(), ".", "/", true);
|
|
||||||
if (!package_dir.empty()) package_dir += "/";
|
|
||||||
|
|
||||||
vector<string> all_files;
|
vector<string> all_files;
|
||||||
|
|
||||||
@ -94,19 +100,19 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
|||||||
|
|
||||||
// Generate main java file.
|
// Generate main java file.
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->Open(java_filename));
|
context->Open(java_filename));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
file_generator.Generate(&printer);
|
file_generator.Generate(&printer);
|
||||||
|
|
||||||
// Generate sibling files.
|
// Generate sibling files.
|
||||||
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
|
file_generator.GenerateSiblings(package_dir, context, &all_files);
|
||||||
|
|
||||||
// Generate output list if requested.
|
// Generate output list if requested.
|
||||||
if (!output_list_file.empty()) {
|
if (!output_list_file.empty()) {
|
||||||
// Generate output list. This is just a simple text file placed in a
|
// Generate output list. This is just a simple text file placed in a
|
||||||
// deterministic location which lists the .java files being generated.
|
// deterministic location which lists the .java files being generated.
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
|
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
|
||||||
output_directory->Open(output_list_file));
|
context->Open(output_list_file));
|
||||||
io::Printer srclist_printer(srclist_raw_output.get(), '$');
|
io::Printer srclist_printer(srclist_raw_output.get(), '$');
|
||||||
for (int i = 0; i < all_files.size(); i++) {
|
for (int i = 0; i < all_files.size(); i++) {
|
||||||
srclist_printer.Print("$filename$\n", "filename", all_files[i]);
|
srclist_printer.Print("$filename$\n", "filename", all_files[i]);
|
@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator {
|
|||||||
// implements CodeGenerator ----------------------------------------
|
// implements CodeGenerator ----------------------------------------
|
||||||
bool Generate(const FileDescriptor* file,
|
bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const;
|
string* error) const;
|
||||||
|
|
||||||
private:
|
private:
|
@ -134,16 +134,27 @@ string FileClassName(const FileDescriptor* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string FileJavaPackage(const FileDescriptor* file) {
|
string FileJavaPackage(const FileDescriptor* file) {
|
||||||
|
string result;
|
||||||
|
|
||||||
if (file->options().has_java_package()) {
|
if (file->options().has_java_package()) {
|
||||||
return file->options().java_package();
|
result = file->options().java_package();
|
||||||
} else {
|
} else {
|
||||||
string result = kDefaultPackage;
|
result = kDefaultPackage;
|
||||||
if (!file->package().empty()) {
|
if (!file->package().empty()) {
|
||||||
if (!result.empty()) result += '.';
|
if (!result.empty()) result += '.';
|
||||||
result += file->package();
|
result += file->package();
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string JavaPackageToDir(string package_name) {
|
||||||
|
string package_dir =
|
||||||
|
StringReplace(package_name, ".", "/", true);
|
||||||
|
if (!package_dir.empty()) package_dir += "/";
|
||||||
|
return package_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
string ToJavaName(const string& full_name, const FileDescriptor* file) {
|
string ToJavaName(const string& full_name, const FileDescriptor* file) {
|
||||||
@ -166,6 +177,18 @@ string ToJavaName(const string& full_name, const FileDescriptor* file) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ClassName(const Descriptor* descriptor) {
|
||||||
|
return ToJavaName(descriptor->full_name(), descriptor->file());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ClassName(const EnumDescriptor* descriptor) {
|
||||||
|
return ToJavaName(descriptor->full_name(), descriptor->file());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ClassName(const ServiceDescriptor* descriptor) {
|
||||||
|
return ToJavaName(descriptor->full_name(), descriptor->file());
|
||||||
|
}
|
||||||
|
|
||||||
string ClassName(const FileDescriptor* descriptor) {
|
string ClassName(const FileDescriptor* descriptor) {
|
||||||
string result = FileJavaPackage(descriptor);
|
string result = FileJavaPackage(descriptor);
|
||||||
if (!result.empty()) result += '.';
|
if (!result.empty()) result += '.';
|
||||||
@ -315,14 +338,14 @@ string DefaultValue(const FieldDescriptor* field) {
|
|||||||
} else {
|
} else {
|
||||||
// See comments in Internal.java for gory details.
|
// See comments in Internal.java for gory details.
|
||||||
return strings::Substitute(
|
return strings::Substitute(
|
||||||
"com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
|
"com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
|
||||||
CEscape(field->default_value_string()));
|
CEscape(field->default_value_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case FieldDescriptor::CPPTYPE_ENUM:
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
return ClassName(field->enum_type()) + "." +
|
return ClassName(field->enum_type()) + "." +
|
||||||
field->default_value_enum()->name();
|
field->default_value_enum()->name();
|
||||||
|
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
return ClassName(field->message_type()) + ".getDefaultInstance()";
|
return ClassName(field->message_type()) + ".getDefaultInstance()";
|
||||||
@ -335,6 +358,142 @@ string DefaultValue(const FieldDescriptor* field) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
|
||||||
|
// Switch on CppType since we need to know which default_value_* method
|
||||||
|
// of FieldDescriptor to call.
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_INT32:
|
||||||
|
return field->default_value_int32() == 0;
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT32:
|
||||||
|
return field->default_value_uint32() == 0;
|
||||||
|
case FieldDescriptor::CPPTYPE_INT64:
|
||||||
|
return field->default_value_int64() == 0L;
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT64:
|
||||||
|
return field->default_value_uint64() == 0L;
|
||||||
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||||
|
return field->default_value_double() == 0.0;
|
||||||
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||||
|
return field->default_value_float() == 0.0;
|
||||||
|
case FieldDescriptor::CPPTYPE_BOOL:
|
||||||
|
return field->default_value_bool() == false;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* bit_masks[] = {
|
||||||
|
"0x00000001",
|
||||||
|
"0x00000002",
|
||||||
|
"0x00000004",
|
||||||
|
"0x00000008",
|
||||||
|
"0x00000010",
|
||||||
|
"0x00000020",
|
||||||
|
"0x00000040",
|
||||||
|
"0x00000080",
|
||||||
|
|
||||||
|
"0x00000100",
|
||||||
|
"0x00000200",
|
||||||
|
"0x00000400",
|
||||||
|
"0x00000800",
|
||||||
|
"0x00001000",
|
||||||
|
"0x00002000",
|
||||||
|
"0x00004000",
|
||||||
|
"0x00008000",
|
||||||
|
|
||||||
|
"0x00010000",
|
||||||
|
"0x00020000",
|
||||||
|
"0x00040000",
|
||||||
|
"0x00080000",
|
||||||
|
"0x00100000",
|
||||||
|
"0x00200000",
|
||||||
|
"0x00400000",
|
||||||
|
"0x00800000",
|
||||||
|
|
||||||
|
"0x01000000",
|
||||||
|
"0x02000000",
|
||||||
|
"0x04000000",
|
||||||
|
"0x08000000",
|
||||||
|
"0x10000000",
|
||||||
|
"0x20000000",
|
||||||
|
"0x40000000",
|
||||||
|
"0x80000000",
|
||||||
|
};
|
||||||
|
|
||||||
|
string GetBitFieldName(int index) {
|
||||||
|
string varName = "bitField";
|
||||||
|
varName += SimpleItoa(index);
|
||||||
|
varName += "_";
|
||||||
|
return varName;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetBitFieldNameForBit(int bitIndex) {
|
||||||
|
return GetBitFieldName(bitIndex / 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
string GenerateGetBitInternal(const string& prefix, int bitIndex) {
|
||||||
|
string varName = prefix + GetBitFieldNameForBit(bitIndex);
|
||||||
|
int bitInVarIndex = bitIndex % 32;
|
||||||
|
|
||||||
|
string mask = bit_masks[bitInVarIndex];
|
||||||
|
string result = "((" + varName + " & " + mask + ") == " + mask + ")";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateSetBitInternal(const string& prefix, int bitIndex) {
|
||||||
|
string varName = prefix + GetBitFieldNameForBit(bitIndex);
|
||||||
|
int bitInVarIndex = bitIndex % 32;
|
||||||
|
|
||||||
|
string mask = bit_masks[bitInVarIndex];
|
||||||
|
string result = varName + " |= " + mask;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
string GenerateGetBit(int bitIndex) {
|
||||||
|
return GenerateGetBitInternal("", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateSetBit(int bitIndex) {
|
||||||
|
return GenerateSetBitInternal("", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateClearBit(int bitIndex) {
|
||||||
|
string varName = GetBitFieldNameForBit(bitIndex);
|
||||||
|
int bitInVarIndex = bitIndex % 32;
|
||||||
|
|
||||||
|
string mask = bit_masks[bitInVarIndex];
|
||||||
|
string result = varName + " = (" + varName + " & ~" + mask + ")";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateGetBitFromLocal(int bitIndex) {
|
||||||
|
return GenerateGetBitInternal("from_", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateSetBitToLocal(int bitIndex) {
|
||||||
|
return GenerateSetBitInternal("to_", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateGetBitMutableLocal(int bitIndex) {
|
||||||
|
return GenerateGetBitInternal("mutable_", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateSetBitMutableLocal(int bitIndex) {
|
||||||
|
return GenerateSetBitInternal("mutable_", bitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace java
|
} // namespace java
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
@ -68,6 +68,9 @@ string FileClassName(const FileDescriptor* file);
|
|||||||
// Returns the file's Java package name.
|
// Returns the file's Java package name.
|
||||||
string FileJavaPackage(const FileDescriptor* file);
|
string FileJavaPackage(const FileDescriptor* file);
|
||||||
|
|
||||||
|
// Returns output directory for the given package name.
|
||||||
|
string JavaPackageToDir(string package_name);
|
||||||
|
|
||||||
// Converts the given fully-qualified name in the proto namespace to its
|
// Converts the given fully-qualified name in the proto namespace to its
|
||||||
// fully-qualified name in the Java namespace, given that it is in the given
|
// fully-qualified name in the Java namespace, given that it is in the given
|
||||||
// file.
|
// file.
|
||||||
@ -75,19 +78,14 @@ string ToJavaName(const string& full_name, const FileDescriptor* file);
|
|||||||
|
|
||||||
// These return the fully-qualified class name corresponding to the given
|
// These return the fully-qualified class name corresponding to the given
|
||||||
// descriptor.
|
// descriptor.
|
||||||
inline string ClassName(const Descriptor* descriptor) {
|
string ClassName(const Descriptor* descriptor);
|
||||||
return ToJavaName(descriptor->full_name(), descriptor->file());
|
string ClassName(const EnumDescriptor* descriptor);
|
||||||
}
|
string ClassName(const ServiceDescriptor* descriptor);
|
||||||
inline string ClassName(const EnumDescriptor* descriptor) {
|
string ClassName(const FileDescriptor* descriptor);
|
||||||
return ToJavaName(descriptor->full_name(), descriptor->file());
|
|
||||||
}
|
|
||||||
inline string ClassName(const ServiceDescriptor* descriptor) {
|
|
||||||
return ToJavaName(descriptor->full_name(), descriptor->file());
|
|
||||||
}
|
|
||||||
inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
|
inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
|
||||||
return ToJavaName(descriptor->full_name(), descriptor->file());
|
return ToJavaName(descriptor->full_name(), descriptor->file());
|
||||||
}
|
}
|
||||||
string ClassName(const FileDescriptor* descriptor);
|
|
||||||
|
|
||||||
// Get the unqualified name that should be used for a field's field
|
// Get the unqualified name that should be used for a field's field
|
||||||
// number constant.
|
// number constant.
|
||||||
@ -118,6 +116,7 @@ JavaType GetJavaType(const FieldDescriptor* field);
|
|||||||
const char* BoxedPrimitiveTypeName(JavaType type);
|
const char* BoxedPrimitiveTypeName(JavaType type);
|
||||||
|
|
||||||
string DefaultValue(const FieldDescriptor* field);
|
string DefaultValue(const FieldDescriptor* field);
|
||||||
|
bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
|
||||||
|
|
||||||
// Does this message class keep track of unknown fields?
|
// Does this message class keep track of unknown fields?
|
||||||
inline bool HasUnknownFields(const Descriptor* descriptor) {
|
inline bool HasUnknownFields(const Descriptor* descriptor) {
|
||||||
@ -132,6 +131,11 @@ inline bool HasGeneratedMethods(const Descriptor* descriptor) {
|
|||||||
FileOptions::CODE_SIZE;
|
FileOptions::CODE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Does this message have specialized equals() and hashCode() methods?
|
||||||
|
inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
|
||||||
|
return descriptor->file()->options().java_generate_equals_and_hash();
|
||||||
|
}
|
||||||
|
|
||||||
// Does this message class have descriptor and reflection methods?
|
// Does this message class have descriptor and reflection methods?
|
||||||
inline bool HasDescriptorMethods(const Descriptor* descriptor) {
|
inline bool HasDescriptorMethods(const Descriptor* descriptor) {
|
||||||
return descriptor->file()->options().optimize_for() !=
|
return descriptor->file()->options().optimize_for() !=
|
||||||
@ -146,6 +150,12 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
|
|||||||
FileOptions::LITE_RUNTIME;
|
FileOptions::LITE_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool HasNestedBuilders(const Descriptor* descriptor) {
|
||||||
|
// The proto-lite version doesn't support nested builders.
|
||||||
|
return descriptor->file()->options().optimize_for() !=
|
||||||
|
FileOptions::LITE_RUNTIME;
|
||||||
|
}
|
||||||
|
|
||||||
// Should we generate generic services for this file?
|
// Should we generate generic services for this file?
|
||||||
inline bool HasGenericServices(const FileDescriptor *file) {
|
inline bool HasGenericServices(const FileDescriptor *file) {
|
||||||
return file->service_count() > 0 &&
|
return file->service_count() > 0 &&
|
||||||
@ -153,6 +163,55 @@ inline bool HasGenericServices(const FileDescriptor *file) {
|
|||||||
file->options().java_generic_services();
|
file->options().java_generic_services();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Methods for shared bitfields.
|
||||||
|
|
||||||
|
// Gets the name of the shared bitfield for the given index.
|
||||||
|
string GetBitFieldName(int index);
|
||||||
|
|
||||||
|
// Gets the name of the shared bitfield for the given bit index.
|
||||||
|
// Effectively, GetBitFieldName(bitIndex / 32)
|
||||||
|
string GetBitFieldNameForBit(int bitIndex);
|
||||||
|
|
||||||
|
// Generates the java code for the expression that returns the boolean value
|
||||||
|
// of the bit of the shared bitfields for the given bit index.
|
||||||
|
// Example: "((bitField1_ & 0x04) == 0x04)"
|
||||||
|
string GenerateGetBit(int bitIndex);
|
||||||
|
|
||||||
|
// Generates the java code for the expression that sets the bit of the shared
|
||||||
|
// bitfields for the given bit index.
|
||||||
|
// Example: "bitField1_ = (bitField1_ | 0x04)"
|
||||||
|
string GenerateSetBit(int bitIndex);
|
||||||
|
|
||||||
|
// Generates the java code for the expression that clears the bit of the shared
|
||||||
|
// bitfields for the given bit index.
|
||||||
|
// Example: "bitField1_ = (bitField1_ & ~0x04)"
|
||||||
|
string GenerateClearBit(int bitIndex);
|
||||||
|
|
||||||
|
// Does the same as GenerateGetBit but operates on the bit field on a local
|
||||||
|
// variable. This is used by the builder to copy the value in the builder to
|
||||||
|
// the message.
|
||||||
|
// Example: "((from_bitField1_ & 0x04) == 0x04)"
|
||||||
|
string GenerateGetBitFromLocal(int bitIndex);
|
||||||
|
|
||||||
|
// Does the same as GenerateSetBit but operates on the bit field on a local
|
||||||
|
// variable. This is used by the builder to copy the value in the builder to
|
||||||
|
// the message.
|
||||||
|
// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
|
||||||
|
string GenerateSetBitToLocal(int bitIndex);
|
||||||
|
|
||||||
|
// Does the same as GenerateGetBit but operates on the bit field on a local
|
||||||
|
// variable. This is used by the parsing constructor to record if a repeated
|
||||||
|
// field is mutable.
|
||||||
|
// Example: "((mutable_bitField1_ & 0x04) == 0x04)"
|
||||||
|
string GenerateGetBitMutableLocal(int bitIndex);
|
||||||
|
|
||||||
|
// Does the same as GenerateSetBit but operates on the bit field on a local
|
||||||
|
// variable. This is used by the parsing constructor to record if a repeated
|
||||||
|
// field is mutable.
|
||||||
|
// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
|
||||||
|
string GenerateSetBitMutableLocal(int bitIndex);
|
||||||
|
|
||||||
} // namespace java
|
} // namespace java
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
File diff suppressed because it is too large
Load Diff
@ -67,11 +67,19 @@ class MessageGenerator {
|
|||||||
// Generate the class itself.
|
// Generate the class itself.
|
||||||
void Generate(io::Printer* printer);
|
void Generate(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generates the base interface that both the class and its builder implement
|
||||||
|
void GenerateInterface(io::Printer* printer);
|
||||||
|
|
||||||
// Generate code to register all contained extensions with an
|
// Generate code to register all contained extensions with an
|
||||||
// ExtensionRegistry.
|
// ExtensionRegistry.
|
||||||
void GenerateExtensionRegistrationCode(io::Printer* printer);
|
void GenerateExtensionRegistrationCode(io::Printer* printer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum UseMemoization {
|
||||||
|
MEMOIZE,
|
||||||
|
DONT_MEMOIZE
|
||||||
|
};
|
||||||
|
|
||||||
void GenerateMessageSerializationMethods(io::Printer* printer);
|
void GenerateMessageSerializationMethods(io::Printer* printer);
|
||||||
void GenerateParseFromMethods(io::Printer* printer);
|
void GenerateParseFromMethods(io::Printer* printer);
|
||||||
void GenerateSerializeOneField(io::Printer* printer,
|
void GenerateSerializeOneField(io::Printer* printer,
|
||||||
@ -81,8 +89,14 @@ class MessageGenerator {
|
|||||||
|
|
||||||
void GenerateBuilder(io::Printer* printer);
|
void GenerateBuilder(io::Printer* printer);
|
||||||
void GenerateCommonBuilderMethods(io::Printer* printer);
|
void GenerateCommonBuilderMethods(io::Printer* printer);
|
||||||
|
void GenerateDescriptorMethods(io::Printer* printer);
|
||||||
void GenerateBuilderParsingMethods(io::Printer* printer);
|
void GenerateBuilderParsingMethods(io::Printer* printer);
|
||||||
void GenerateIsInitialized(io::Printer* printer);
|
void GenerateIsInitialized(io::Printer* printer,
|
||||||
|
UseMemoization useMemoization);
|
||||||
|
void GenerateEqualsAndHashCode(io::Printer* printer);
|
||||||
|
|
||||||
|
void GenerateParser(io::Printer* printer);
|
||||||
|
void GenerateParsingConstructor(io::Printer* printer);
|
||||||
|
|
||||||
const Descriptor* descriptor_;
|
const Descriptor* descriptor_;
|
||||||
FieldGeneratorMap field_generators_;
|
FieldGeneratorMap field_generators_;
|
@ -0,0 +1,974 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_message_field.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||||
|
// repeat code between this and the other field types.
|
||||||
|
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
(*variables)["name"] =
|
||||||
|
UnderscoresToCamelCase(descriptor);
|
||||||
|
(*variables)["capitalized_name"] =
|
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||||
|
(*variables)["constant_name"] = FieldConstantName(descriptor);
|
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
|
(*variables)["type"] = ClassName(descriptor->message_type());
|
||||||
|
(*variables)["group_or_message"] =
|
||||||
|
(GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
|
||||||
|
"Group" : "Message";
|
||||||
|
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
|
||||||
|
// by the proto compiler
|
||||||
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
|
? "@java.lang.Deprecated " : "";
|
||||||
|
(*variables)["on_changed"] =
|
||||||
|
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
|
||||||
|
|
||||||
|
// For singular messages and builders, one bit is used for the hasField bit.
|
||||||
|
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_has_field_bit_builder"] =
|
||||||
|
GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repated builders, one bit is used for whether the array is immutable.
|
||||||
|
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repeated fields, one bit is used for whether the array is immutable
|
||||||
|
// in the parsing constructor.
|
||||||
|
(*variables)["get_mutable_bit_parser"] =
|
||||||
|
GenerateGetBitMutableLocal(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_parser"] =
|
||||||
|
GenerateSetBitMutableLocal(builderBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_from_local"] =
|
||||||
|
GenerateGetBitFromLocal(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_to_local"] =
|
||||||
|
GenerateSetBitToLocal(messageBitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
MessageFieldGenerator::
|
||||||
|
MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFieldGenerator::~MessageFieldGenerator() {}
|
||||||
|
|
||||||
|
int MessageFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MessageFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
// TODO(jonp): In the future, consider having a method specific to the
|
||||||
|
// interface so that builders can choose dynamically to either return a
|
||||||
|
// message or a nested builder, so that asking for the interface doesn't
|
||||||
|
// cause a message to ever be built.
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$boolean has$capitalized_name$();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$();\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $type$ $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_message$;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::PrintNestedBuilderCondition(
|
||||||
|
io::Printer* printer,
|
||||||
|
const char* regular_case,
|
||||||
|
const char* nested_builder_case) const {
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_, "if ($name$Builder_ == null) {\n");
|
||||||
|
printer->Indent();
|
||||||
|
printer->Print(variables_, regular_case);
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("} else {\n");
|
||||||
|
printer->Indent();
|
||||||
|
printer->Print(variables_, nested_builder_case);
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_, regular_case);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::PrintNestedBuilderFunction(
|
||||||
|
io::Printer* printer,
|
||||||
|
const char* method_prototype,
|
||||||
|
const char* regular_case,
|
||||||
|
const char* nested_builder_case,
|
||||||
|
const char* trailing_code) const {
|
||||||
|
printer->Print(variables_, method_prototype);
|
||||||
|
printer->Print(" {\n");
|
||||||
|
printer->Indent();
|
||||||
|
PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
|
||||||
|
if (trailing_code != NULL) {
|
||||||
|
printer->Print(variables_, trailing_code);
|
||||||
|
}
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
// When using nested-builders, the code initially works just like the
|
||||||
|
// non-nested builder case. It only creates a nested builder lazily on
|
||||||
|
// demand and then forever delegates to it after creation.
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
// Used when the builder is null.
|
||||||
|
"private $type$ $name$_ = $type$.getDefaultInstance();\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
// If this builder is non-null, it is used and the other fields are
|
||||||
|
// ignored.
|
||||||
|
"private com.google.protobuf.SingleFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The comments above the methods below are based on a hypothetical
|
||||||
|
// field of type "Field" called "Field".
|
||||||
|
|
||||||
|
// boolean hasField()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_builder$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
// Field getField()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$()",
|
||||||
|
|
||||||
|
"return $name$_;\n",
|
||||||
|
|
||||||
|
"return $name$Builder_.getMessage();\n",
|
||||||
|
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Field.Builder setField(Field value)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$($type$ value)",
|
||||||
|
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
"}\n"
|
||||||
|
"$name$_ = value;\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.setMessage(value);\n",
|
||||||
|
|
||||||
|
"$set_has_field_bit_builder$;\n"
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Field.Builder setField(Field.Builder builderForValue)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" $type$.Builder builderForValue)",
|
||||||
|
|
||||||
|
"$name$_ = builderForValue.build();\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.setMessage(builderForValue.build());\n",
|
||||||
|
|
||||||
|
"$set_has_field_bit_builder$;\n"
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Field.Builder mergeField(Field value)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder merge$capitalized_name$($type$ value)",
|
||||||
|
|
||||||
|
"if ($get_has_field_bit_builder$ &&\n"
|
||||||
|
" $name$_ != $type$.getDefaultInstance()) {\n"
|
||||||
|
" $name$_ =\n"
|
||||||
|
" $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
|
||||||
|
"} else {\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
"}\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.mergeFrom(value);\n",
|
||||||
|
|
||||||
|
"$set_has_field_bit_builder$;\n"
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Field.Builder clearField()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$()",
|
||||||
|
|
||||||
|
"$name$_ = $type$.getDefaultInstance();\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.clear();\n",
|
||||||
|
|
||||||
|
"$clear_has_field_bit_builder$;\n"
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return get$capitalized_name$FieldBuilder().getBuilder();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
|
||||||
|
" if ($name$Builder_ != null) {\n"
|
||||||
|
" return $name$Builder_.getMessageOrBuilder();\n"
|
||||||
|
" } else {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private com.google.protobuf.SingleFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder> \n"
|
||||||
|
" get$capitalized_name$FieldBuilder() {\n"
|
||||||
|
" if ($name$Builder_ == null) {\n"
|
||||||
|
" $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder>(\n"
|
||||||
|
" $name$_,\n"
|
||||||
|
" getParentForChildren(),\n"
|
||||||
|
" isClean());\n"
|
||||||
|
" $name$_ = null;\n"
|
||||||
|
" }\n"
|
||||||
|
" return $name$Builder_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"get$capitalized_name$FieldBuilder();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
PrintNestedBuilderCondition(printer,
|
||||||
|
"$name$_ = $type$.getDefaultInstance();\n",
|
||||||
|
|
||||||
|
"$name$Builder_.clear();\n");
|
||||||
|
printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (other.has$capitalized_name$()) {\n"
|
||||||
|
" merge$capitalized_name$(other.get$capitalized_name$());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_from_local$) {\n"
|
||||||
|
" $set_has_field_bit_to_local$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
PrintNestedBuilderCondition(printer,
|
||||||
|
"result.$name$_ = $name$_;\n",
|
||||||
|
|
||||||
|
"result.$name$_ = $name$Builder_.build();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$type$.Builder subBuilder = null;\n"
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" subBuilder = $name$_.toBuilder();\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = input.readGroup($number$, $type$.PARSER,\n"
|
||||||
|
" extensionRegistry);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (subBuilder != null) {\n"
|
||||||
|
" subBuilder.mergeFrom($name$_);\n"
|
||||||
|
" $name$_ = subBuilder.buildPartial();\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$set_has_field_bit_message$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
// noop for messages.
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" output.write$group_or_message$($number$, $name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .compute$group_or_message$Size($number$, $name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$()\n"
|
||||||
|
" .equals(other.get$capitalized_name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
"hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string MessageFieldGenerator::GetBoxedType() const {
|
||||||
|
return ClassName(descriptor_->message_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator::
|
||||||
|
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
||||||
|
|
||||||
|
int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
// TODO(jonp): In the future, consider having methods specific to the
|
||||||
|
// interface so that builders can choose dynamically to either return a
|
||||||
|
// message or a nested builder, so that asking for the interface doesn't
|
||||||
|
// cause a message to ever be built.
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.util.List<$type$> \n"
|
||||||
|
" get$capitalized_name$List();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$(int index);\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$int get$capitalized_name$Count();\n");
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.util.List<? extends $type$OrBuilder> \n"
|
||||||
|
" get$capitalized_name$OrBuilderList();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
|
||||||
|
" int index);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private java.util.List<$type$> $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
|
||||||
|
" return $name$_;\n" // note: unmodifiable list
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
|
||||||
|
" get$capitalized_name$OrBuilderList() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
|
||||||
|
" int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
|
||||||
|
io::Printer* printer,
|
||||||
|
const char* regular_case,
|
||||||
|
const char* nested_builder_case) const {
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_, "if ($name$Builder_ == null) {\n");
|
||||||
|
printer->Indent();
|
||||||
|
printer->Print(variables_, regular_case);
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("} else {\n");
|
||||||
|
printer->Indent();
|
||||||
|
printer->Print(variables_, nested_builder_case);
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_, regular_case);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
|
||||||
|
io::Printer* printer,
|
||||||
|
const char* method_prototype,
|
||||||
|
const char* regular_case,
|
||||||
|
const char* nested_builder_case,
|
||||||
|
const char* trailing_code) const {
|
||||||
|
printer->Print(variables_, method_prototype);
|
||||||
|
printer->Print(" {\n");
|
||||||
|
printer->Indent();
|
||||||
|
PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
|
||||||
|
if (trailing_code != NULL) {
|
||||||
|
printer->Print(variables_, trailing_code);
|
||||||
|
}
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
// When using nested-builders, the code initially works just like the
|
||||||
|
// non-nested builder case. It only creates a nested builder lazily on
|
||||||
|
// demand and then forever delegates to it after creation.
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
// Used when the builder is null.
|
||||||
|
// One field is the list and the other field keeps track of whether the
|
||||||
|
// list is immutable. If it's immutable, the invariant is that it must
|
||||||
|
// either an instance of Collections.emptyList() or it's an ArrayList
|
||||||
|
// wrapped in a Collections.unmodifiableList() wrapper and nobody else has
|
||||||
|
// a refererence to the underlying ArrayList. This invariant allows us to
|
||||||
|
// share instances of lists between protocol buffers avoiding expensive
|
||||||
|
// memory allocations. Note, immutable is a strong guarantee here -- not
|
||||||
|
// just that the list cannot be modified via the reference but that the
|
||||||
|
// list can never be modified.
|
||||||
|
"private java.util.List<$type$> $name$_ =\n"
|
||||||
|
" java.util.Collections.emptyList();\n"
|
||||||
|
|
||||||
|
"private void ensure$capitalized_name$IsMutable() {\n"
|
||||||
|
" if (!$get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
|
||||||
|
" $set_mutable_bit_builder$;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
// If this builder is non-null, it is used and the other fields are
|
||||||
|
// ignored.
|
||||||
|
"private com.google.protobuf.RepeatedFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The comments above the methods below are based on a hypothetical
|
||||||
|
// repeated field of type "Field" called "RepeatedField".
|
||||||
|
|
||||||
|
// List<Field> getRepeatedFieldList()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
|
||||||
|
|
||||||
|
"return java.util.Collections.unmodifiableList($name$_);\n",
|
||||||
|
"return $name$Builder_.getMessageList();\n",
|
||||||
|
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// int getRepeatedFieldCount()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count()",
|
||||||
|
|
||||||
|
"return $name$_.size();\n",
|
||||||
|
"return $name$Builder_.getCount();\n",
|
||||||
|
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Field getRepeatedField(int index)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index)",
|
||||||
|
|
||||||
|
"return $name$_.get(index);\n",
|
||||||
|
|
||||||
|
"return $name$Builder_.getMessage(index);\n",
|
||||||
|
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Builder setRepeatedField(int index, Field value)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" int index, $type$ value)",
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
"}\n"
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.set(index, value);\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
"$name$Builder_.setMessage(index, value);\n",
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder setRepeatedField(int index, Field.Builder builderForValue)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" int index, $type$.Builder builderForValue)",
|
||||||
|
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.set(index, builderForValue.build());\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.setMessage(index, builderForValue.build());\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder addRepeatedField(Field value)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$($type$ value)",
|
||||||
|
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
"}\n"
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.add(value);\n"
|
||||||
|
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.addMessage(value);\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder addRepeatedField(int index, Field value)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$(\n"
|
||||||
|
" int index, $type$ value)",
|
||||||
|
|
||||||
|
"if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
"}\n"
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.add(index, value);\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.addMessage(index, value);\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder addRepeatedField(Field.Builder builderForValue)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$(\n"
|
||||||
|
" $type$.Builder builderForValue)",
|
||||||
|
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.add(builderForValue.build());\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.addMessage(builderForValue.build());\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder addRepeatedField(int index, Field.Builder builderForValue)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$(\n"
|
||||||
|
" int index, $type$.Builder builderForValue)",
|
||||||
|
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.add(index, builderForValue.build());\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.addMessage(index, builderForValue.build());\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder addAllRepeatedField(Iterable<Field> values)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder addAll$capitalized_name$(\n"
|
||||||
|
" java.lang.Iterable<? extends $type$> values)",
|
||||||
|
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"super.addAll(values, $name$_);\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.addAllMessages(values);\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder clearAllRepeatedField()
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$()",
|
||||||
|
|
||||||
|
"$name$_ = java.util.Collections.emptyList();\n"
|
||||||
|
"$clear_mutable_bit_builder$;\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.clear();\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
// Builder removeRepeatedField(int index)
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
PrintNestedBuilderFunction(printer,
|
||||||
|
"$deprecation$public Builder remove$capitalized_name$(int index)",
|
||||||
|
|
||||||
|
"ensure$capitalized_name$IsMutable();\n"
|
||||||
|
"$name$_.remove(index);\n"
|
||||||
|
"$on_changed$\n",
|
||||||
|
|
||||||
|
"$name$Builder_.remove(index);\n",
|
||||||
|
|
||||||
|
"return this;\n");
|
||||||
|
|
||||||
|
if (HasNestedBuilders(descriptor_->containing_type())) {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
|
||||||
|
" int index) {\n"
|
||||||
|
" return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
|
||||||
|
" int index) {\n"
|
||||||
|
" if ($name$Builder_ == null) {\n"
|
||||||
|
" return $name$_.get(index);"
|
||||||
|
" } else {\n"
|
||||||
|
" return $name$Builder_.getMessageOrBuilder(index);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
|
||||||
|
" get$capitalized_name$OrBuilderList() {\n"
|
||||||
|
" if ($name$Builder_ != null) {\n"
|
||||||
|
" return $name$Builder_.getMessageOrBuilderList();\n"
|
||||||
|
" } else {\n"
|
||||||
|
" return java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
|
||||||
|
" return get$capitalized_name$FieldBuilder().addBuilder(\n"
|
||||||
|
" $type$.getDefaultInstance());\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
|
||||||
|
" int index) {\n"
|
||||||
|
" return get$capitalized_name$FieldBuilder().addBuilder(\n"
|
||||||
|
" index, $type$.getDefaultInstance());\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<$type$.Builder> \n"
|
||||||
|
" get$capitalized_name$BuilderList() {\n"
|
||||||
|
" return get$capitalized_name$FieldBuilder().getBuilderList();\n"
|
||||||
|
"}\n"
|
||||||
|
"private com.google.protobuf.RepeatedFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder> \n"
|
||||||
|
" get$capitalized_name$FieldBuilder() {\n"
|
||||||
|
" if ($name$Builder_ == null) {\n"
|
||||||
|
" $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
|
||||||
|
" $type$, $type$.Builder, $type$OrBuilder>(\n"
|
||||||
|
" $name$_,\n"
|
||||||
|
" $get_mutable_bit_builder$,\n"
|
||||||
|
" getParentForChildren(),\n"
|
||||||
|
" isClean());\n"
|
||||||
|
" $name$_ = null;\n"
|
||||||
|
" }\n"
|
||||||
|
" return $name$Builder_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"get$capitalized_name$FieldBuilder();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
PrintNestedBuilderCondition(printer,
|
||||||
|
"$name$_ = java.util.Collections.emptyList();\n"
|
||||||
|
"$clear_mutable_bit_builder$;\n",
|
||||||
|
|
||||||
|
"$name$Builder_.clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
// The code below does two optimizations (non-nested builder case):
|
||||||
|
// 1. If the other list is empty, there's nothing to do. This ensures we
|
||||||
|
// don't allocate a new array if we already have an immutable one.
|
||||||
|
// 2. If the other list is non-empty and our current list is empty, we can
|
||||||
|
// reuse the other list which is guaranteed to be immutable.
|
||||||
|
PrintNestedBuilderCondition(printer,
|
||||||
|
"if (!other.$name$_.isEmpty()) {\n"
|
||||||
|
" if ($name$_.isEmpty()) {\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.addAll(other.$name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
"}\n",
|
||||||
|
|
||||||
|
"if (!other.$name$_.isEmpty()) {\n"
|
||||||
|
" if ($name$Builder_.isEmpty()) {\n"
|
||||||
|
" $name$Builder_.dispose();\n"
|
||||||
|
" $name$Builder_ = null;\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" $name$Builder_ = \n"
|
||||||
|
" com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
|
||||||
|
" get$capitalized_name$FieldBuilder() : null;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" $name$Builder_.addAllMessages(other.$name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
// The code below (non-nested builder case) ensures that the result has an
|
||||||
|
// immutable list. If our list is immutable, we can just reuse it. If not,
|
||||||
|
// we make it immutable.
|
||||||
|
PrintNestedBuilderCondition(printer,
|
||||||
|
"if ($get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n",
|
||||||
|
|
||||||
|
"result.$name$_ = $name$Builder_.build();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!$get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$type$>();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
|
||||||
|
" extensionRegistry));\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.write$group_or_message$($number$, $name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .compute$group_or_message$Size($number$, $name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$List()\n"
|
||||||
|
" .equals(other.get$capitalized_name$List());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$Count() > 0) {\n"
|
||||||
|
" hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
" hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string RepeatedMessageFieldGenerator::GetBoxedType() const {
|
||||||
|
return ClassName(descriptor_->message_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -46,50 +46,86 @@ namespace java {
|
|||||||
|
|
||||||
class MessageFieldGenerator : public FieldGenerator {
|
class MessageFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
|
explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~MessageFieldGenerator();
|
~MessageFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
||||||
|
|
||||||
|
void PrintNestedBuilderCondition(io::Printer* printer,
|
||||||
|
const char* regular_case, const char* nested_builder_case) const;
|
||||||
|
void PrintNestedBuilderFunction(io::Printer* printer,
|
||||||
|
const char* method_prototype, const char* regular_case,
|
||||||
|
const char* nested_builder_case,
|
||||||
|
const char* trailing_code) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~RepeatedMessageFieldGenerator();
|
~RepeatedMessageFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||||
|
|
||||||
|
void PrintNestedBuilderCondition(io::Printer* printer,
|
||||||
|
const char* regular_case, const char* nested_builder_case) const;
|
||||||
|
void PrintNestedBuilderFunction(io::Printer* printer,
|
||||||
|
const char* method_prototype, const char* regular_case,
|
||||||
|
const char* nested_builder_case,
|
||||||
|
const char* trailing_code) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace java
|
} // namespace java
|
@ -56,21 +56,22 @@ class TestGenerator : public CodeGenerator {
|
|||||||
|
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
TryInsert("Test.java", "outer_class_scope", output_directory);
|
string filename = "Test.java";
|
||||||
TryInsert("Test.java", "class_scope:foo.Bar", output_directory);
|
TryInsert(filename, "outer_class_scope", context);
|
||||||
TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory);
|
TryInsert(filename, "class_scope:foo.Bar", context);
|
||||||
TryInsert("Test.java", "builder_scope:foo.Bar", output_directory);
|
TryInsert(filename, "class_scope:foo.Bar.Baz", context);
|
||||||
TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory);
|
TryInsert(filename, "builder_scope:foo.Bar", context);
|
||||||
TryInsert("Test.java", "enum_scope:foo.Qux", output_directory);
|
TryInsert(filename, "builder_scope:foo.Bar.Baz", context);
|
||||||
|
TryInsert(filename, "enum_scope:foo.Qux", context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryInsert(const string& filename, const string& insertion_point,
|
void TryInsert(const string& filename, const string& insertion_point,
|
||||||
OutputDirectory* output_directory) const {
|
GeneratorContext* context) const {
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->OpenForInsert(filename, insertion_point));
|
context->OpenForInsert(filename, insertion_point));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||||
}
|
}
|
@ -0,0 +1,787 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_primitive_field.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
using internal::WireFormatLite;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char* PrimitiveTypeName(JavaType type) {
|
||||||
|
switch (type) {
|
||||||
|
case JAVATYPE_INT : return "int";
|
||||||
|
case JAVATYPE_LONG : return "long";
|
||||||
|
case JAVATYPE_FLOAT : return "float";
|
||||||
|
case JAVATYPE_DOUBLE : return "double";
|
||||||
|
case JAVATYPE_BOOLEAN: return "boolean";
|
||||||
|
case JAVATYPE_STRING : return "java.lang.String";
|
||||||
|
case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
|
||||||
|
case JAVATYPE_ENUM : return NULL;
|
||||||
|
case JAVATYPE_MESSAGE: return NULL;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsReferenceType(JavaType type) {
|
||||||
|
switch (type) {
|
||||||
|
case JAVATYPE_INT : return false;
|
||||||
|
case JAVATYPE_LONG : return false;
|
||||||
|
case JAVATYPE_FLOAT : return false;
|
||||||
|
case JAVATYPE_DOUBLE : return false;
|
||||||
|
case JAVATYPE_BOOLEAN: return false;
|
||||||
|
case JAVATYPE_STRING : return true;
|
||||||
|
case JAVATYPE_BYTES : return true;
|
||||||
|
case JAVATYPE_ENUM : return true;
|
||||||
|
case JAVATYPE_MESSAGE: return true;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetCapitalizedType(const FieldDescriptor* field) {
|
||||||
|
switch (GetType(field)) {
|
||||||
|
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
|
||||||
|
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
|
||||||
|
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
|
||||||
|
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
|
||||||
|
case FieldDescriptor::TYPE_INT64 : return "Int64" ;
|
||||||
|
case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
|
||||||
|
case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
|
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
|
||||||
|
case FieldDescriptor::TYPE_FLOAT : return "Float" ;
|
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
|
||||||
|
case FieldDescriptor::TYPE_BOOL : return "Bool" ;
|
||||||
|
case FieldDescriptor::TYPE_STRING : return "String" ;
|
||||||
|
case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
|
||||||
|
case FieldDescriptor::TYPE_ENUM : return "Enum" ;
|
||||||
|
case FieldDescriptor::TYPE_GROUP : return "Group" ;
|
||||||
|
case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||||
|
// returns -1.
|
||||||
|
int FixedSize(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 WireFormatLite::kFixed32Size;
|
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
||||||
|
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BOOL : return 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
(*variables)["name"] =
|
||||||
|
UnderscoresToCamelCase(descriptor);
|
||||||
|
(*variables)["capitalized_name"] =
|
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||||
|
(*variables)["constant_name"] = FieldConstantName(descriptor);
|
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
|
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
|
||||||
|
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
|
||||||
|
(*variables)["field_type"] = (*variables)["type"];
|
||||||
|
(*variables)["field_list_type"] = "java.util.List<" +
|
||||||
|
(*variables)["boxed_type"] + ">";
|
||||||
|
(*variables)["empty_list"] = "java.util.Collections.emptyList()";
|
||||||
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
|
||||||
|
"" : ("= " + DefaultValue(descriptor));
|
||||||
|
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
|
||||||
|
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
|
||||||
|
(*variables)["tag_size"] = SimpleItoa(
|
||||||
|
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
||||||
|
if (IsReferenceType(GetJavaType(descriptor))) {
|
||||||
|
(*variables)["null_check"] =
|
||||||
|
" if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
" }\n";
|
||||||
|
} else {
|
||||||
|
(*variables)["null_check"] = "";
|
||||||
|
}
|
||||||
|
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
|
||||||
|
// by the proto compiler
|
||||||
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
|
? "@java.lang.Deprecated " : "";
|
||||||
|
int fixed_size = FixedSize(GetType(descriptor));
|
||||||
|
if (fixed_size != -1) {
|
||||||
|
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
|
||||||
|
}
|
||||||
|
(*variables)["on_changed"] =
|
||||||
|
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
|
||||||
|
|
||||||
|
// For singular messages and builders, one bit is used for the hasField bit.
|
||||||
|
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_has_field_bit_builder"] =
|
||||||
|
GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repated builders, one bit is used for whether the array is immutable.
|
||||||
|
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repeated fields, one bit is used for whether the array is immutable
|
||||||
|
// in the parsing constructor.
|
||||||
|
(*variables)["get_mutable_bit_parser"] =
|
||||||
|
GenerateGetBitMutableLocal(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_parser"] =
|
||||||
|
GenerateSetBitMutableLocal(builderBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_from_local"] =
|
||||||
|
GenerateGetBitFromLocal(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_to_local"] =
|
||||||
|
GenerateSetBitToLocal(messageBitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
PrimitiveFieldGenerator::
|
||||||
|
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
||||||
|
|
||||||
|
int PrimitiveFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrimitiveFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$boolean has$capitalized_name$();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $field_type$ $name$_;\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_message$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $field_type$ $name$_ $default_init$;\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_builder$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $clear_has_field_bit_builder$;\n");
|
||||||
|
JavaType type = GetJavaType(descriptor_);
|
||||||
|
if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
|
||||||
|
// The default value is not a simple literal so we want to avoid executing
|
||||||
|
// it multiple times. Instead, get the default out of the default instance.
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $name$_ = getDefaultInstance().get$capitalized_name$();\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for primitives
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = $default$;\n"
|
||||||
|
"$clear_has_field_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (other.has$capitalized_name$()) {\n"
|
||||||
|
" set$capitalized_name$(other.get$capitalized_name$());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_from_local$) {\n"
|
||||||
|
" $set_has_field_bit_to_local$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$set_has_field_bit_message$;\n"
|
||||||
|
"$name$_ = input.read$capitalized_type$();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
// noop for primitives.
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" output.write$capitalized_type$($number$, $name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .compute$capitalized_type$Size($number$, $name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
switch (GetJavaType(descriptor_)) {
|
||||||
|
case JAVATYPE_INT:
|
||||||
|
case JAVATYPE_LONG:
|
||||||
|
case JAVATYPE_BOOLEAN:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && (get$capitalized_name$()\n"
|
||||||
|
" == other.get$capitalized_name$());\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_FLOAT:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && (Float.floatToIntBits(get$capitalized_name$())"
|
||||||
|
" == Float.floatToIntBits(other.get$capitalized_name$()));\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_DOUBLE:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && (Double.doubleToLongBits(get$capitalized_name$())"
|
||||||
|
" == Double.doubleToLongBits(other.get$capitalized_name$()));\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_STRING:
|
||||||
|
case JAVATYPE_BYTES:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$()\n"
|
||||||
|
" .equals(other.get$capitalized_name$());\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_ENUM:
|
||||||
|
case JAVATYPE_MESSAGE:
|
||||||
|
default:
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (37 * hash) + $constant_name$;\n");
|
||||||
|
switch (GetJavaType(descriptor_)) {
|
||||||
|
case JAVATYPE_INT:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + get$capitalized_name$();\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_LONG:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + hashLong(get$capitalized_name$());\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_BOOLEAN:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_FLOAT:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + Float.floatToIntBits(\n"
|
||||||
|
" get$capitalized_name$());\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_DOUBLE:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + hashLong(\n"
|
||||||
|
" Double.doubleToLongBits(get$capitalized_name$()));\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_STRING:
|
||||||
|
case JAVATYPE_BYTES:
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JAVATYPE_ENUM:
|
||||||
|
case JAVATYPE_MESSAGE:
|
||||||
|
default:
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string PrimitiveFieldGenerator::GetBoxedType() const {
|
||||||
|
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator::
|
||||||
|
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
|
||||||
|
|
||||||
|
int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$int get$capitalized_name$Count();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$$type$ get$capitalized_name$(int index);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $field_list_type$ $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<$boxed_type$>\n"
|
||||||
|
" get$capitalized_name$List() {\n"
|
||||||
|
" return $name$_;\n" // note: unmodifiable list
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed() &&
|
||||||
|
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private int $name$MemoizedSerializedSize = -1;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
// One field is the list and the bit field keeps track of whether the
|
||||||
|
// list is immutable. If it's immutable, the invariant is that it must
|
||||||
|
// either an instance of Collections.emptyList() or it's an ArrayList
|
||||||
|
// wrapped in a Collections.unmodifiableList() wrapper and nobody else has
|
||||||
|
// a refererence to the underlying ArrayList. This invariant allows us to
|
||||||
|
// share instances of lists between protocol buffers avoiding expensive
|
||||||
|
// memory allocations. Note, immutable is a strong guarantee here -- not
|
||||||
|
// just that the list cannot be modified via the reference but that the
|
||||||
|
// list can never be modified.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private $field_list_type$ $name$_ = $empty_list$;\n");
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private void ensure$capitalized_name$IsMutable() {\n"
|
||||||
|
" if (!$get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n"
|
||||||
|
" $set_mutable_bit_builder$;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
// Note: We return an unmodifiable list because otherwise the caller
|
||||||
|
// could hold on to the returned list and modify it after the message
|
||||||
|
// has been built, thus mutating the message which is supposed to be
|
||||||
|
// immutable.
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<$boxed_type$>\n"
|
||||||
|
" get$capitalized_name$List() {\n"
|
||||||
|
" return java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" int index, $type$ value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.set(index, value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.add(value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder addAll$capitalized_name$(\n"
|
||||||
|
" java.lang.Iterable<? extends $boxed_type$> values) {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" super.addAll(values, $name$_);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $name$_ = $empty_list$;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for primitives
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $empty_list$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = $empty_list$;\n"
|
||||||
|
"$clear_mutable_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
// The code below does two optimizations:
|
||||||
|
// 1. If the other list is empty, there's nothing to do. This ensures we
|
||||||
|
// don't allocate a new array if we already have an immutable one.
|
||||||
|
// 2. If the other list is non-empty and our current list is empty, we can
|
||||||
|
// reuse the other list which is guaranteed to be immutable.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!other.$name$_.isEmpty()) {\n"
|
||||||
|
" if ($name$_.isEmpty()) {\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.addAll(other.$name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
// The code below ensures that the result has an immutable list. If our
|
||||||
|
// list is immutable, we can just reuse it. If not, we make it immutable.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!$get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
"}\n"
|
||||||
|
"$name$_.add(input.read$capitalized_type$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int length = input.readRawVarint32();\n"
|
||||||
|
"int limit = input.pushLimit(length);\n"
|
||||||
|
"if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
|
||||||
|
" $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
"}\n"
|
||||||
|
"while (input.getBytesUntilLimit() > 0) {\n"
|
||||||
|
" $name$_.add(input.read$capitalized_type$());\n"
|
||||||
|
"}\n"
|
||||||
|
"input.popLimit(limit);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$List().size() > 0) {\n"
|
||||||
|
" output.writeRawVarint32($tag$);\n"
|
||||||
|
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
||||||
|
"}\n"
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.write$capitalized_type$NoTag($name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.write$capitalized_type$($number$, $name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"{\n"
|
||||||
|
" int dataSize = 0;\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
if (FixedSize(GetType(descriptor_)) == -1) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"size += dataSize;\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!get$capitalized_name$List().isEmpty()) {\n"
|
||||||
|
" size += $tag_size$;\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeInt32SizeNoTag(dataSize);\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"size += $tag_size$ * get$capitalized_name$List().size();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the data size for packed fields.
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$MemoizedSerializedSize = dataSize;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$List()\n"
|
||||||
|
" .equals(other.get$capitalized_name$List());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$Count() > 0) {\n"
|
||||||
|
" hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
" hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
|
||||||
|
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -46,49 +46,71 @@ namespace java {
|
|||||||
|
|
||||||
class PrimitiveFieldGenerator : public FieldGenerator {
|
class PrimitiveFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~PrimitiveFieldGenerator();
|
~PrimitiveFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||||
public:
|
public:
|
||||||
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
~RepeatedPrimitiveFieldGenerator();
|
~RepeatedPrimitiveFieldGenerator();
|
||||||
|
|
||||||
// implements FieldGenerator ---------------------------------------
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
void GenerateMembers(io::Printer* printer) const;
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
void GenerateBuilderMembers(io::Printer* printer) const;
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
void GenerateInitializationCode(io::Printer* printer) const;
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
void GenerateMergingCode(io::Printer* printer) const;
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
void GenerateBuildingCode(io::Printer* printer) const;
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCode(io::Printer* printer) const;
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
void GenerateSerializationCode(io::Printer* printer) const;
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
|
||||||
string GetBoxedType() const;
|
string GetBoxedType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FieldDescriptor* descriptor_;
|
const FieldDescriptor* descriptor_;
|
||||||
map<string, string> variables_;
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
|
||||||
};
|
};
|
@ -33,6 +33,7 @@
|
|||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
#include <google/protobuf/compiler/java/java_service.h>
|
#include <google/protobuf/compiler/java/java_service.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
@ -50,6 +51,7 @@ ServiceGenerator::~ServiceGenerator() {}
|
|||||||
|
|
||||||
void ServiceGenerator::Generate(io::Printer* printer) {
|
void ServiceGenerator::Generate(io::Printer* printer) {
|
||||||
bool is_own_file = descriptor_->file()->options().java_multiple_files();
|
bool is_own_file = descriptor_->file()->options().java_multiple_files();
|
||||||
|
WriteServiceDocComment(printer, descriptor_);
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"public $static$ abstract class $classname$\n"
|
"public $static$ abstract class $classname$\n"
|
||||||
" implements com.google.protobuf.Service {\n",
|
" implements com.google.protobuf.Service {\n",
|
||||||
@ -86,6 +88,12 @@ void ServiceGenerator::Generate(io::Printer* printer) {
|
|||||||
GenerateStub(printer);
|
GenerateStub(printer);
|
||||||
GenerateBlockingStub(printer);
|
GenerateBlockingStub(printer);
|
||||||
|
|
||||||
|
// Add an insertion point.
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
|
||||||
|
"full_name", descriptor_->full_name());
|
||||||
|
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n\n");
|
printer->Print("}\n\n");
|
||||||
}
|
}
|
||||||
@ -118,7 +126,7 @@ void ServiceGenerator::GenerateNewReflectiveServiceMethod(
|
|||||||
|
|
||||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
const MethodDescriptor* method = descriptor_->method(i);
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
printer->Print("@Override\n");
|
printer->Print("@java.lang.Override\n");
|
||||||
GenerateMethodSignature(printer, method, IS_CONCRETE);
|
GenerateMethodSignature(printer, method, IS_CONCRETE);
|
||||||
printer->Print(
|
printer->Print(
|
||||||
" {\n"
|
" {\n"
|
||||||
@ -157,6 +165,7 @@ void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
|
|||||||
void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
|
void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
|
||||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
const MethodDescriptor* method = descriptor_->method(i);
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
WriteMethodDocComment(printer, method);
|
||||||
GenerateMethodSignature(printer, method, IS_ABSTRACT);
|
GenerateMethodSignature(printer, method, IS_ABSTRACT);
|
||||||
printer->Print(";\n\n");
|
printer->Print(";\n\n");
|
||||||
}
|
}
|
@ -0,0 +1,726 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Author: jonp@google.com (Jon Perlow)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/java/java_string_field.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
using internal::WireFormatLite;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
(*variables)["name"] =
|
||||||
|
UnderscoresToCamelCase(descriptor);
|
||||||
|
(*variables)["capitalized_name"] =
|
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||||
|
(*variables)["constant_name"] = FieldConstantName(descriptor);
|
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
|
(*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
|
||||||
|
|
||||||
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["default_init"] = ("= " + DefaultValue(descriptor));
|
||||||
|
(*variables)["capitalized_type"] = "String";
|
||||||
|
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
|
||||||
|
(*variables)["tag_size"] = SimpleItoa(
|
||||||
|
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
||||||
|
(*variables)["null_check"] =
|
||||||
|
" if (value == null) {\n"
|
||||||
|
" throw new NullPointerException();\n"
|
||||||
|
" }\n";
|
||||||
|
|
||||||
|
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
|
||||||
|
// by the proto compiler
|
||||||
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
|
? "@java.lang.Deprecated " : "";
|
||||||
|
(*variables)["on_changed"] =
|
||||||
|
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
|
||||||
|
|
||||||
|
// For singular messages and builders, one bit is used for the hasField bit.
|
||||||
|
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_has_field_bit_builder"] =
|
||||||
|
GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repated builders, one bit is used for whether the array is immutable.
|
||||||
|
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||||
|
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
|
||||||
|
|
||||||
|
// For repeated fields, one bit is used for whether the array is immutable
|
||||||
|
// in the parsing constructor.
|
||||||
|
(*variables)["get_mutable_bit_parser"] =
|
||||||
|
GenerateGetBitMutableLocal(builderBitIndex);
|
||||||
|
(*variables)["set_mutable_bit_parser"] =
|
||||||
|
GenerateSetBitMutableLocal(builderBitIndex);
|
||||||
|
|
||||||
|
(*variables)["get_has_field_bit_from_local"] =
|
||||||
|
GenerateGetBitFromLocal(builderBitIndex);
|
||||||
|
(*variables)["set_has_field_bit_to_local"] =
|
||||||
|
GenerateSetBitToLocal(messageBitIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
StringFieldGenerator::
|
||||||
|
StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringFieldGenerator::~StringFieldGenerator() {}
|
||||||
|
|
||||||
|
int StringFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A note about how strings are handled. This code used to just store a String
|
||||||
|
// in the Message. This had two issues:
|
||||||
|
//
|
||||||
|
// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
|
||||||
|
// strings, but rather fields that were raw bytes incorrectly marked
|
||||||
|
// as strings in the proto file. This is common because in the proto1
|
||||||
|
// syntax, string was the way to indicate bytes and C++ engineers can
|
||||||
|
// easily make this mistake without affecting the C++ API. By converting to
|
||||||
|
// strings immediately, some java code might corrupt these byte arrays as
|
||||||
|
// it passes through a java server even if the field was never accessed by
|
||||||
|
// application code.
|
||||||
|
//
|
||||||
|
// 2. There's a performance hit to converting between bytes and strings and
|
||||||
|
// it many cases, the field is never even read by the application code. This
|
||||||
|
// avoids unnecessary conversions in the common use cases.
|
||||||
|
//
|
||||||
|
// So now, the field for String is maintained as an Object reference which can
|
||||||
|
// either store a String or a ByteString. The code uses an instanceof check
|
||||||
|
// to see which one it has and converts to the other one if needed. It remembers
|
||||||
|
// the last value requested (in a thread safe manner) as this is most likely
|
||||||
|
// the one needed next. The thread safety is such that if two threads both
|
||||||
|
// convert the field because the changes made by each thread were not visible to
|
||||||
|
// the other, they may cause a conversion to happen more times than would
|
||||||
|
// otherwise be necessary. This was deemed better than adding synchronization
|
||||||
|
// overhead. It will not cause any corruption issues or affect the behavior of
|
||||||
|
// the API. The instanceof check is also highly optimized in the JVM and we
|
||||||
|
// decided it was better to reduce the memory overhead by not having two
|
||||||
|
// separate fields but rather use dynamic type checking.
|
||||||
|
//
|
||||||
|
// For single fields, the logic for this is done inside the generated code. For
|
||||||
|
// repeated fields, the logic is done in LazyStringArrayList and
|
||||||
|
// UnmodifiableLazyStringList.
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$boolean has$capitalized_name$();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.lang.String get$capitalized_name$();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private java.lang.Object $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_message$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
|
||||||
|
" java.lang.Object ref = $name$_;\n"
|
||||||
|
" if (ref instanceof java.lang.String) {\n"
|
||||||
|
" return (java.lang.String) ref;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" com.google.protobuf.ByteString bs = \n"
|
||||||
|
" (com.google.protobuf.ByteString) ref;\n"
|
||||||
|
" java.lang.String s = bs.toStringUtf8();\n"
|
||||||
|
" if (bs.isValidUtf8()) {\n"
|
||||||
|
" $name$_ = s;\n"
|
||||||
|
" }\n"
|
||||||
|
" return s;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes() {\n"
|
||||||
|
" java.lang.Object ref = $name$_;\n"
|
||||||
|
" if (ref instanceof java.lang.String) {\n"
|
||||||
|
" com.google.protobuf.ByteString b = \n"
|
||||||
|
" com.google.protobuf.ByteString.copyFromUtf8(\n"
|
||||||
|
" (java.lang.String) ref);\n"
|
||||||
|
" $name$_ = b;\n"
|
||||||
|
" return b;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" return (com.google.protobuf.ByteString) ref;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private java.lang.Object $name$_ $default_init$;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||||
|
" return $get_has_field_bit_builder$;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
|
||||||
|
" java.lang.Object ref = $name$_;\n"
|
||||||
|
" if (!(ref instanceof java.lang.String)) {\n"
|
||||||
|
" java.lang.String s = ((com.google.protobuf.ByteString) ref)\n"
|
||||||
|
" .toStringUtf8();\n"
|
||||||
|
" $name$_ = s;\n"
|
||||||
|
" return s;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" return (java.lang.String) ref;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes() {\n"
|
||||||
|
" java.lang.Object ref = $name$_;\n"
|
||||||
|
" if (ref instanceof String) {\n"
|
||||||
|
" com.google.protobuf.ByteString b = \n"
|
||||||
|
" com.google.protobuf.ByteString.copyFromUtf8(\n"
|
||||||
|
" (java.lang.String) ref);\n"
|
||||||
|
" $name$_ = b;\n"
|
||||||
|
" return b;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" return (com.google.protobuf.ByteString) ref;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" java.lang.String value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $clear_has_field_bit_builder$;\n");
|
||||||
|
// The default value is not a simple literal so we want to avoid executing
|
||||||
|
// it multiple times. Instead, get the default out of the default instance.
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $name$_ = getDefaultInstance().get$capitalized_name$();\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$Bytes(\n"
|
||||||
|
" com.google.protobuf.ByteString value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for primitives
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = $default$;\n"
|
||||||
|
"$clear_has_field_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
// Allow a slight breach of abstraction here in order to avoid forcing
|
||||||
|
// all string fields to Strings when copying fields from a Message.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (other.has$capitalized_name$()) {\n"
|
||||||
|
" $set_has_field_bit_builder$;\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_from_local$) {\n"
|
||||||
|
" $set_has_field_bit_to_local$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$set_has_field_bit_message$;\n"
|
||||||
|
"$name$_ = input.readBytes();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
// noop for strings.
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" output.writeBytes($number$, get$capitalized_name$Bytes());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_has_field_bit_message$) {\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$()\n"
|
||||||
|
" .equals(other.get$capitalized_name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (37 * hash) + $constant_name$;\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string StringFieldGenerator::GetBoxedType() const {
|
||||||
|
return "java.lang.String";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedStringFieldGenerator::
|
||||||
|
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex,
|
||||||
|
int builderBitIndex)
|
||||||
|
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||||
|
builderBitIndex_(builderBitIndex) {
|
||||||
|
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
|
||||||
|
&variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
||||||
|
|
||||||
|
int RepeatedStringFieldGenerator::GetNumBitsForMessage() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.util.List<java.lang.String>\n"
|
||||||
|
"get$capitalized_name$List();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$int get$capitalized_name$Count();\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$java.lang.String get$capitalized_name$(int index);\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes(int index);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private com.google.protobuf.LazyStringList $name$_;\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<java.lang.String>\n"
|
||||||
|
" get$capitalized_name$List() {\n"
|
||||||
|
" return $name$_;\n" // note: unmodifiable list
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes(int index) {\n"
|
||||||
|
" return $name$_.getByteString(index);\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed() &&
|
||||||
|
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private int $name$MemoizedSerializedSize = -1;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateBuilderMembers(io::Printer* printer) const {
|
||||||
|
// One field is the list and the bit field keeps track of whether the
|
||||||
|
// list is immutable. If it's immutable, the invariant is that it must
|
||||||
|
// either an instance of Collections.emptyList() or it's an ArrayList
|
||||||
|
// wrapped in a Collections.unmodifiableList() wrapper and nobody else has
|
||||||
|
// a refererence to the underlying ArrayList. This invariant allows us to
|
||||||
|
// share instances of lists between protocol buffers avoiding expensive
|
||||||
|
// memory allocations. Note, immutable is a strong guarantee here -- not
|
||||||
|
// just that the list cannot be modified via the reference but that the
|
||||||
|
// list can never be modified.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"private void ensure$capitalized_name$IsMutable() {\n"
|
||||||
|
" if (!$get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
|
||||||
|
" $set_mutable_bit_builder$;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
// Note: We return an unmodifiable list because otherwise the caller
|
||||||
|
// could hold on to the returned list and modify it after the message
|
||||||
|
// has been built, thus mutating the message which is supposed to be
|
||||||
|
// immutable.
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.util.List<java.lang.String>\n"
|
||||||
|
" get$capitalized_name$List() {\n"
|
||||||
|
" return java.util.Collections.unmodifiableList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||||
|
" return $name$_.size();\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
|
||||||
|
" return $name$_.get(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public com.google.protobuf.ByteString\n"
|
||||||
|
" get$capitalized_name$Bytes(int index) {\n"
|
||||||
|
" return $name$_.getByteString(index);\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||||
|
" int index, java.lang.String value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.set(index, value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$(\n"
|
||||||
|
" java.lang.String value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.add(value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder addAll$capitalized_name$(\n"
|
||||||
|
" java.lang.Iterable<java.lang.String> values) {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" super.addAll(values, $name$_);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||||
|
" $name$_ = $empty_list$;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
WriteFieldDocComment(printer, descriptor_);
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$deprecation$public Builder add$capitalized_name$Bytes(\n"
|
||||||
|
" com.google.protobuf.ByteString value) {\n"
|
||||||
|
"$null_check$"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.add(value);\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
" return this;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||||
|
// noop for primitives
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateInitializationCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $empty_list$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = $empty_list$;\n"
|
||||||
|
"$clear_mutable_bit_builder$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
// The code below does two optimizations:
|
||||||
|
// 1. If the other list is empty, there's nothing to do. This ensures we
|
||||||
|
// don't allocate a new array if we already have an immutable one.
|
||||||
|
// 2. If the other list is non-empty and our current list is empty, we can
|
||||||
|
// reuse the other list which is guaranteed to be immutable.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!other.$name$_.isEmpty()) {\n"
|
||||||
|
" if ($name$_.isEmpty()) {\n"
|
||||||
|
" $name$_ = other.$name$_;\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ensure$capitalized_name$IsMutable();\n"
|
||||||
|
" $name$_.addAll(other.$name$_);\n"
|
||||||
|
" }\n"
|
||||||
|
" $on_changed$\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateBuildingCode(io::Printer* printer) const {
|
||||||
|
// The code below ensures that the result has an immutable list. If our
|
||||||
|
// list is immutable, we can just reuse it. If not, we make it immutable.
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_builder$) {\n"
|
||||||
|
" $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n"
|
||||||
|
" $name$_);\n"
|
||||||
|
" $clear_mutable_bit_builder$;\n"
|
||||||
|
"}\n"
|
||||||
|
"result.$name$_ = $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateParsingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!$get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
"}\n"
|
||||||
|
"$name$_.add(input.readBytes());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int length = input.readRawVarint32();\n"
|
||||||
|
"int limit = input.pushLimit(length);\n"
|
||||||
|
"if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
|
||||||
|
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
|
||||||
|
" $set_mutable_bit_parser$;\n"
|
||||||
|
"}\n"
|
||||||
|
"while (input.getBytesUntilLimit() > 0) {\n"
|
||||||
|
" $name$.add(input.read$capitalized_type$());\n"
|
||||||
|
"}\n"
|
||||||
|
"input.popLimit(limit);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($get_mutable_bit_parser$) {\n"
|
||||||
|
" $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateSerializationCode(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$List().size() > 0) {\n"
|
||||||
|
" output.writeRawVarint32($tag$);\n"
|
||||||
|
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
||||||
|
"}\n"
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.write$capitalized_type$NoTag($name$_.get(i));\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" output.writeBytes($number$, $name$_.getByteString(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"{\n"
|
||||||
|
" int dataSize = 0;\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||||
|
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeBytesSizeNoTag($name$_.getByteString(i));\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"size += dataSize;\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (!get$capitalized_name$List().isEmpty()) {\n"
|
||||||
|
" size += $tag_size$;\n"
|
||||||
|
" size += com.google.protobuf.CodedOutputStream\n"
|
||||||
|
" .computeInt32SizeNoTag(dataSize);\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"size += $tag_size$ * get$capitalized_name$List().size();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the data size for packed fields.
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$MemoizedSerializedSize = dataSize;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateEqualsCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"result = result && get$capitalized_name$List()\n"
|
||||||
|
" .equals(other.get$capitalized_name$List());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateHashCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (get$capitalized_name$Count() > 0) {\n"
|
||||||
|
" hash = (37 * hash) + $constant_name$;\n"
|
||||||
|
" hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string RepeatedStringFieldGenerator::GetBoxedType() const {
|
||||||
|
return "String";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,122 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Author: jonp@google.com (Jon Perlow)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/java/java_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace java {
|
||||||
|
|
||||||
|
class StringFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
|
~StringFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
string GetBoxedType() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||||
|
int messageBitIndex, int builderBitIndex);
|
||||||
|
~RepeatedStringFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
int GetNumBitsForMessage() const;
|
||||||
|
int GetNumBitsForBuilder() const;
|
||||||
|
void GenerateInterfaceMembers(io::Printer* printer) const;
|
||||||
|
void GenerateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderMembers(io::Printer* printer) const;
|
||||||
|
void GenerateInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuilderClearCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateBuildingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingCode(io::Printer* printer) const;
|
||||||
|
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
|
||||||
|
void GenerateParsingDoneCode(io::Printer* printer) const;
|
||||||
|
void GenerateSerializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const;
|
||||||
|
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
|
||||||
|
void GenerateEqualsCode(io::Printer* printer) const;
|
||||||
|
void GenerateHashCode(io::Printer* printer) const;
|
||||||
|
string GetBoxedType() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
const int messageBitIndex_;
|
||||||
|
const int builderBitIndex_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
|
@ -43,7 +43,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Proto2 C++
|
// Proto2 C++
|
||||||
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
||||||
cli.RegisterGenerator("--cpp_out", &cpp_generator,
|
cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
|
||||||
"Generate C++ header and source.");
|
"Generate C++ header and source.");
|
||||||
|
|
||||||
// Proto2 Java
|
// Proto2 Java
|
@ -33,18 +33,29 @@
|
|||||||
#include <google/protobuf/compiler/mock_code_generator.h>
|
#include <google/protobuf/compiler/mock_code_generator.h>
|
||||||
|
|
||||||
#include <google/protobuf/testing/file.h>
|
#include <google/protobuf/testing/file.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <google/protobuf/stubs/stl_util-inl.h>
|
#include <google/protobuf/stubs/stl_util.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
|
// Returns the list of the names of files in all_files in the form of a
|
||||||
|
// comma-separated string.
|
||||||
|
string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
|
||||||
|
vector<string> names;
|
||||||
|
for (int i = 0; i < all_files.size(); i++) {
|
||||||
|
names.push_back(all_files[i]->name());
|
||||||
|
}
|
||||||
|
return JoinStrings(names, ",");
|
||||||
|
}
|
||||||
|
|
||||||
static const char* kFirstInsertionPointName = "first_mock_insertion_point";
|
static const char* kFirstInsertionPointName = "first_mock_insertion_point";
|
||||||
static const char* kSecondInsertionPointName = "second_mock_insertion_point";
|
static const char* kSecondInsertionPointName = "second_mock_insertion_point";
|
||||||
static const char* kFirstInsertionPoint =
|
static const char* kFirstInsertionPoint =
|
||||||
@ -63,6 +74,7 @@ void MockCodeGenerator::ExpectGenerated(
|
|||||||
const string& insertions,
|
const string& insertions,
|
||||||
const string& file,
|
const string& file,
|
||||||
const string& first_message_name,
|
const string& first_message_name,
|
||||||
|
const string& first_parsed_file_name,
|
||||||
const string& output_directory) {
|
const string& output_directory) {
|
||||||
string content;
|
string content;
|
||||||
ASSERT_TRUE(File::ReadFileToString(
|
ASSERT_TRUE(File::ReadFileToString(
|
||||||
@ -84,7 +96,8 @@ void MockCodeGenerator::ExpectGenerated(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
|
ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
|
||||||
EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name),
|
EXPECT_EQ(GetOutputFileContent(name, parameter, file,
|
||||||
|
first_parsed_file_name, first_message_name),
|
||||||
lines[0]);
|
lines[0]);
|
||||||
|
|
||||||
EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
|
EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
|
||||||
@ -92,12 +105,12 @@ void MockCodeGenerator::ExpectGenerated(
|
|||||||
|
|
||||||
for (int i = 0; i < insertion_list.size(); i++) {
|
for (int i = 0; i < insertion_list.size(); i++) {
|
||||||
EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
|
EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
|
||||||
file, first_message_name),
|
file, file, first_message_name),
|
||||||
lines[1 + i]);
|
lines[1 + i]);
|
||||||
// Second insertion point is indented, so the inserted text should
|
// Second insertion point is indented, so the inserted text should
|
||||||
// automatically be indented too.
|
// automatically be indented too.
|
||||||
EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
|
EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
|
||||||
file, first_message_name),
|
file, file, first_message_name),
|
||||||
lines[2 + insertion_list.size() + i]);
|
lines[2 + insertion_list.size() + i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +118,7 @@ void MockCodeGenerator::ExpectGenerated(
|
|||||||
bool MockCodeGenerator::Generate(
|
bool MockCodeGenerator::Generate(
|
||||||
const FileDescriptor* file,
|
const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
for (int i = 0; i < file->message_type_count(); i++) {
|
for (int i = 0; i < file->message_type_count(); i++) {
|
||||||
if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
|
if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
|
||||||
@ -120,6 +133,15 @@ bool MockCodeGenerator::Generate(
|
|||||||
} else if (command == "Abort") {
|
} else if (command == "Abort") {
|
||||||
cerr << "Saw message type MockCodeGenerator_Abort." << endl;
|
cerr << "Saw message type MockCodeGenerator_Abort." << endl;
|
||||||
abort();
|
abort();
|
||||||
|
} else if (command == "HasSourceCodeInfo") {
|
||||||
|
FileDescriptorProto file_descriptor_proto;
|
||||||
|
file->CopySourceCodeInfoTo(&file_descriptor_proto);
|
||||||
|
bool has_source_code_info =
|
||||||
|
file_descriptor_proto.has_source_code_info() &&
|
||||||
|
file_descriptor_proto.source_code_info().location_size() > 0;
|
||||||
|
cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
|
||||||
|
<< has_source_code_info << "." << endl;
|
||||||
|
abort();
|
||||||
} else {
|
} else {
|
||||||
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
|
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
|
||||||
}
|
}
|
||||||
@ -134,11 +156,12 @@ bool MockCodeGenerator::Generate(
|
|||||||
for (int i = 0; i < insert_into.size(); i++) {
|
for (int i = 0; i < insert_into.size(); i++) {
|
||||||
{
|
{
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->OpenForInsert(
|
context->OpenForInsert(
|
||||||
GetOutputFileName(insert_into[i], file),
|
GetOutputFileName(insert_into[i], file),
|
||||||
kFirstInsertionPointName));
|
kFirstInsertionPointName));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file));
|
printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
|
||||||
|
file, context));
|
||||||
if (printer.failed()) {
|
if (printer.failed()) {
|
||||||
*error = "MockCodeGenerator detected write error.";
|
*error = "MockCodeGenerator detected write error.";
|
||||||
return false;
|
return false;
|
||||||
@ -147,11 +170,12 @@ bool MockCodeGenerator::Generate(
|
|||||||
|
|
||||||
{
|
{
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->OpenForInsert(
|
context->OpenForInsert(
|
||||||
GetOutputFileName(insert_into[i], file),
|
GetOutputFileName(insert_into[i], file),
|
||||||
kSecondInsertionPointName));
|
kSecondInsertionPointName));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file));
|
printer.PrintRaw(GetOutputFileContent(name_, "second_insert",
|
||||||
|
file, context));
|
||||||
if (printer.failed()) {
|
if (printer.failed()) {
|
||||||
*error = "MockCodeGenerator detected write error.";
|
*error = "MockCodeGenerator detected write error.";
|
||||||
return false;
|
return false;
|
||||||
@ -160,10 +184,11 @@ bool MockCodeGenerator::Generate(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->Open(GetOutputFileName(name_, file)));
|
context->Open(GetOutputFileName(name_, file)));
|
||||||
|
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.PrintRaw(GetOutputFileContent(name_, parameter, file));
|
printer.PrintRaw(GetOutputFileContent(name_, parameter,
|
||||||
|
file, context));
|
||||||
printer.PrintRaw(kFirstInsertionPoint);
|
printer.PrintRaw(kFirstInsertionPoint);
|
||||||
printer.PrintRaw(kSecondInsertionPoint);
|
printer.PrintRaw(kSecondInsertionPoint);
|
||||||
|
|
||||||
@ -186,11 +211,16 @@ string MockCodeGenerator::GetOutputFileName(const string& generator_name,
|
|||||||
return file + ".MockCodeGenerator." + generator_name;
|
return file + ".MockCodeGenerator." + generator_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
string MockCodeGenerator::GetOutputFileContent(const string& generator_name,
|
string MockCodeGenerator::GetOutputFileContent(
|
||||||
const string& parameter,
|
const string& generator_name,
|
||||||
const FileDescriptor* file) {
|
const string& parameter,
|
||||||
|
const FileDescriptor* file,
|
||||||
|
GeneratorContext *context) {
|
||||||
|
vector<const FileDescriptor*> all_files;
|
||||||
|
context->ListParsedFiles(&all_files);
|
||||||
return GetOutputFileContent(
|
return GetOutputFileContent(
|
||||||
generator_name, parameter, file->name(),
|
generator_name, parameter, file->name(),
|
||||||
|
CommaSeparatedList(all_files),
|
||||||
file->message_type_count() > 0 ?
|
file->message_type_count() > 0 ?
|
||||||
file->message_type(0)->name() : "(none)");
|
file->message_type(0)->name() : "(none)");
|
||||||
}
|
}
|
||||||
@ -199,9 +229,11 @@ string MockCodeGenerator::GetOutputFileContent(
|
|||||||
const string& generator_name,
|
const string& generator_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
const string& file,
|
const string& file,
|
||||||
|
const string& parsed_file_list,
|
||||||
const string& first_message_name) {
|
const string& first_message_name) {
|
||||||
return strings::Substitute("$0: $1, $2, $3\n",
|
return strings::Substitute("$0: $1, $2, $3, $4\n",
|
||||||
generator_name, parameter, file, first_message_name);
|
generator_name, parameter, file,
|
||||||
|
first_message_name, parsed_file_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
@ -59,6 +59,10 @@ namespace compiler {
|
|||||||
// MockCodeGenerator_Exit." to stderr and then calls exit(123).
|
// MockCodeGenerator_Exit." to stderr and then calls exit(123).
|
||||||
// MockCodeGenerator_Abort: Generate() prints "Saw message type
|
// MockCodeGenerator_Abort: Generate() prints "Saw message type
|
||||||
// MockCodeGenerator_Abort." to stderr and then calls abort().
|
// MockCodeGenerator_Abort." to stderr and then calls abort().
|
||||||
|
// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after
|
||||||
|
// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
|
||||||
|
// stderr, where FOO is "1" if the supplied FileDescriptorProto has source
|
||||||
|
// code info, and "0" otherwise.
|
||||||
class MockCodeGenerator : public CodeGenerator {
|
class MockCodeGenerator : public CodeGenerator {
|
||||||
public:
|
public:
|
||||||
MockCodeGenerator(const string& name);
|
MockCodeGenerator(const string& name);
|
||||||
@ -69,11 +73,14 @@ class MockCodeGenerator : public CodeGenerator {
|
|||||||
//
|
//
|
||||||
// |insertions| is a comma-separated list of names of MockCodeGenerators which
|
// |insertions| is a comma-separated list of names of MockCodeGenerators which
|
||||||
// should have inserted lines into this file.
|
// should have inserted lines into this file.
|
||||||
|
// |parsed_file_list| is a comma-separated list of names of the files
|
||||||
|
// that are being compiled together in this run.
|
||||||
static void ExpectGenerated(const string& name,
|
static void ExpectGenerated(const string& name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
const string& insertions,
|
const string& insertions,
|
||||||
const string& file,
|
const string& file,
|
||||||
const string& first_message_name,
|
const string& first_message_name,
|
||||||
|
const string& parsed_file_list,
|
||||||
const string& output_directory);
|
const string& output_directory);
|
||||||
|
|
||||||
// Get the name of the file which would be written by the given generator.
|
// Get the name of the file which would be written by the given generator.
|
||||||
@ -86,7 +93,7 @@ class MockCodeGenerator : public CodeGenerator {
|
|||||||
|
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const;
|
string* error) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -94,10 +101,12 @@ class MockCodeGenerator : public CodeGenerator {
|
|||||||
|
|
||||||
static string GetOutputFileContent(const string& generator_name,
|
static string GetOutputFileContent(const string& generator_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
const FileDescriptor* file);
|
const FileDescriptor* file,
|
||||||
|
GeneratorContext *context);
|
||||||
static string GetOutputFileContent(const string& generator_name,
|
static string GetOutputFileContent(const string& generator_name,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
const string& file,
|
const string& file,
|
||||||
|
const string& parsed_file_list,
|
||||||
const string& first_message_name);
|
const string& first_message_name);
|
||||||
};
|
};
|
||||||
|
|
1611
common/protobuf-2.5.0/src/google/protobuf/compiler/parser.cc
Normal file
1611
common/protobuf-2.5.0/src/google/protobuf/compiler/parser.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -74,6 +74,9 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
|
|
||||||
// Optional fetaures:
|
// Optional fetaures:
|
||||||
|
|
||||||
|
// DEPRECATED: New code should use the SourceCodeInfo embedded in the
|
||||||
|
// FileDescriptorProto.
|
||||||
|
//
|
||||||
// Requests that locations of certain definitions be recorded to the given
|
// Requests that locations of certain definitions be recorded to the given
|
||||||
// SourceLocationTable while parsing. This can be used to look up exact line
|
// SourceLocationTable while parsing. This can be used to look up exact line
|
||||||
// and column numbers for errors reported by DescriptorPool during validation.
|
// and column numbers for errors reported by DescriptorPool during validation.
|
||||||
@ -82,7 +85,7 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
source_location_table_ = location_table;
|
source_location_table_ = location_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Requsets that errors be recorded to the given ErrorCollector while
|
// Requests that errors be recorded to the given ErrorCollector while
|
||||||
// parsing. Set to NULL (the default) to discard error messages.
|
// parsing. Set to NULL (the default) to discard error messages.
|
||||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||||
error_collector_ = error_collector;
|
error_collector_ = error_collector;
|
||||||
@ -113,6 +116,8 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class LocationRecorder;
|
||||||
|
|
||||||
// =================================================================
|
// =================================================================
|
||||||
// Error recovery helpers
|
// Error recovery helpers
|
||||||
|
|
||||||
@ -161,6 +166,8 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
bool ConsumeIdentifier(string* output, const char* error);
|
bool ConsumeIdentifier(string* output, const char* error);
|
||||||
// Consume an integer and store its value in "output".
|
// Consume an integer and store its value in "output".
|
||||||
bool ConsumeInteger(int* output, const char* error);
|
bool ConsumeInteger(int* output, const char* error);
|
||||||
|
// Consume a signed integer and store its value in "output".
|
||||||
|
bool ConsumeSignedInteger(int* output, const char* error);
|
||||||
// Consume a 64-bit integer and store its value in "output". If the value
|
// Consume a 64-bit integer and store its value in "output". If the value
|
||||||
// is greater than max_value, an error will be reported.
|
// is greater than max_value, an error will be reported.
|
||||||
bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
|
bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
|
||||||
@ -170,6 +177,20 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
// Consume a string literal and store its (unescaped) value in "output".
|
// Consume a string literal and store its (unescaped) value in "output".
|
||||||
bool ConsumeString(string* output, const char* error);
|
bool ConsumeString(string* output, const char* error);
|
||||||
|
|
||||||
|
// Consume a token representing the end of the statement. Comments between
|
||||||
|
// this token and the next will be harvested for documentation. The given
|
||||||
|
// LocationRecorder should refer to the declaration that was just parsed;
|
||||||
|
// it will be populated with these comments.
|
||||||
|
//
|
||||||
|
// TODO(kenton): The LocationRecorder is const because historically locations
|
||||||
|
// have been passed around by const reference, for no particularly good
|
||||||
|
// reason. We should probably go through and change them all to mutable
|
||||||
|
// pointer to make this more intuitive.
|
||||||
|
bool TryConsumeEndOfDeclaration(const char* text,
|
||||||
|
const LocationRecorder* location);
|
||||||
|
bool ConsumeEndOfDeclaration(const char* text,
|
||||||
|
const LocationRecorder* location);
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// Error logging helpers
|
// Error logging helpers
|
||||||
|
|
||||||
@ -180,16 +201,64 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
// of the current token.
|
// of the current token.
|
||||||
void AddError(const string& error);
|
void AddError(const string& error);
|
||||||
|
|
||||||
// Record the given line and column and associate it with this descriptor
|
// Records a location in the SourceCodeInfo.location table (see
|
||||||
// in the SourceLocationTable.
|
// descriptor.proto). We use RAII to ensure that the start and end locations
|
||||||
void RecordLocation(const Message* descriptor,
|
// are recorded -- the constructor records the start location and the
|
||||||
DescriptorPool::ErrorCollector::ErrorLocation location,
|
// destructor records the end location. Since the parser is
|
||||||
int line, int column);
|
// recursive-descent, this works out beautifully.
|
||||||
|
class LIBPROTOBUF_EXPORT LocationRecorder {
|
||||||
|
public:
|
||||||
|
// Construct the file's "root" location.
|
||||||
|
LocationRecorder(Parser* parser);
|
||||||
|
|
||||||
// Record the current line and column and associate it with this descriptor
|
// Construct a location that represents a declaration nested within the
|
||||||
// in the SourceLocationTable.
|
// given parent. E.g. a field's location is nested within the location
|
||||||
void RecordLocation(const Message* descriptor,
|
// for a message type. The parent's path will be copied, so you should
|
||||||
DescriptorPool::ErrorCollector::ErrorLocation location);
|
// call AddPath() only to add the path components leading from the parent
|
||||||
|
// to the child (as opposed to leading from the root to the child).
|
||||||
|
LocationRecorder(const LocationRecorder& parent);
|
||||||
|
|
||||||
|
// Convenience constructors that call AddPath() one or two times.
|
||||||
|
LocationRecorder(const LocationRecorder& parent, int path1);
|
||||||
|
LocationRecorder(const LocationRecorder& parent, int path1, int path2);
|
||||||
|
|
||||||
|
~LocationRecorder();
|
||||||
|
|
||||||
|
// Add a path component. See SourceCodeInfo.Location.path in
|
||||||
|
// descriptor.proto.
|
||||||
|
void AddPath(int path_component);
|
||||||
|
|
||||||
|
// By default the location is considered to start at the current token at
|
||||||
|
// the time the LocationRecorder is created. StartAt() sets the start
|
||||||
|
// location to the given token instead.
|
||||||
|
void StartAt(const io::Tokenizer::Token& token);
|
||||||
|
|
||||||
|
// By default the location is considered to end at the previous token at
|
||||||
|
// the time the LocationRecorder is destroyed. EndAt() sets the end
|
||||||
|
// location to the given token instead.
|
||||||
|
void EndAt(const io::Tokenizer::Token& token);
|
||||||
|
|
||||||
|
// Records the start point of this location to the SourceLocationTable that
|
||||||
|
// was passed to RecordSourceLocationsTo(), if any. SourceLocationTable
|
||||||
|
// is an older way of keeping track of source locations which is still
|
||||||
|
// used in some places.
|
||||||
|
void RecordLegacyLocation(const Message* descriptor,
|
||||||
|
DescriptorPool::ErrorCollector::ErrorLocation location);
|
||||||
|
|
||||||
|
// Attaches leading and trailing comments to the location. The two strings
|
||||||
|
// will be swapped into place, so after this is called *leading and
|
||||||
|
// *trailing will be empty.
|
||||||
|
//
|
||||||
|
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
|
||||||
|
// why this is const.
|
||||||
|
void AttachComments(string* leading, string* trailing) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Parser* parser_;
|
||||||
|
SourceCodeInfo::Location* location_;
|
||||||
|
|
||||||
|
void Init(const LocationRecorder& parent);
|
||||||
|
};
|
||||||
|
|
||||||
// =================================================================
|
// =================================================================
|
||||||
// Parsers for various language constructs
|
// Parsers for various language constructs
|
||||||
@ -210,50 +279,88 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
// makes logic much simpler for the caller.
|
// makes logic much simpler for the caller.
|
||||||
|
|
||||||
// Parse a top-level message, enum, service, etc.
|
// Parse a top-level message, enum, service, etc.
|
||||||
bool ParseTopLevelStatement(FileDescriptorProto* file);
|
bool ParseTopLevelStatement(FileDescriptorProto* file,
|
||||||
|
const LocationRecorder& root_location);
|
||||||
|
|
||||||
// Parse various language high-level language construrcts.
|
// Parse various language high-level language construrcts.
|
||||||
bool ParseMessageDefinition(DescriptorProto* message);
|
bool ParseMessageDefinition(DescriptorProto* message,
|
||||||
bool ParseEnumDefinition(EnumDescriptorProto* enum_type);
|
const LocationRecorder& message_location);
|
||||||
bool ParseServiceDefinition(ServiceDescriptorProto* service);
|
bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
|
||||||
bool ParsePackage(FileDescriptorProto* file);
|
const LocationRecorder& enum_location);
|
||||||
bool ParseImport(string* import_filename);
|
bool ParseServiceDefinition(ServiceDescriptorProto* service,
|
||||||
bool ParseOption(Message* options);
|
const LocationRecorder& service_location);
|
||||||
|
bool ParsePackage(FileDescriptorProto* file,
|
||||||
|
const LocationRecorder& root_location);
|
||||||
|
bool ParseImport(RepeatedPtrField<string>* dependency,
|
||||||
|
RepeatedField<int32>* public_dependency,
|
||||||
|
RepeatedField<int32>* weak_dependency,
|
||||||
|
const LocationRecorder& root_location);
|
||||||
|
bool ParseOption(Message* options,
|
||||||
|
const LocationRecorder& options_location);
|
||||||
|
|
||||||
// These methods parse the contents of a message, enum, or service type and
|
// These methods parse the contents of a message, enum, or service type and
|
||||||
// add them to the given object. They consume the entire block including
|
// add them to the given object. They consume the entire block including
|
||||||
// the beginning and ending brace.
|
// the beginning and ending brace.
|
||||||
bool ParseMessageBlock(DescriptorProto* message);
|
bool ParseMessageBlock(DescriptorProto* message,
|
||||||
bool ParseEnumBlock(EnumDescriptorProto* enum_type);
|
const LocationRecorder& message_location);
|
||||||
bool ParseServiceBlock(ServiceDescriptorProto* service);
|
bool ParseEnumBlock(EnumDescriptorProto* enum_type,
|
||||||
|
const LocationRecorder& enum_location);
|
||||||
|
bool ParseServiceBlock(ServiceDescriptorProto* service,
|
||||||
|
const LocationRecorder& service_location);
|
||||||
|
|
||||||
// Parse one statement within a message, enum, or service block, inclunding
|
// Parse one statement within a message, enum, or service block, inclunding
|
||||||
// final semicolon.
|
// final semicolon.
|
||||||
bool ParseMessageStatement(DescriptorProto* message);
|
bool ParseMessageStatement(DescriptorProto* message,
|
||||||
bool ParseEnumStatement(EnumDescriptorProto* message);
|
const LocationRecorder& message_location);
|
||||||
bool ParseServiceStatement(ServiceDescriptorProto* message);
|
bool ParseEnumStatement(EnumDescriptorProto* message,
|
||||||
|
const LocationRecorder& enum_location);
|
||||||
|
bool ParseServiceStatement(ServiceDescriptorProto* message,
|
||||||
|
const LocationRecorder& service_location);
|
||||||
|
|
||||||
// Parse a field of a message. If the field is a group, its type will be
|
// Parse a field of a message. If the field is a group, its type will be
|
||||||
// added to "messages".
|
// added to "messages".
|
||||||
|
//
|
||||||
|
// parent_location and location_field_number_for_nested_type are needed when
|
||||||
|
// parsing groups -- we need to generate a nested message type within the
|
||||||
|
// parent and record its location accordingly. Since the parent could be
|
||||||
|
// either a FileDescriptorProto or a DescriptorProto, we must pass in the
|
||||||
|
// correct field number to use.
|
||||||
bool ParseMessageField(FieldDescriptorProto* field,
|
bool ParseMessageField(FieldDescriptorProto* field,
|
||||||
RepeatedPtrField<DescriptorProto>* messages);
|
RepeatedPtrField<DescriptorProto>* messages,
|
||||||
|
const LocationRecorder& parent_location,
|
||||||
|
int location_field_number_for_nested_type,
|
||||||
|
const LocationRecorder& field_location);
|
||||||
|
|
||||||
// Parse an "extensions" declaration.
|
// Parse an "extensions" declaration.
|
||||||
bool ParseExtensions(DescriptorProto* message);
|
bool ParseExtensions(DescriptorProto* message,
|
||||||
|
const LocationRecorder& extensions_location);
|
||||||
|
|
||||||
// Parse an "extend" declaration.
|
// Parse an "extend" declaration. (See also comments for
|
||||||
|
// ParseMessageField().)
|
||||||
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
|
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
|
||||||
RepeatedPtrField<DescriptorProto>* messages);
|
RepeatedPtrField<DescriptorProto>* messages,
|
||||||
|
const LocationRecorder& parent_location,
|
||||||
|
int location_field_number_for_nested_type,
|
||||||
|
const LocationRecorder& extend_location);
|
||||||
|
|
||||||
// Parse a single enum value within an enum block.
|
// Parse a single enum value within an enum block.
|
||||||
bool ParseEnumConstant(EnumValueDescriptorProto* enum_value);
|
bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
|
||||||
|
const LocationRecorder& enum_value_location);
|
||||||
|
|
||||||
// Parse enum constant options, i.e. the list in square brackets at the end
|
// Parse enum constant options, i.e. the list in square brackets at the end
|
||||||
// of the enum constant value definition.
|
// of the enum constant value definition.
|
||||||
bool ParseEnumConstantOptions(EnumValueDescriptorProto* value);
|
bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
|
||||||
|
const LocationRecorder& enum_value_location);
|
||||||
|
|
||||||
// Parse a single method within a service definition.
|
// Parse a single method within a service definition.
|
||||||
bool ParseServiceMethod(MethodDescriptorProto* method);
|
bool ParseServiceMethod(MethodDescriptorProto* method,
|
||||||
|
const LocationRecorder& method_location);
|
||||||
|
|
||||||
|
|
||||||
|
// Parse options of a single method or stream.
|
||||||
|
bool ParseOptions(const LocationRecorder& parent_location,
|
||||||
|
const int optionsFieldNumber,
|
||||||
|
Message* mutable_options);
|
||||||
|
|
||||||
// Parse "required", "optional", or "repeated" and fill in "label"
|
// Parse "required", "optional", or "repeated" and fill in "label"
|
||||||
// with the value.
|
// with the value.
|
||||||
@ -269,39 +376,71 @@ class LIBPROTOBUF_EXPORT Parser {
|
|||||||
|
|
||||||
// Parses field options, i.e. the stuff in square brackets at the end
|
// Parses field options, i.e. the stuff in square brackets at the end
|
||||||
// of a field definition. Also parses default value.
|
// of a field definition. Also parses default value.
|
||||||
bool ParseFieldOptions(FieldDescriptorProto* field);
|
bool ParseFieldOptions(FieldDescriptorProto* field,
|
||||||
|
const LocationRecorder& field_location);
|
||||||
|
|
||||||
// Parse the "default" option. This needs special handling because its
|
// Parse the "default" option. This needs special handling because its
|
||||||
// type is the field's type.
|
// type is the field's type.
|
||||||
bool ParseDefaultAssignment(FieldDescriptorProto* field);
|
bool ParseDefaultAssignment(FieldDescriptorProto* field,
|
||||||
|
const LocationRecorder& field_location);
|
||||||
|
|
||||||
|
enum OptionStyle {
|
||||||
|
OPTION_ASSIGNMENT, // just "name = value"
|
||||||
|
OPTION_STATEMENT // "option name = value;"
|
||||||
|
};
|
||||||
|
|
||||||
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
|
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
|
||||||
// identifies a field of the given Message, and the value of that field
|
// identifies a field of the given Message, and the value of that field
|
||||||
// is set to the parsed value.
|
// is set to the parsed value.
|
||||||
bool ParseOptionAssignment(Message* options);
|
bool ParseOption(Message* options,
|
||||||
|
const LocationRecorder& options_location,
|
||||||
|
OptionStyle style);
|
||||||
|
|
||||||
// Parses a single part of a multipart option name. A multipart name consists
|
// Parses a single part of a multipart option name. A multipart name consists
|
||||||
// of names separated by dots. Each name is either an identifier or a series
|
// of names separated by dots. Each name is either an identifier or a series
|
||||||
// of identifiers separated by dots and enclosed in parentheses. E.g.,
|
// of identifiers separated by dots and enclosed in parentheses. E.g.,
|
||||||
// "foo.(bar.baz).qux".
|
// "foo.(bar.baz).qux".
|
||||||
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option);
|
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
|
||||||
|
const LocationRecorder& part_location);
|
||||||
|
|
||||||
|
// Parses a string surrounded by balanced braces. Strips off the outer
|
||||||
|
// braces and stores the enclosed string in *value.
|
||||||
|
// E.g.,
|
||||||
|
// { foo } *value gets 'foo'
|
||||||
|
// { foo { bar: box } } *value gets 'foo { bar: box }'
|
||||||
|
// {} *value gets ''
|
||||||
|
//
|
||||||
|
// REQUIRES: LookingAt("{")
|
||||||
|
// When finished successfully, we are looking at the first token past
|
||||||
|
// the ending brace.
|
||||||
|
bool ParseUninterpretedBlock(string* value);
|
||||||
|
|
||||||
// =================================================================
|
// =================================================================
|
||||||
|
|
||||||
io::Tokenizer* input_;
|
io::Tokenizer* input_;
|
||||||
io::ErrorCollector* error_collector_;
|
io::ErrorCollector* error_collector_;
|
||||||
SourceLocationTable* source_location_table_;
|
SourceCodeInfo* source_code_info_;
|
||||||
|
SourceLocationTable* source_location_table_; // legacy
|
||||||
bool had_errors_;
|
bool had_errors_;
|
||||||
bool require_syntax_identifier_;
|
bool require_syntax_identifier_;
|
||||||
bool stop_after_syntax_identifier_;
|
bool stop_after_syntax_identifier_;
|
||||||
string syntax_identifier_;
|
string syntax_identifier_;
|
||||||
|
|
||||||
|
// Leading doc comments for the next declaration. These are not complete
|
||||||
|
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
|
||||||
|
string upcoming_doc_comments_;
|
||||||
|
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
|
||||||
};
|
};
|
||||||
|
|
||||||
// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
|
// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
|
||||||
// DescriptorPool when validating descriptors -- to line and column numbers
|
// DescriptorPool when validating descriptors -- to line and column numbers
|
||||||
// within the original source code.
|
// within the original source code.
|
||||||
|
//
|
||||||
|
// This is semi-obsolete: FileDescriptorProto.source_code_info now contains
|
||||||
|
// far more complete information about source locations. However, as of this
|
||||||
|
// writing you still need to use SourceLocationTable when integrating with
|
||||||
|
// DescriptorPool.
|
||||||
class LIBPROTOBUF_EXPORT SourceLocationTable {
|
class LIBPROTOBUF_EXPORT SourceLocationTable {
|
||||||
public:
|
public:
|
||||||
SourceLocationTable();
|
SourceLocationTable();
|
File diff suppressed because it is too large
Load Diff
@ -59,13 +59,15 @@ namespace google {
|
|||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
class GeneratorResponseOutputDirectory : public OutputDirectory {
|
class GeneratorResponseContext : public GeneratorContext {
|
||||||
public:
|
public:
|
||||||
GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
|
GeneratorResponseContext(CodeGeneratorResponse* response,
|
||||||
: response_(response) {}
|
const vector<const FileDescriptor*>& parsed_files)
|
||||||
virtual ~GeneratorResponseOutputDirectory() {}
|
: response_(response),
|
||||||
|
parsed_files_(parsed_files) {}
|
||||||
|
virtual ~GeneratorResponseContext() {}
|
||||||
|
|
||||||
// implements OutputDirectory --------------------------------------
|
// implements GeneratorContext --------------------------------------
|
||||||
|
|
||||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
||||||
CodeGeneratorResponse::File* file = response_->add_file();
|
CodeGeneratorResponse::File* file = response_->add_file();
|
||||||
@ -81,8 +83,13 @@ class GeneratorResponseOutputDirectory : public OutputDirectory {
|
|||||||
return new io::StringOutputStream(file->mutable_content());
|
return new io::StringOutputStream(file->mutable_content());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListParsedFiles(vector<const FileDescriptor*>* output) {
|
||||||
|
*output = parsed_files_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CodeGeneratorResponse* response_;
|
CodeGeneratorResponse* response_;
|
||||||
|
const vector<const FileDescriptor*>& parsed_files_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
|
int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
|
||||||
@ -112,22 +119,26 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGeneratorResponse response;
|
vector<const FileDescriptor*> parsed_files;
|
||||||
GeneratorResponseOutputDirectory output_directory(&response);
|
|
||||||
|
|
||||||
for (int i = 0; i < request.file_to_generate_size(); i++) {
|
for (int i = 0; i < request.file_to_generate_size(); i++) {
|
||||||
const FileDescriptor* file =
|
parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
|
||||||
pool.FindFileByName(request.file_to_generate(i));
|
if (parsed_files.back() == NULL) {
|
||||||
if (file == NULL) {
|
|
||||||
cerr << argv[0] << ": protoc asked plugin to generate a file but "
|
cerr << argv[0] << ": protoc asked plugin to generate a file but "
|
||||||
"did not provide a descriptor for the file: "
|
"did not provide a descriptor for the file: "
|
||||||
<< request.file_to_generate(i) << endl;
|
<< request.file_to_generate(i) << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeGeneratorResponse response;
|
||||||
|
GeneratorResponseContext context(&response, parsed_files);
|
||||||
|
|
||||||
|
for (int i = 0; i < parsed_files.size(); i++) {
|
||||||
|
const FileDescriptor* file = parsed_files[i];
|
||||||
|
|
||||||
string error;
|
string error;
|
||||||
bool succeeded = generator->Generate(
|
bool succeeded = generator->Generate(
|
||||||
file, request.parameter(), &output_directory, &error);
|
file, request.parameter(), &context, &error);
|
||||||
|
|
||||||
if (!succeeded && error.empty()) {
|
if (!succeeded && error.empty()) {
|
||||||
error = "Code generator returned false but provided no error "
|
error = "Code generator returned false but provided no error "
|
@ -56,7 +56,6 @@
|
|||||||
#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
|
#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
|
||||||
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
namespace compiler {
|
namespace compiler {
|
@ -1,11 +1,17 @@
|
|||||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
// source: google/protobuf/compiler/plugin.proto
|
||||||
|
|
||||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||||
#include "google/protobuf/compiler/plugin.pb.h"
|
#include "google/protobuf/compiler/plugin.pb.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/stubs/once.h>
|
#include <google/protobuf/stubs/once.h>
|
||||||
#include <google/protobuf/io/coded_stream.h>
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
#include <google/protobuf/wire_format_lite_inl.h>
|
#include <google/protobuf/wire_format_lite_inl.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/generated_message_reflection.h>
|
||||||
#include <google/protobuf/reflection_ops.h>
|
#include <google/protobuf/reflection_ops.h>
|
||||||
#include <google/protobuf/wire_format.h>
|
#include <google/protobuf/wire_format.h>
|
||||||
// @@protoc_insertion_point(includes)
|
// @@protoc_insertion_point(includes)
|
||||||
@ -133,7 +139,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
|
|||||||
"atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
|
"atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
|
||||||
"\01324.google.protobuf.compiler.CodeGenerat"
|
"\01324.google.protobuf.compiler.CodeGenerat"
|
||||||
"orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
|
"orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
|
||||||
"\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t", 399);
|
"\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
|
||||||
|
",\n\034com.google.protobuf.compilerB\014PluginP"
|
||||||
|
"rotos", 445);
|
||||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||||
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
|
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
|
||||||
CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
|
CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
|
||||||
@ -152,10 +160,8 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto
|
|||||||
}
|
}
|
||||||
} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
|
} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
|
||||||
|
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
const ::std::string CodeGeneratorRequest::_default_parameter_;
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
|
const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
|
||||||
const int CodeGeneratorRequest::kParameterFieldNumber;
|
const int CodeGeneratorRequest::kParameterFieldNumber;
|
||||||
@ -178,7 +184,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
|
|||||||
|
|
||||||
void CodeGeneratorRequest::SharedCtor() {
|
void CodeGeneratorRequest::SharedCtor() {
|
||||||
_cached_size_ = 0;
|
_cached_size_ = 0;
|
||||||
parameter_ = const_cast< ::std::string*>(&_default_parameter_);
|
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +193,7 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeGeneratorRequest::SharedDtor() {
|
void CodeGeneratorRequest::SharedDtor() {
|
||||||
if (parameter_ != &_default_parameter_) {
|
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
delete parameter_;
|
delete parameter_;
|
||||||
}
|
}
|
||||||
if (this != default_instance_) {
|
if (this != default_instance_) {
|
||||||
@ -205,7 +211,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
|
const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
|
||||||
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
|
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
return *default_instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
|
CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
|
||||||
@ -216,8 +223,8 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const {
|
|||||||
|
|
||||||
void CodeGeneratorRequest::Clear() {
|
void CodeGeneratorRequest::Clear() {
|
||||||
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
||||||
if (_has_bit(1)) {
|
if (has_parameter()) {
|
||||||
if (parameter_ != &_default_parameter_) {
|
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_->clear();
|
parameter_->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +249,8 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
|
|||||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||||
input, this->add_file_to_generate()));
|
input, this->add_file_to_generate()));
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->file_to_generate(0).data(), this->file_to_generate(0).length(),
|
this->file_to_generate(this->file_to_generate_size() - 1).data(),
|
||||||
|
this->file_to_generate(this->file_to_generate_size() - 1).length(),
|
||||||
::google::protobuf::internal::WireFormat::PARSE);
|
::google::protobuf::internal::WireFormat::PARSE);
|
||||||
} else {
|
} else {
|
||||||
goto handle_uninterpreted;
|
goto handle_uninterpreted;
|
||||||
@ -251,7 +259,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectTag(18)) goto parse_parameter;
|
if (input->ExpectTag(18)) goto parse_parameter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
case 2: {
|
case 2: {
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -268,7 +276,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectTag(122)) goto parse_proto_file;
|
if (input->ExpectTag(122)) goto parse_proto_file;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
case 15: {
|
case 15: {
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -283,7 +291,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectAtEnd()) return true;
|
if (input->ExpectAtEnd()) return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
handle_uninterpreted:
|
handle_uninterpreted:
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -310,22 +318,22 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
1, this->file_to_generate(i), output);
|
1, this->file_to_generate(i), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
if (_has_bit(1)) {
|
if (has_parameter()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->parameter().data(), this->parameter().length(),
|
this->parameter().data(), this->parameter().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
2, this->parameter(), output);
|
2, this->parameter(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
for (int i = 0; i < this->proto_file_size(); i++) {
|
for (int i = 0; i < this->proto_file_size(); i++) {
|
||||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||||
15, this->proto_file(i), output);
|
15, this->proto_file(i), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||||
unknown_fields(), output);
|
unknown_fields(), output);
|
||||||
@ -342,9 +350,9 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
|||||||
target = ::google::protobuf::internal::WireFormatLite::
|
target = ::google::protobuf::internal::WireFormatLite::
|
||||||
WriteStringToArray(1, this->file_to_generate(i), target);
|
WriteStringToArray(1, this->file_to_generate(i), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
if (_has_bit(1)) {
|
if (has_parameter()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->parameter().data(), this->parameter().length(),
|
this->parameter().data(), this->parameter().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
@ -352,14 +360,14 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||||
2, this->parameter(), target);
|
2, this->parameter(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
for (int i = 0; i < this->proto_file_size(); i++) {
|
for (int i = 0; i < this->proto_file_size(); i++) {
|
||||||
target = ::google::protobuf::internal::WireFormatLite::
|
target = ::google::protobuf::internal::WireFormatLite::
|
||||||
WriteMessageNoVirtualToArray(
|
WriteMessageNoVirtualToArray(
|
||||||
15, this->proto_file(i), target);
|
15, this->proto_file(i), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||||
unknown_fields(), target);
|
unknown_fields(), target);
|
||||||
@ -369,7 +377,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
|||||||
|
|
||||||
int CodeGeneratorRequest::ByteSize() const {
|
int CodeGeneratorRequest::ByteSize() const {
|
||||||
int total_size = 0;
|
int total_size = 0;
|
||||||
|
|
||||||
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
if (has_parameter()) {
|
if (has_parameter()) {
|
||||||
@ -377,7 +385,7 @@ int CodeGeneratorRequest::ByteSize() const {
|
|||||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->parameter());
|
this->parameter());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// repeated string file_to_generate = 1;
|
// repeated string file_to_generate = 1;
|
||||||
total_size += 1 * this->file_to_generate_size();
|
total_size += 1 * this->file_to_generate_size();
|
||||||
@ -385,7 +393,7 @@ int CodeGeneratorRequest::ByteSize() const {
|
|||||||
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
|
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->file_to_generate(i));
|
this->file_to_generate(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
total_size += 1 * this->proto_file_size();
|
total_size += 1 * this->proto_file_size();
|
||||||
for (int i = 0; i < this->proto_file_size(); i++) {
|
for (int i = 0; i < this->proto_file_size(); i++) {
|
||||||
@ -393,7 +401,7 @@ int CodeGeneratorRequest::ByteSize() const {
|
|||||||
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
||||||
this->proto_file(i));
|
this->proto_file(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
total_size +=
|
total_size +=
|
||||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||||
@ -422,7 +430,7 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
|
|||||||
file_to_generate_.MergeFrom(from.file_to_generate_);
|
file_to_generate_.MergeFrom(from.file_to_generate_);
|
||||||
proto_file_.MergeFrom(from.proto_file_);
|
proto_file_.MergeFrom(from.proto_file_);
|
||||||
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
||||||
if (from._has_bit(1)) {
|
if (from.has_parameter()) {
|
||||||
set_parameter(from.parameter());
|
set_parameter(from.parameter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,7 +450,7 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGeneratorRequest::IsInitialized() const {
|
bool CodeGeneratorRequest::IsInitialized() const {
|
||||||
|
|
||||||
for (int i = 0; i < proto_file_size(); i++) {
|
for (int i = 0; i < proto_file_size(); i++) {
|
||||||
if (!this->proto_file(i).IsInitialized()) return false;
|
if (!this->proto_file(i).IsInitialized()) return false;
|
||||||
}
|
}
|
||||||
@ -471,9 +479,6 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
|
|||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
const ::std::string CodeGeneratorResponse_File::_default_name_;
|
|
||||||
const ::std::string CodeGeneratorResponse_File::_default_insertion_point_;
|
|
||||||
const ::std::string CodeGeneratorResponse_File::_default_content_;
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
const int CodeGeneratorResponse_File::kNameFieldNumber;
|
const int CodeGeneratorResponse_File::kNameFieldNumber;
|
||||||
const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
|
const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
|
||||||
@ -496,9 +501,9 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon
|
|||||||
|
|
||||||
void CodeGeneratorResponse_File::SharedCtor() {
|
void CodeGeneratorResponse_File::SharedCtor() {
|
||||||
_cached_size_ = 0;
|
_cached_size_ = 0;
|
||||||
name_ = const_cast< ::std::string*>(&_default_name_);
|
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_);
|
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
content_ = const_cast< ::std::string*>(&_default_content_);
|
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,13 +512,13 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeGeneratorResponse_File::SharedDtor() {
|
void CodeGeneratorResponse_File::SharedDtor() {
|
||||||
if (name_ != &_default_name_) {
|
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
delete name_;
|
delete name_;
|
||||||
}
|
}
|
||||||
if (insertion_point_ != &_default_insertion_point_) {
|
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
delete insertion_point_;
|
delete insertion_point_;
|
||||||
}
|
}
|
||||||
if (content_ != &_default_content_) {
|
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
delete content_;
|
delete content_;
|
||||||
}
|
}
|
||||||
if (this != default_instance_) {
|
if (this != default_instance_) {
|
||||||
@ -531,7 +536,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
|
const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
|
||||||
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
|
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
return *default_instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
|
CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
|
||||||
@ -542,18 +548,18 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
|
|||||||
|
|
||||||
void CodeGeneratorResponse_File::Clear() {
|
void CodeGeneratorResponse_File::Clear() {
|
||||||
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
if (_has_bit(0)) {
|
if (has_name()) {
|
||||||
if (name_ != &_default_name_) {
|
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
name_->clear();
|
name_->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_has_bit(1)) {
|
if (has_insertion_point()) {
|
||||||
if (insertion_point_ != &_default_insertion_point_) {
|
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_->clear();
|
insertion_point_->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_has_bit(2)) {
|
if (has_content()) {
|
||||||
if (content_ != &_default_content_) {
|
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
content_->clear();
|
content_->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -583,7 +589,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectTag(18)) goto parse_insertion_point;
|
if (input->ExpectTag(18)) goto parse_insertion_point;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
case 2: {
|
case 2: {
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -600,7 +606,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectTag(122)) goto parse_content;
|
if (input->ExpectTag(122)) goto parse_content;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
case 15: {
|
case 15: {
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -617,7 +623,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectAtEnd()) return true;
|
if (input->ExpectAtEnd()) return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
handle_uninterpreted:
|
handle_uninterpreted:
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -637,32 +643,32 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
|
|||||||
void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
||||||
::google::protobuf::io::CodedOutputStream* output) const {
|
::google::protobuf::io::CodedOutputStream* output) const {
|
||||||
// optional string name = 1;
|
// optional string name = 1;
|
||||||
if (_has_bit(0)) {
|
if (has_name()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->name().data(), this->name().length(),
|
this->name().data(), this->name().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
1, this->name(), output);
|
1, this->name(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
if (_has_bit(1)) {
|
if (has_insertion_point()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->insertion_point().data(), this->insertion_point().length(),
|
this->insertion_point().data(), this->insertion_point().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
2, this->insertion_point(), output);
|
2, this->insertion_point(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
if (_has_bit(2)) {
|
if (has_content()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->content().data(), this->content().length(),
|
this->content().data(), this->content().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
15, this->content(), output);
|
15, this->content(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||||
unknown_fields(), output);
|
unknown_fields(), output);
|
||||||
@ -672,7 +678,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
|
::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
|
||||||
::google::protobuf::uint8* target) const {
|
::google::protobuf::uint8* target) const {
|
||||||
// optional string name = 1;
|
// optional string name = 1;
|
||||||
if (_has_bit(0)) {
|
if (has_name()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->name().data(), this->name().length(),
|
this->name().data(), this->name().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
@ -680,9 +686,9 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||||
1, this->name(), target);
|
1, this->name(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
if (_has_bit(1)) {
|
if (has_insertion_point()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->insertion_point().data(), this->insertion_point().length(),
|
this->insertion_point().data(), this->insertion_point().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
@ -690,9 +696,9 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||||
2, this->insertion_point(), target);
|
2, this->insertion_point(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
if (_has_bit(2)) {
|
if (has_content()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->content().data(), this->content().length(),
|
this->content().data(), this->content().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
@ -700,7 +706,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||||
15, this->content(), target);
|
15, this->content(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||||
unknown_fields(), target);
|
unknown_fields(), target);
|
||||||
@ -710,7 +716,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
|
|||||||
|
|
||||||
int CodeGeneratorResponse_File::ByteSize() const {
|
int CodeGeneratorResponse_File::ByteSize() const {
|
||||||
int total_size = 0;
|
int total_size = 0;
|
||||||
|
|
||||||
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
// optional string name = 1;
|
// optional string name = 1;
|
||||||
if (has_name()) {
|
if (has_name()) {
|
||||||
@ -718,21 +724,21 @@ int CodeGeneratorResponse_File::ByteSize() const {
|
|||||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->name());
|
this->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
if (has_insertion_point()) {
|
if (has_insertion_point()) {
|
||||||
total_size += 1 +
|
total_size += 1 +
|
||||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->insertion_point());
|
this->insertion_point());
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
if (has_content()) {
|
if (has_content()) {
|
||||||
total_size += 1 +
|
total_size += 1 +
|
||||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->content());
|
this->content());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
total_size +=
|
total_size +=
|
||||||
@ -760,13 +766,13 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr
|
|||||||
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
|
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
|
||||||
GOOGLE_CHECK_NE(&from, this);
|
GOOGLE_CHECK_NE(&from, this);
|
||||||
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
if (from._has_bit(0)) {
|
if (from.has_name()) {
|
||||||
set_name(from.name());
|
set_name(from.name());
|
||||||
}
|
}
|
||||||
if (from._has_bit(1)) {
|
if (from.has_insertion_point()) {
|
||||||
set_insertion_point(from.insertion_point());
|
set_insertion_point(from.insertion_point());
|
||||||
}
|
}
|
||||||
if (from._has_bit(2)) {
|
if (from.has_content()) {
|
||||||
set_content(from.content());
|
set_content(from.content());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -786,7 +792,7 @@ void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGeneratorResponse_File::IsInitialized() const {
|
bool CodeGeneratorResponse_File::IsInitialized() const {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,7 +818,6 @@ void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
|
|||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
const ::std::string CodeGeneratorResponse::_default_error_;
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
const int CodeGeneratorResponse::kErrorFieldNumber;
|
const int CodeGeneratorResponse::kErrorFieldNumber;
|
||||||
const int CodeGeneratorResponse::kFileFieldNumber;
|
const int CodeGeneratorResponse::kFileFieldNumber;
|
||||||
@ -834,7 +839,7 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
|
|||||||
|
|
||||||
void CodeGeneratorResponse::SharedCtor() {
|
void CodeGeneratorResponse::SharedCtor() {
|
||||||
_cached_size_ = 0;
|
_cached_size_ = 0;
|
||||||
error_ = const_cast< ::std::string*>(&_default_error_);
|
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,7 +848,7 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeGeneratorResponse::SharedDtor() {
|
void CodeGeneratorResponse::SharedDtor() {
|
||||||
if (error_ != &_default_error_) {
|
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
delete error_;
|
delete error_;
|
||||||
}
|
}
|
||||||
if (this != default_instance_) {
|
if (this != default_instance_) {
|
||||||
@ -861,7 +866,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
|
const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
|
||||||
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
|
if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
return *default_instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
|
CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
|
||||||
@ -872,8 +878,8 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const {
|
|||||||
|
|
||||||
void CodeGeneratorResponse::Clear() {
|
void CodeGeneratorResponse::Clear() {
|
||||||
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
if (_has_bit(0)) {
|
if (has_error()) {
|
||||||
if (error_ != &_default_error_) {
|
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
error_->clear();
|
error_->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -904,7 +910,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectTag(122)) goto parse_file;
|
if (input->ExpectTag(122)) goto parse_file;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
case 15: {
|
case 15: {
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -919,7 +925,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
|
|||||||
if (input->ExpectAtEnd()) return true;
|
if (input->ExpectAtEnd()) return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
handle_uninterpreted:
|
handle_uninterpreted:
|
||||||
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||||
@ -939,20 +945,20 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
|
|||||||
void CodeGeneratorResponse::SerializeWithCachedSizes(
|
void CodeGeneratorResponse::SerializeWithCachedSizes(
|
||||||
::google::protobuf::io::CodedOutputStream* output) const {
|
::google::protobuf::io::CodedOutputStream* output) const {
|
||||||
// optional string error = 1;
|
// optional string error = 1;
|
||||||
if (_has_bit(0)) {
|
if (has_error()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->error().data(), this->error().length(),
|
this->error().data(), this->error().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||||
1, this->error(), output);
|
1, this->error(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
for (int i = 0; i < this->file_size(); i++) {
|
for (int i = 0; i < this->file_size(); i++) {
|
||||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||||
15, this->file(i), output);
|
15, this->file(i), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
|
||||||
unknown_fields(), output);
|
unknown_fields(), output);
|
||||||
@ -962,7 +968,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
|
::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
|
||||||
::google::protobuf::uint8* target) const {
|
::google::protobuf::uint8* target) const {
|
||||||
// optional string error = 1;
|
// optional string error = 1;
|
||||||
if (_has_bit(0)) {
|
if (has_error()) {
|
||||||
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
::google::protobuf::internal::WireFormat::VerifyUTF8String(
|
||||||
this->error().data(), this->error().length(),
|
this->error().data(), this->error().length(),
|
||||||
::google::protobuf::internal::WireFormat::SERIALIZE);
|
::google::protobuf::internal::WireFormat::SERIALIZE);
|
||||||
@ -970,14 +976,14 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
|||||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||||
1, this->error(), target);
|
1, this->error(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
for (int i = 0; i < this->file_size(); i++) {
|
for (int i = 0; i < this->file_size(); i++) {
|
||||||
target = ::google::protobuf::internal::WireFormatLite::
|
target = ::google::protobuf::internal::WireFormatLite::
|
||||||
WriteMessageNoVirtualToArray(
|
WriteMessageNoVirtualToArray(
|
||||||
15, this->file(i), target);
|
15, this->file(i), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
|
||||||
unknown_fields(), target);
|
unknown_fields(), target);
|
||||||
@ -987,7 +993,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
|||||||
|
|
||||||
int CodeGeneratorResponse::ByteSize() const {
|
int CodeGeneratorResponse::ByteSize() const {
|
||||||
int total_size = 0;
|
int total_size = 0;
|
||||||
|
|
||||||
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
// optional string error = 1;
|
// optional string error = 1;
|
||||||
if (has_error()) {
|
if (has_error()) {
|
||||||
@ -995,7 +1001,7 @@ int CodeGeneratorResponse::ByteSize() const {
|
|||||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||||
this->error());
|
this->error());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
total_size += 1 * this->file_size();
|
total_size += 1 * this->file_size();
|
||||||
@ -1004,7 +1010,7 @@ int CodeGeneratorResponse::ByteSize() const {
|
|||||||
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
||||||
this->file(i));
|
this->file(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unknown_fields().empty()) {
|
if (!unknown_fields().empty()) {
|
||||||
total_size +=
|
total_size +=
|
||||||
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
|
||||||
@ -1032,7 +1038,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
|
|||||||
GOOGLE_CHECK_NE(&from, this);
|
GOOGLE_CHECK_NE(&from, this);
|
||||||
file_.MergeFrom(from.file_);
|
file_.MergeFrom(from.file_);
|
||||||
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||||
if (from._has_bit(0)) {
|
if (from.has_error()) {
|
||||||
set_error(from.error());
|
set_error(from.error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1052,7 +1058,7 @@ void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGeneratorResponse::IsInitialized() const {
|
bool CodeGeneratorResponse::IsInitialized() const {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -8,21 +8,22 @@
|
|||||||
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
#if GOOGLE_PROTOBUF_VERSION < 2003000
|
#if GOOGLE_PROTOBUF_VERSION < 2005000
|
||||||
#error This file was generated by a newer version of protoc which is
|
#error This file was generated by a newer version of protoc which is
|
||||||
#error incompatible with your Protocol Buffer headers. Please update
|
#error incompatible with your Protocol Buffer headers. Please update
|
||||||
#error your headers.
|
#error your headers.
|
||||||
#endif
|
#endif
|
||||||
#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
#if 2005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||||
#error This file was generated by an older version of protoc which is
|
#error This file was generated by an older version of protoc which is
|
||||||
#error incompatible with your Protocol Buffer headers. Please
|
#error incompatible with your Protocol Buffer headers. Please
|
||||||
#error regenerate this file with a newer version of protoc.
|
#error regenerate this file with a newer version of protoc.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <google/protobuf/generated_message_util.h>
|
#include <google/protobuf/generated_message_util.h>
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
#include <google/protobuf/repeated_field.h>
|
#include <google/protobuf/repeated_field.h>
|
||||||
#include <google/protobuf/extension_set.h>
|
#include <google/protobuf/extension_set.h>
|
||||||
#include <google/protobuf/generated_message_reflection.h>
|
#include <google/protobuf/unknown_field_set.h>
|
||||||
#include "google/protobuf/descriptor.pb.h"
|
#include "google/protobuf/descriptor.pb.h"
|
||||||
// @@protoc_insertion_point(includes)
|
// @@protoc_insertion_point(includes)
|
||||||
|
|
||||||
@ -45,29 +46,29 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
public:
|
public:
|
||||||
CodeGeneratorRequest();
|
CodeGeneratorRequest();
|
||||||
virtual ~CodeGeneratorRequest();
|
virtual ~CodeGeneratorRequest();
|
||||||
|
|
||||||
CodeGeneratorRequest(const CodeGeneratorRequest& from);
|
CodeGeneratorRequest(const CodeGeneratorRequest& from);
|
||||||
|
|
||||||
inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
|
inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
|
||||||
CopyFrom(from);
|
CopyFrom(from);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
return _unknown_fields_;
|
return _unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
return &_unknown_fields_;
|
return &_unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ::google::protobuf::Descriptor* descriptor();
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
static const CodeGeneratorRequest& default_instance();
|
static const CodeGeneratorRequest& default_instance();
|
||||||
|
|
||||||
void Swap(CodeGeneratorRequest* other);
|
void Swap(CodeGeneratorRequest* other);
|
||||||
|
|
||||||
// implements Message ----------------------------------------------
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
CodeGeneratorRequest* New() const;
|
CodeGeneratorRequest* New() const;
|
||||||
void CopyFrom(const ::google::protobuf::Message& from);
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
void MergeFrom(const ::google::protobuf::Message& from);
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
@ -75,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
void MergeFrom(const CodeGeneratorRequest& from);
|
void MergeFrom(const CodeGeneratorRequest& from);
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsInitialized() const;
|
bool IsInitialized() const;
|
||||||
|
|
||||||
int ByteSize() const;
|
int ByteSize() const;
|
||||||
bool MergePartialFromCodedStream(
|
bool MergePartialFromCodedStream(
|
||||||
::google::protobuf::io::CodedInputStream* input);
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
@ -88,13 +89,13 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
void SharedDtor();
|
void SharedDtor();
|
||||||
void SetCachedSize(int size) const;
|
void SetCachedSize(int size) const;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
::google::protobuf::Metadata GetMetadata() const;
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
// nested types ----------------------------------------------------
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
// accessors -------------------------------------------------------
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
// repeated string file_to_generate = 1;
|
// repeated string file_to_generate = 1;
|
||||||
inline int file_to_generate_size() const;
|
inline int file_to_generate_size() const;
|
||||||
inline void clear_file_to_generate();
|
inline void clear_file_to_generate();
|
||||||
@ -110,7 +111,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
inline void add_file_to_generate(const char* value, size_t size);
|
inline void add_file_to_generate(const char* value, size_t size);
|
||||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
|
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
|
||||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
|
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
|
||||||
|
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
inline bool has_parameter() const;
|
inline bool has_parameter() const;
|
||||||
inline void clear_parameter();
|
inline void clear_parameter();
|
||||||
@ -120,7 +121,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
inline void set_parameter(const char* value);
|
inline void set_parameter(const char* value);
|
||||||
inline void set_parameter(const char* value, size_t size);
|
inline void set_parameter(const char* value, size_t size);
|
||||||
inline ::std::string* mutable_parameter();
|
inline ::std::string* mutable_parameter();
|
||||||
|
inline ::std::string* release_parameter();
|
||||||
|
inline void set_allocated_parameter(::std::string* parameter);
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
inline int proto_file_size() const;
|
inline int proto_file_size() const;
|
||||||
inline void clear_proto_file();
|
inline void clear_proto_file();
|
||||||
@ -132,33 +135,25 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
|||||||
proto_file() const;
|
proto_file() const;
|
||||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||||
mutable_proto_file();
|
mutable_proto_file();
|
||||||
|
|
||||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
|
||||||
private:
|
private:
|
||||||
|
inline void set_has_parameter();
|
||||||
|
inline void clear_has_parameter();
|
||||||
|
|
||||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
mutable int _cached_size_;
|
|
||||||
|
|
||||||
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
|
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
|
||||||
::std::string* parameter_;
|
::std::string* parameter_;
|
||||||
static const ::std::string _default_parameter_;
|
|
||||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
|
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
|
||||||
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||||
|
|
||||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
|
||||||
|
|
||||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
|
||||||
inline bool _has_bit(int index) const {
|
|
||||||
return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
|
|
||||||
}
|
|
||||||
inline void _set_bit(int index) {
|
|
||||||
_has_bits_[index / 32] |= (1u << (index % 32));
|
|
||||||
}
|
|
||||||
inline void _clear_bit(int index) {
|
|
||||||
_has_bits_[index / 32] &= ~(1u << (index % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitAsDefaultInstance();
|
void InitAsDefaultInstance();
|
||||||
static CodeGeneratorRequest* default_instance_;
|
static CodeGeneratorRequest* default_instance_;
|
||||||
};
|
};
|
||||||
@ -168,29 +163,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
public:
|
public:
|
||||||
CodeGeneratorResponse_File();
|
CodeGeneratorResponse_File();
|
||||||
virtual ~CodeGeneratorResponse_File();
|
virtual ~CodeGeneratorResponse_File();
|
||||||
|
|
||||||
CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
|
CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
|
||||||
|
|
||||||
inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
|
inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
|
||||||
CopyFrom(from);
|
CopyFrom(from);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
return _unknown_fields_;
|
return _unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
return &_unknown_fields_;
|
return &_unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ::google::protobuf::Descriptor* descriptor();
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
static const CodeGeneratorResponse_File& default_instance();
|
static const CodeGeneratorResponse_File& default_instance();
|
||||||
|
|
||||||
void Swap(CodeGeneratorResponse_File* other);
|
void Swap(CodeGeneratorResponse_File* other);
|
||||||
|
|
||||||
// implements Message ----------------------------------------------
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
CodeGeneratorResponse_File* New() const;
|
CodeGeneratorResponse_File* New() const;
|
||||||
void CopyFrom(const ::google::protobuf::Message& from);
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
void MergeFrom(const ::google::protobuf::Message& from);
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
@ -198,7 +193,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
void MergeFrom(const CodeGeneratorResponse_File& from);
|
void MergeFrom(const CodeGeneratorResponse_File& from);
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsInitialized() const;
|
bool IsInitialized() const;
|
||||||
|
|
||||||
int ByteSize() const;
|
int ByteSize() const;
|
||||||
bool MergePartialFromCodedStream(
|
bool MergePartialFromCodedStream(
|
||||||
::google::protobuf::io::CodedInputStream* input);
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
@ -211,13 +206,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
void SharedDtor();
|
void SharedDtor();
|
||||||
void SetCachedSize(int size) const;
|
void SetCachedSize(int size) const;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
::google::protobuf::Metadata GetMetadata() const;
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
// nested types ----------------------------------------------------
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
// accessors -------------------------------------------------------
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
// optional string name = 1;
|
// optional string name = 1;
|
||||||
inline bool has_name() const;
|
inline bool has_name() const;
|
||||||
inline void clear_name();
|
inline void clear_name();
|
||||||
@ -227,7 +222,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
inline void set_name(const char* value);
|
inline void set_name(const char* value);
|
||||||
inline void set_name(const char* value, size_t size);
|
inline void set_name(const char* value, size_t size);
|
||||||
inline ::std::string* mutable_name();
|
inline ::std::string* mutable_name();
|
||||||
|
inline ::std::string* release_name();
|
||||||
|
inline void set_allocated_name(::std::string* name);
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
inline bool has_insertion_point() const;
|
inline bool has_insertion_point() const;
|
||||||
inline void clear_insertion_point();
|
inline void clear_insertion_point();
|
||||||
@ -237,7 +234,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
inline void set_insertion_point(const char* value);
|
inline void set_insertion_point(const char* value);
|
||||||
inline void set_insertion_point(const char* value, size_t size);
|
inline void set_insertion_point(const char* value, size_t size);
|
||||||
inline ::std::string* mutable_insertion_point();
|
inline ::std::string* mutable_insertion_point();
|
||||||
|
inline ::std::string* release_insertion_point();
|
||||||
|
inline void set_allocated_insertion_point(::std::string* insertion_point);
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
inline bool has_content() const;
|
inline bool has_content() const;
|
||||||
inline void clear_content();
|
inline void clear_content();
|
||||||
@ -247,35 +246,31 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
|||||||
inline void set_content(const char* value);
|
inline void set_content(const char* value);
|
||||||
inline void set_content(const char* value, size_t size);
|
inline void set_content(const char* value, size_t size);
|
||||||
inline ::std::string* mutable_content();
|
inline ::std::string* mutable_content();
|
||||||
|
inline ::std::string* release_content();
|
||||||
|
inline void set_allocated_content(::std::string* content);
|
||||||
|
|
||||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||||
private:
|
private:
|
||||||
|
inline void set_has_name();
|
||||||
|
inline void clear_has_name();
|
||||||
|
inline void set_has_insertion_point();
|
||||||
|
inline void clear_has_insertion_point();
|
||||||
|
inline void set_has_content();
|
||||||
|
inline void clear_has_content();
|
||||||
|
|
||||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
mutable int _cached_size_;
|
|
||||||
|
|
||||||
::std::string* name_;
|
::std::string* name_;
|
||||||
static const ::std::string _default_name_;
|
|
||||||
::std::string* insertion_point_;
|
::std::string* insertion_point_;
|
||||||
static const ::std::string _default_insertion_point_;
|
|
||||||
::std::string* content_;
|
::std::string* content_;
|
||||||
static const ::std::string _default_content_;
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||||
|
|
||||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
|
||||||
|
|
||||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
|
||||||
inline bool _has_bit(int index) const {
|
|
||||||
return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
|
|
||||||
}
|
|
||||||
inline void _set_bit(int index) {
|
|
||||||
_has_bits_[index / 32] |= (1u << (index % 32));
|
|
||||||
}
|
|
||||||
inline void _clear_bit(int index) {
|
|
||||||
_has_bits_[index / 32] &= ~(1u << (index % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitAsDefaultInstance();
|
void InitAsDefaultInstance();
|
||||||
static CodeGeneratorResponse_File* default_instance_;
|
static CodeGeneratorResponse_File* default_instance_;
|
||||||
};
|
};
|
||||||
@ -285,29 +280,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
|||||||
public:
|
public:
|
||||||
CodeGeneratorResponse();
|
CodeGeneratorResponse();
|
||||||
virtual ~CodeGeneratorResponse();
|
virtual ~CodeGeneratorResponse();
|
||||||
|
|
||||||
CodeGeneratorResponse(const CodeGeneratorResponse& from);
|
CodeGeneratorResponse(const CodeGeneratorResponse& from);
|
||||||
|
|
||||||
inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
|
inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
|
||||||
CopyFrom(from);
|
CopyFrom(from);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
return _unknown_fields_;
|
return _unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
return &_unknown_fields_;
|
return &_unknown_fields_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ::google::protobuf::Descriptor* descriptor();
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
static const CodeGeneratorResponse& default_instance();
|
static const CodeGeneratorResponse& default_instance();
|
||||||
|
|
||||||
void Swap(CodeGeneratorResponse* other);
|
void Swap(CodeGeneratorResponse* other);
|
||||||
|
|
||||||
// implements Message ----------------------------------------------
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
CodeGeneratorResponse* New() const;
|
CodeGeneratorResponse* New() const;
|
||||||
void CopyFrom(const ::google::protobuf::Message& from);
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
void MergeFrom(const ::google::protobuf::Message& from);
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
@ -315,7 +310,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
|||||||
void MergeFrom(const CodeGeneratorResponse& from);
|
void MergeFrom(const CodeGeneratorResponse& from);
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsInitialized() const;
|
bool IsInitialized() const;
|
||||||
|
|
||||||
int ByteSize() const;
|
int ByteSize() const;
|
||||||
bool MergePartialFromCodedStream(
|
bool MergePartialFromCodedStream(
|
||||||
::google::protobuf::io::CodedInputStream* input);
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
@ -328,15 +323,15 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
|||||||
void SharedDtor();
|
void SharedDtor();
|
||||||
void SetCachedSize(int size) const;
|
void SetCachedSize(int size) const;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
::google::protobuf::Metadata GetMetadata() const;
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
// nested types ----------------------------------------------------
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
typedef CodeGeneratorResponse_File File;
|
typedef CodeGeneratorResponse_File File;
|
||||||
|
|
||||||
// accessors -------------------------------------------------------
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
// optional string error = 1;
|
// optional string error = 1;
|
||||||
inline bool has_error() const;
|
inline bool has_error() const;
|
||||||
inline void clear_error();
|
inline void clear_error();
|
||||||
@ -346,7 +341,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
|||||||
inline void set_error(const char* value);
|
inline void set_error(const char* value);
|
||||||
inline void set_error(const char* value, size_t size);
|
inline void set_error(const char* value, size_t size);
|
||||||
inline ::std::string* mutable_error();
|
inline ::std::string* mutable_error();
|
||||||
|
inline ::std::string* release_error();
|
||||||
|
inline void set_allocated_error(::std::string* error);
|
||||||
|
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
inline int file_size() const;
|
inline int file_size() const;
|
||||||
inline void clear_file();
|
inline void clear_file();
|
||||||
@ -358,32 +355,24 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
|||||||
file() const;
|
file() const;
|
||||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||||
mutable_file();
|
mutable_file();
|
||||||
|
|
||||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
|
||||||
private:
|
private:
|
||||||
|
inline void set_has_error();
|
||||||
|
inline void clear_has_error();
|
||||||
|
|
||||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
mutable int _cached_size_;
|
|
||||||
|
|
||||||
::std::string* error_;
|
::std::string* error_;
|
||||||
static const ::std::string _default_error_;
|
|
||||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
|
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
|
||||||
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||||
|
|
||||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
|
||||||
|
|
||||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
|
||||||
inline bool _has_bit(int index) const {
|
|
||||||
return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
|
|
||||||
}
|
|
||||||
inline void _set_bit(int index) {
|
|
||||||
_has_bits_[index / 32] |= (1u << (index % 32));
|
|
||||||
}
|
|
||||||
inline void _clear_bit(int index) {
|
|
||||||
_has_bits_[index / 32] &= ~(1u << (index % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitAsDefaultInstance();
|
void InitAsDefaultInstance();
|
||||||
static CodeGeneratorResponse* default_instance_;
|
static CodeGeneratorResponse* default_instance_;
|
||||||
};
|
};
|
||||||
@ -440,45 +429,73 @@ CodeGeneratorRequest::mutable_file_to_generate() {
|
|||||||
|
|
||||||
// optional string parameter = 2;
|
// optional string parameter = 2;
|
||||||
inline bool CodeGeneratorRequest::has_parameter() const {
|
inline bool CodeGeneratorRequest::has_parameter() const {
|
||||||
return _has_bit(1);
|
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_has_parameter() {
|
||||||
|
_has_bits_[0] |= 0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::clear_has_parameter() {
|
||||||
|
_has_bits_[0] &= ~0x00000002u;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorRequest::clear_parameter() {
|
inline void CodeGeneratorRequest::clear_parameter() {
|
||||||
if (parameter_ != &_default_parameter_) {
|
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_->clear();
|
parameter_->clear();
|
||||||
}
|
}
|
||||||
_clear_bit(1);
|
clear_has_parameter();
|
||||||
}
|
}
|
||||||
inline const ::std::string& CodeGeneratorRequest::parameter() const {
|
inline const ::std::string& CodeGeneratorRequest::parameter() const {
|
||||||
return *parameter_;
|
return *parameter_;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
|
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
|
||||||
_set_bit(1);
|
set_has_parameter();
|
||||||
if (parameter_ == &_default_parameter_) {
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_ = new ::std::string;
|
parameter_ = new ::std::string;
|
||||||
}
|
}
|
||||||
parameter_->assign(value);
|
parameter_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorRequest::set_parameter(const char* value) {
|
inline void CodeGeneratorRequest::set_parameter(const char* value) {
|
||||||
_set_bit(1);
|
set_has_parameter();
|
||||||
if (parameter_ == &_default_parameter_) {
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_ = new ::std::string;
|
parameter_ = new ::std::string;
|
||||||
}
|
}
|
||||||
parameter_->assign(value);
|
parameter_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
|
inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
|
||||||
_set_bit(1);
|
set_has_parameter();
|
||||||
if (parameter_ == &_default_parameter_) {
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_ = new ::std::string;
|
parameter_ = new ::std::string;
|
||||||
}
|
}
|
||||||
parameter_->assign(reinterpret_cast<const char*>(value), size);
|
parameter_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
}
|
}
|
||||||
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
|
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
|
||||||
_set_bit(1);
|
set_has_parameter();
|
||||||
if (parameter_ == &_default_parameter_) {
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
parameter_ = new ::std::string;
|
parameter_ = new ::std::string;
|
||||||
}
|
}
|
||||||
return parameter_;
|
return parameter_;
|
||||||
}
|
}
|
||||||
|
inline ::std::string* CodeGeneratorRequest::release_parameter() {
|
||||||
|
clear_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = parameter_;
|
||||||
|
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
|
||||||
|
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
delete parameter_;
|
||||||
|
}
|
||||||
|
if (parameter) {
|
||||||
|
set_has_parameter();
|
||||||
|
parameter_ = parameter;
|
||||||
|
} else {
|
||||||
|
clear_has_parameter();
|
||||||
|
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
inline int CodeGeneratorRequest::proto_file_size() const {
|
inline int CodeGeneratorRequest::proto_file_size() const {
|
||||||
@ -511,129 +528,213 @@ CodeGeneratorRequest::mutable_proto_file() {
|
|||||||
|
|
||||||
// optional string name = 1;
|
// optional string name = 1;
|
||||||
inline bool CodeGeneratorResponse_File::has_name() const {
|
inline bool CodeGeneratorResponse_File::has_name() const {
|
||||||
return _has_bit(0);
|
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_name() {
|
||||||
|
_has_bits_[0] |= 0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_name() {
|
||||||
|
_has_bits_[0] &= ~0x00000001u;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::clear_name() {
|
inline void CodeGeneratorResponse_File::clear_name() {
|
||||||
if (name_ != &_default_name_) {
|
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
name_->clear();
|
name_->clear();
|
||||||
}
|
}
|
||||||
_clear_bit(0);
|
clear_has_name();
|
||||||
}
|
}
|
||||||
inline const ::std::string& CodeGeneratorResponse_File::name() const {
|
inline const ::std::string& CodeGeneratorResponse_File::name() const {
|
||||||
return *name_;
|
return *name_;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
|
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
|
||||||
_set_bit(0);
|
set_has_name();
|
||||||
if (name_ == &_default_name_) {
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
name_ = new ::std::string;
|
name_ = new ::std::string;
|
||||||
}
|
}
|
||||||
name_->assign(value);
|
name_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_name(const char* value) {
|
inline void CodeGeneratorResponse_File::set_name(const char* value) {
|
||||||
_set_bit(0);
|
set_has_name();
|
||||||
if (name_ == &_default_name_) {
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
name_ = new ::std::string;
|
name_ = new ::std::string;
|
||||||
}
|
}
|
||||||
name_->assign(value);
|
name_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
|
inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
|
||||||
_set_bit(0);
|
set_has_name();
|
||||||
if (name_ == &_default_name_) {
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
name_ = new ::std::string;
|
name_ = new ::std::string;
|
||||||
}
|
}
|
||||||
name_->assign(reinterpret_cast<const char*>(value), size);
|
name_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
}
|
}
|
||||||
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
|
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
|
||||||
_set_bit(0);
|
set_has_name();
|
||||||
if (name_ == &_default_name_) {
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
name_ = new ::std::string;
|
name_ = new ::std::string;
|
||||||
}
|
}
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_name() {
|
||||||
|
clear_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = name_;
|
||||||
|
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
|
||||||
|
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
delete name_;
|
||||||
|
}
|
||||||
|
if (name) {
|
||||||
|
set_has_name();
|
||||||
|
name_ = name;
|
||||||
|
} else {
|
||||||
|
clear_has_name();
|
||||||
|
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// optional string insertion_point = 2;
|
// optional string insertion_point = 2;
|
||||||
inline bool CodeGeneratorResponse_File::has_insertion_point() const {
|
inline bool CodeGeneratorResponse_File::has_insertion_point() const {
|
||||||
return _has_bit(1);
|
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_insertion_point() {
|
||||||
|
_has_bits_[0] |= 0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
|
||||||
|
_has_bits_[0] &= ~0x00000002u;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::clear_insertion_point() {
|
inline void CodeGeneratorResponse_File::clear_insertion_point() {
|
||||||
if (insertion_point_ != &_default_insertion_point_) {
|
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_->clear();
|
insertion_point_->clear();
|
||||||
}
|
}
|
||||||
_clear_bit(1);
|
clear_has_insertion_point();
|
||||||
}
|
}
|
||||||
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
|
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
|
||||||
return *insertion_point_;
|
return *insertion_point_;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
|
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
|
||||||
_set_bit(1);
|
set_has_insertion_point();
|
||||||
if (insertion_point_ == &_default_insertion_point_) {
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_ = new ::std::string;
|
insertion_point_ = new ::std::string;
|
||||||
}
|
}
|
||||||
insertion_point_->assign(value);
|
insertion_point_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
|
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
|
||||||
_set_bit(1);
|
set_has_insertion_point();
|
||||||
if (insertion_point_ == &_default_insertion_point_) {
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_ = new ::std::string;
|
insertion_point_ = new ::std::string;
|
||||||
}
|
}
|
||||||
insertion_point_->assign(value);
|
insertion_point_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
|
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
|
||||||
_set_bit(1);
|
set_has_insertion_point();
|
||||||
if (insertion_point_ == &_default_insertion_point_) {
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_ = new ::std::string;
|
insertion_point_ = new ::std::string;
|
||||||
}
|
}
|
||||||
insertion_point_->assign(reinterpret_cast<const char*>(value), size);
|
insertion_point_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
}
|
}
|
||||||
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
|
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
|
||||||
_set_bit(1);
|
set_has_insertion_point();
|
||||||
if (insertion_point_ == &_default_insertion_point_) {
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
insertion_point_ = new ::std::string;
|
insertion_point_ = new ::std::string;
|
||||||
}
|
}
|
||||||
return insertion_point_;
|
return insertion_point_;
|
||||||
}
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
|
||||||
|
clear_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = insertion_point_;
|
||||||
|
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
|
||||||
|
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
delete insertion_point_;
|
||||||
|
}
|
||||||
|
if (insertion_point) {
|
||||||
|
set_has_insertion_point();
|
||||||
|
insertion_point_ = insertion_point;
|
||||||
|
} else {
|
||||||
|
clear_has_insertion_point();
|
||||||
|
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// optional string content = 15;
|
// optional string content = 15;
|
||||||
inline bool CodeGeneratorResponse_File::has_content() const {
|
inline bool CodeGeneratorResponse_File::has_content() const {
|
||||||
return _has_bit(2);
|
return (_has_bits_[0] & 0x00000004u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_content() {
|
||||||
|
_has_bits_[0] |= 0x00000004u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_content() {
|
||||||
|
_has_bits_[0] &= ~0x00000004u;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::clear_content() {
|
inline void CodeGeneratorResponse_File::clear_content() {
|
||||||
if (content_ != &_default_content_) {
|
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
content_->clear();
|
content_->clear();
|
||||||
}
|
}
|
||||||
_clear_bit(2);
|
clear_has_content();
|
||||||
}
|
}
|
||||||
inline const ::std::string& CodeGeneratorResponse_File::content() const {
|
inline const ::std::string& CodeGeneratorResponse_File::content() const {
|
||||||
return *content_;
|
return *content_;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
|
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
|
||||||
_set_bit(2);
|
set_has_content();
|
||||||
if (content_ == &_default_content_) {
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
content_ = new ::std::string;
|
content_ = new ::std::string;
|
||||||
}
|
}
|
||||||
content_->assign(value);
|
content_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_content(const char* value) {
|
inline void CodeGeneratorResponse_File::set_content(const char* value) {
|
||||||
_set_bit(2);
|
set_has_content();
|
||||||
if (content_ == &_default_content_) {
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
content_ = new ::std::string;
|
content_ = new ::std::string;
|
||||||
}
|
}
|
||||||
content_->assign(value);
|
content_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
|
inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
|
||||||
_set_bit(2);
|
set_has_content();
|
||||||
if (content_ == &_default_content_) {
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
content_ = new ::std::string;
|
content_ = new ::std::string;
|
||||||
}
|
}
|
||||||
content_->assign(reinterpret_cast<const char*>(value), size);
|
content_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
}
|
}
|
||||||
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
||||||
_set_bit(2);
|
set_has_content();
|
||||||
if (content_ == &_default_content_) {
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
content_ = new ::std::string;
|
content_ = new ::std::string;
|
||||||
}
|
}
|
||||||
return content_;
|
return content_;
|
||||||
}
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_content() {
|
||||||
|
clear_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = content_;
|
||||||
|
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
|
||||||
|
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
delete content_;
|
||||||
|
}
|
||||||
|
if (content) {
|
||||||
|
set_has_content();
|
||||||
|
content_ = content;
|
||||||
|
} else {
|
||||||
|
clear_has_content();
|
||||||
|
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
@ -641,45 +742,73 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
|||||||
|
|
||||||
// optional string error = 1;
|
// optional string error = 1;
|
||||||
inline bool CodeGeneratorResponse::has_error() const {
|
inline bool CodeGeneratorResponse::has_error() const {
|
||||||
return _has_bit(0);
|
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_has_error() {
|
||||||
|
_has_bits_[0] |= 0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::clear_has_error() {
|
||||||
|
_has_bits_[0] &= ~0x00000001u;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse::clear_error() {
|
inline void CodeGeneratorResponse::clear_error() {
|
||||||
if (error_ != &_default_error_) {
|
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
error_->clear();
|
error_->clear();
|
||||||
}
|
}
|
||||||
_clear_bit(0);
|
clear_has_error();
|
||||||
}
|
}
|
||||||
inline const ::std::string& CodeGeneratorResponse::error() const {
|
inline const ::std::string& CodeGeneratorResponse::error() const {
|
||||||
return *error_;
|
return *error_;
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
|
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
|
||||||
_set_bit(0);
|
set_has_error();
|
||||||
if (error_ == &_default_error_) {
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
error_ = new ::std::string;
|
error_ = new ::std::string;
|
||||||
}
|
}
|
||||||
error_->assign(value);
|
error_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse::set_error(const char* value) {
|
inline void CodeGeneratorResponse::set_error(const char* value) {
|
||||||
_set_bit(0);
|
set_has_error();
|
||||||
if (error_ == &_default_error_) {
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
error_ = new ::std::string;
|
error_ = new ::std::string;
|
||||||
}
|
}
|
||||||
error_->assign(value);
|
error_->assign(value);
|
||||||
}
|
}
|
||||||
inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
|
inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
|
||||||
_set_bit(0);
|
set_has_error();
|
||||||
if (error_ == &_default_error_) {
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
error_ = new ::std::string;
|
error_ = new ::std::string;
|
||||||
}
|
}
|
||||||
error_->assign(reinterpret_cast<const char*>(value), size);
|
error_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
}
|
}
|
||||||
inline ::std::string* CodeGeneratorResponse::mutable_error() {
|
inline ::std::string* CodeGeneratorResponse::mutable_error() {
|
||||||
_set_bit(0);
|
set_has_error();
|
||||||
if (error_ == &_default_error_) {
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
error_ = new ::std::string;
|
error_ = new ::std::string;
|
||||||
}
|
}
|
||||||
return error_;
|
return error_;
|
||||||
}
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse::release_error() {
|
||||||
|
clear_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = error_;
|
||||||
|
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
|
||||||
|
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
delete error_;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
set_has_error();
|
||||||
|
error_ = error;
|
||||||
|
} else {
|
||||||
|
clear_has_error();
|
||||||
|
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
inline int CodeGeneratorResponse::file_size() const {
|
inline int CodeGeneratorResponse::file_size() const {
|
@ -45,6 +45,8 @@
|
|||||||
// flag "--${NAME}_out" is passed to protoc.
|
// flag "--${NAME}_out" is passed to protoc.
|
||||||
|
|
||||||
package google.protobuf.compiler;
|
package google.protobuf.compiler;
|
||||||
|
option java_package = "com.google.protobuf.compiler";
|
||||||
|
option java_outer_classname = "PluginProtos";
|
||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
@ -131,7 +133,7 @@ message CodeGeneratorResponse {
|
|||||||
// in order to work correctly in that context.
|
// in order to work correctly in that context.
|
||||||
//
|
//
|
||||||
// The code generator that generates the initial file and the one which
|
// The code generator that generates the initial file and the one which
|
||||||
// inserts into it must both run as part of a single invocatino of protoc.
|
// inserts into it must both run as part of a single invocation of protoc.
|
||||||
// Code generators are executed in the order in which they appear on the
|
// Code generators are executed in the order in which they appear on the
|
||||||
// command line.
|
// command line.
|
||||||
//
|
//
|
@ -52,6 +52,7 @@
|
|||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/stringprintf.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
@ -106,6 +107,12 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
|
|||||||
const char kDescriptorKey[] = "DESCRIPTOR";
|
const char kDescriptorKey[] = "DESCRIPTOR";
|
||||||
|
|
||||||
|
|
||||||
|
// Does the file have top-level enums?
|
||||||
|
inline bool HasTopLevelEnums(const FileDescriptor *file) {
|
||||||
|
return file->enum_type_count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Should we generate generic services for this file?
|
// Should we generate generic services for this file?
|
||||||
inline bool HasGenericServices(const FileDescriptor *file) {
|
inline bool HasGenericServices(const FileDescriptor *file) {
|
||||||
return file->service_count() > 0 &&
|
return file->service_count() > 0 &&
|
||||||
@ -120,13 +127,21 @@ void PrintTopBoilerplate(
|
|||||||
// TODO(robinson): Allow parameterization of Python version?
|
// TODO(robinson): Allow parameterization of Python version?
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||||
"\n"
|
"# source: $filename$\n"
|
||||||
"from google.protobuf import descriptor\n"
|
"\n",
|
||||||
"from google.protobuf import message\n"
|
"filename", file->name());
|
||||||
"from google.protobuf import reflection\n");
|
if (HasTopLevelEnums(file)) {
|
||||||
|
printer->Print(
|
||||||
|
"from google.protobuf.internal import enum_type_wrapper\n");
|
||||||
|
}
|
||||||
|
printer->Print(
|
||||||
|
"from google.protobuf import descriptor as _descriptor\n"
|
||||||
|
"from google.protobuf import message as _message\n"
|
||||||
|
"from google.protobuf import reflection as _reflection\n"
|
||||||
|
);
|
||||||
if (HasGenericServices(file)) {
|
if (HasGenericServices(file)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"from google.protobuf import service\n"
|
"from google.protobuf import service as _service\n"
|
||||||
"from google.protobuf import service_reflection\n");
|
"from google.protobuf import service_reflection\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,12 +219,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
|
|||||||
case FieldDescriptor::CPPTYPE_STRING:
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
if (field.type() == FieldDescriptor::TYPE_STRING) {
|
if (field.type() == FieldDescriptor::TYPE_STRING) {
|
||||||
return "unicode(\"" + CEscape(field.default_value_string()) +
|
return "unicode(\"" + CEscape(field.default_value_string()) +
|
||||||
"\", \"utf-8\")";
|
"\", \"utf-8\")";
|
||||||
} else {
|
} else {
|
||||||
return "\"" + CEscape(field.default_value_string()) + "\"";
|
return "\"" + CEscape(field.default_value_string()) + "\"";
|
||||||
}
|
}
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
// (We could add a default case above but then we wouldn't get the nice
|
// (We could add a default case above but then we wouldn't get the nice
|
||||||
// compiler warning when a new type is added.)
|
// compiler warning when a new type is added.)
|
||||||
@ -230,7 +245,7 @@ Generator::~Generator() {
|
|||||||
|
|
||||||
bool Generator::Generate(const FileDescriptor* file,
|
bool Generator::Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
|
|
||||||
// Completely serialize all Generate() calls on this instance. The
|
// Completely serialize all Generate() calls on this instance. The
|
||||||
@ -252,26 +267,29 @@ bool Generator::Generate(const FileDescriptor* file,
|
|||||||
fdp.SerializeToString(&file_descriptor_serialized_);
|
fdp.SerializeToString(&file_descriptor_serialized_);
|
||||||
|
|
||||||
|
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename));
|
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||||
GOOGLE_CHECK(output.get());
|
GOOGLE_CHECK(output.get());
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer_ = &printer;
|
printer_ = &printer;
|
||||||
|
|
||||||
PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
|
PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
|
||||||
|
PrintImports();
|
||||||
PrintFileDescriptor();
|
PrintFileDescriptor();
|
||||||
PrintTopLevelEnums();
|
PrintTopLevelEnums();
|
||||||
PrintTopLevelExtensions();
|
PrintTopLevelExtensions();
|
||||||
PrintAllNestedEnumsInFile();
|
PrintAllNestedEnumsInFile();
|
||||||
PrintMessageDescriptors();
|
PrintMessageDescriptors();
|
||||||
// We have to print the imports after the descriptors, so that mutually
|
|
||||||
// recursive protos in separate files can successfully reference each other.
|
|
||||||
PrintImports();
|
|
||||||
FixForeignFieldsInDescriptors();
|
FixForeignFieldsInDescriptors();
|
||||||
PrintMessages();
|
PrintMessages();
|
||||||
// We have to fix up the extensions after the message classes themselves,
|
// We have to fix up the extensions after the message classes themselves,
|
||||||
// since they need to call static RegisterExtension() methods on these
|
// since they need to call static RegisterExtension() methods on these
|
||||||
// classes.
|
// classes.
|
||||||
FixForeignFieldsInExtensions();
|
FixForeignFieldsInExtensions();
|
||||||
|
// Descriptor options may have custom extensions. These custom options
|
||||||
|
// can only be successfully parsed after we register corresponding
|
||||||
|
// extensions. Therefore we parse all options again here to recognize
|
||||||
|
// custom options that may be unknown when we define the descriptors.
|
||||||
|
FixAllDescriptorOptions();
|
||||||
if (HasGenericServices(file)) {
|
if (HasGenericServices(file)) {
|
||||||
PrintServices();
|
PrintServices();
|
||||||
}
|
}
|
||||||
@ -290,6 +308,13 @@ void Generator::PrintImports() const {
|
|||||||
module_name);
|
module_name);
|
||||||
}
|
}
|
||||||
printer_->Print("\n");
|
printer_->Print("\n");
|
||||||
|
|
||||||
|
// Print public imports.
|
||||||
|
for (int i = 0; i < file_->public_dependency_count(); ++i) {
|
||||||
|
string module_name = ModuleName(file_->public_dependency(i)->name());
|
||||||
|
printer_->Print("from $module$ import *\n", "module", module_name);
|
||||||
|
}
|
||||||
|
printer_->Print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the single file descriptor for this file.
|
// Prints the single file descriptor for this file.
|
||||||
@ -299,7 +324,7 @@ void Generator::PrintFileDescriptor() const {
|
|||||||
m["name"] = file_->name();
|
m["name"] = file_->name();
|
||||||
m["package"] = file_->package();
|
m["package"] = file_->package();
|
||||||
const char file_descriptor_template[] =
|
const char file_descriptor_template[] =
|
||||||
"$descriptor_name$ = descriptor.FileDescriptor(\n"
|
"$descriptor_name$ = _descriptor.FileDescriptor(\n"
|
||||||
" name='$name$',\n"
|
" name='$name$',\n"
|
||||||
" package='$package$',\n";
|
" package='$package$',\n";
|
||||||
printer_->Print(m, file_descriptor_template);
|
printer_->Print(m, file_descriptor_template);
|
||||||
@ -323,6 +348,11 @@ void Generator::PrintTopLevelEnums() const {
|
|||||||
for (int i = 0; i < file_->enum_type_count(); ++i) {
|
for (int i = 0; i < file_->enum_type_count(); ++i) {
|
||||||
const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
|
const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
|
||||||
PrintEnum(enum_descriptor);
|
PrintEnum(enum_descriptor);
|
||||||
|
printer_->Print("$name$ = "
|
||||||
|
"enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
|
||||||
|
"name", enum_descriptor.name(),
|
||||||
|
"descriptor_name",
|
||||||
|
ModuleLevelDescriptorName(enum_descriptor));
|
||||||
printer_->Print("\n");
|
printer_->Print("\n");
|
||||||
|
|
||||||
for (int j = 0; j < enum_descriptor.value_count(); ++j) {
|
for (int j = 0; j < enum_descriptor.value_count(); ++j) {
|
||||||
@ -357,7 +387,7 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
|
|||||||
m["full_name"] = enum_descriptor.full_name();
|
m["full_name"] = enum_descriptor.full_name();
|
||||||
m["file"] = kDescriptorKey;
|
m["file"] = kDescriptorKey;
|
||||||
const char enum_descriptor_template[] =
|
const char enum_descriptor_template[] =
|
||||||
"$descriptor_name$ = descriptor.EnumDescriptor(\n"
|
"$descriptor_name$ = _descriptor.EnumDescriptor(\n"
|
||||||
" name='$name$',\n"
|
" name='$name$',\n"
|
||||||
" full_name='$full_name$',\n"
|
" full_name='$full_name$',\n"
|
||||||
" filename=None,\n"
|
" filename=None,\n"
|
||||||
@ -377,7 +407,7 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
|
|||||||
printer_->Print("containing_type=None,\n");
|
printer_->Print("containing_type=None,\n");
|
||||||
printer_->Print("options=$options_value$,\n",
|
printer_->Print("options=$options_value$,\n",
|
||||||
"options_value",
|
"options_value",
|
||||||
OptionsValue("EnumOptions", CEscape(options_string)));
|
OptionsValue("EnumOptions", options_string));
|
||||||
EnumDescriptorProto edp;
|
EnumDescriptorProto edp;
|
||||||
PrintSerializedPbInterval(enum_descriptor, edp);
|
PrintSerializedPbInterval(enum_descriptor, edp);
|
||||||
printer_->Outdent();
|
printer_->Outdent();
|
||||||
@ -438,7 +468,7 @@ void Generator::PrintServiceDescriptor(
|
|||||||
descriptor.options().SerializeToString(&options_string);
|
descriptor.options().SerializeToString(&options_string);
|
||||||
|
|
||||||
printer_->Print(
|
printer_->Print(
|
||||||
"$service_name$ = descriptor.ServiceDescriptor(\n",
|
"$service_name$ = _descriptor.ServiceDescriptor(\n",
|
||||||
"service_name", service_name);
|
"service_name", service_name);
|
||||||
printer_->Indent();
|
printer_->Indent();
|
||||||
map<string, string> m;
|
map<string, string> m;
|
||||||
@ -461,7 +491,6 @@ void Generator::PrintServiceDescriptor(
|
|||||||
printer_->Print("methods=[\n");
|
printer_->Print("methods=[\n");
|
||||||
for (int i = 0; i < descriptor.method_count(); ++i) {
|
for (int i = 0; i < descriptor.method_count(); ++i) {
|
||||||
const MethodDescriptor* method = descriptor.method(i);
|
const MethodDescriptor* method = descriptor.method(i);
|
||||||
string options_string;
|
|
||||||
method->options().SerializeToString(&options_string);
|
method->options().SerializeToString(&options_string);
|
||||||
|
|
||||||
m.clear();
|
m.clear();
|
||||||
@ -472,7 +501,7 @@ void Generator::PrintServiceDescriptor(
|
|||||||
m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
|
m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
|
||||||
m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
|
m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
|
||||||
m["options_value"] = OptionsValue("MethodOptions", options_string);
|
m["options_value"] = OptionsValue("MethodOptions", options_string);
|
||||||
printer_->Print("descriptor.MethodDescriptor(\n");
|
printer_->Print("_descriptor.MethodDescriptor(\n");
|
||||||
printer_->Indent();
|
printer_->Indent();
|
||||||
printer_->Print(
|
printer_->Print(
|
||||||
m,
|
m,
|
||||||
@ -493,7 +522,7 @@ void Generator::PrintServiceDescriptor(
|
|||||||
|
|
||||||
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
|
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
|
||||||
// Print the service.
|
// Print the service.
|
||||||
printer_->Print("class $class_name$(service.Service):\n",
|
printer_->Print("class $class_name$(_service.Service):\n",
|
||||||
"class_name", descriptor.name());
|
"class_name", descriptor.name());
|
||||||
printer_->Indent();
|
printer_->Indent();
|
||||||
printer_->Print(
|
printer_->Print(
|
||||||
@ -525,7 +554,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
|
|||||||
PrintNestedDescriptors(message_descriptor);
|
PrintNestedDescriptors(message_descriptor);
|
||||||
|
|
||||||
printer_->Print("\n");
|
printer_->Print("\n");
|
||||||
printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n",
|
printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
|
||||||
"descriptor_name",
|
"descriptor_name",
|
||||||
ModuleLevelDescriptorName(message_descriptor));
|
ModuleLevelDescriptorName(message_descriptor));
|
||||||
printer_->Indent();
|
printer_->Indent();
|
||||||
@ -620,10 +649,10 @@ void Generator::PrintMessages() const {
|
|||||||
// Mutually recursive with PrintNestedMessages().
|
// Mutually recursive with PrintNestedMessages().
|
||||||
void Generator::PrintMessage(
|
void Generator::PrintMessage(
|
||||||
const Descriptor& message_descriptor) const {
|
const Descriptor& message_descriptor) const {
|
||||||
printer_->Print("class $name$(message.Message):\n", "name",
|
printer_->Print("class $name$(_message.Message):\n", "name",
|
||||||
message_descriptor.name());
|
message_descriptor.name());
|
||||||
printer_->Indent();
|
printer_->Indent();
|
||||||
printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n");
|
printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n");
|
||||||
PrintNestedMessages(message_descriptor);
|
PrintNestedMessages(message_descriptor);
|
||||||
map<string, string> m;
|
map<string, string> m;
|
||||||
m["descriptor_key"] = kDescriptorKey;
|
m["descriptor_key"] = kDescriptorKey;
|
||||||
@ -674,6 +703,17 @@ void Generator::FixForeignFieldsInDescriptor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
|
||||||
|
map<string, string> m;
|
||||||
|
m["descriptor_name"] = kDescriptorKey;
|
||||||
|
m["message_name"] = descriptor.name();
|
||||||
|
m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
|
||||||
|
const char file_descriptor_template[] =
|
||||||
|
"$descriptor_name$.message_types_by_name['$message_name$'] = "
|
||||||
|
"$message_descriptor_name$\n";
|
||||||
|
printer_->Print(m, file_descriptor_template);
|
||||||
|
}
|
||||||
|
|
||||||
// Sets any necessary message_type and enum_type attributes
|
// Sets any necessary message_type and enum_type attributes
|
||||||
// for the Python version of |field|.
|
// for the Python version of |field|.
|
||||||
//
|
//
|
||||||
@ -752,6 +792,9 @@ void Generator::FixForeignFieldsInDescriptors() const {
|
|||||||
for (int i = 0; i < file_->message_type_count(); ++i) {
|
for (int i = 0; i < file_->message_type_count(); ++i) {
|
||||||
FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
|
FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < file_->message_type_count(); ++i) {
|
||||||
|
AddMessageToFileDescriptor(*file_->message_type(i));
|
||||||
|
}
|
||||||
printer_->Print("\n");
|
printer_->Print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,6 +810,7 @@ void Generator::FixForeignFieldsInExtensions() const {
|
|||||||
for (int i = 0; i < file_->message_type_count(); ++i) {
|
for (int i = 0; i < file_->message_type_count(); ++i) {
|
||||||
FixForeignFieldsInNestedExtensions(*file_->message_type(i));
|
FixForeignFieldsInNestedExtensions(*file_->message_type(i));
|
||||||
}
|
}
|
||||||
|
printer_->Print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generator::FixForeignFieldsInExtension(
|
void Generator::FixForeignFieldsInExtension(
|
||||||
@ -817,19 +861,21 @@ void Generator::PrintEnumValueDescriptor(
|
|||||||
m["options"] = OptionsValue("EnumValueOptions", options_string);
|
m["options"] = OptionsValue("EnumValueOptions", options_string);
|
||||||
printer_->Print(
|
printer_->Print(
|
||||||
m,
|
m,
|
||||||
"descriptor.EnumValueDescriptor(\n"
|
"_descriptor.EnumValueDescriptor(\n"
|
||||||
" name='$name$', index=$index$, number=$number$,\n"
|
" name='$name$', index=$index$, number=$number$,\n"
|
||||||
" options=$options$,\n"
|
" options=$options$,\n"
|
||||||
" type=None)");
|
" type=None)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a Python expression that calls descriptor._ParseOptions using
|
||||||
|
// the given descriptor class name and serialized options protobuf string.
|
||||||
string Generator::OptionsValue(
|
string Generator::OptionsValue(
|
||||||
const string& class_name, const string& serialized_options) const {
|
const string& class_name, const string& serialized_options) const {
|
||||||
if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
|
if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
|
||||||
return "None";
|
return "None";
|
||||||
} else {
|
} else {
|
||||||
string full_class_name = "descriptor_pb2." + class_name;
|
string full_class_name = "descriptor_pb2." + class_name;
|
||||||
return "descriptor._ParseOptions(" + full_class_name + "(), '"
|
return "_descriptor._ParseOptions(" + full_class_name + "(), '"
|
||||||
+ CEscape(serialized_options)+ "')";
|
+ CEscape(serialized_options)+ "')";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -855,7 +901,7 @@ void Generator::PrintFieldDescriptor(
|
|||||||
// these fields in correctly after all referenced descriptors have been
|
// these fields in correctly after all referenced descriptors have been
|
||||||
// defined and/or imported (see FixForeignFieldsInDescriptors()).
|
// defined and/or imported (see FixForeignFieldsInDescriptors()).
|
||||||
const char field_descriptor_decl[] =
|
const char field_descriptor_decl[] =
|
||||||
"descriptor.FieldDescriptor(\n"
|
"_descriptor.FieldDescriptor(\n"
|
||||||
" name='$name$', full_name='$full_name$', index=$index$,\n"
|
" name='$name$', full_name='$full_name$', index=$index$,\n"
|
||||||
" number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
|
" number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
|
||||||
" has_default_value=$has_default_value$, default_value=$default_value$,\n"
|
" has_default_value=$has_default_value$, default_value=$default_value$,\n"
|
||||||
@ -986,6 +1032,125 @@ void Generator::PrintSerializedPbInterval(
|
|||||||
"serialized_end", SimpleItoa(offset + sp.size()));
|
"serialized_end", SimpleItoa(offset + sp.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void PrintDescriptorOptionsFixingCode(const string& descriptor,
|
||||||
|
const string& options,
|
||||||
|
io::Printer* printer) {
|
||||||
|
// TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
|
||||||
|
// in proto2 python runtime but it couldn't be used here because appengine
|
||||||
|
// uses a snapshot version of the library in which the new method is not
|
||||||
|
// yet present. After appengine has synced their runtime library, the code
|
||||||
|
// below should be cleaned up to use _SetOptions().
|
||||||
|
printer->Print(
|
||||||
|
"$descriptor$.has_options = True\n"
|
||||||
|
"$descriptor$._options = $options$\n",
|
||||||
|
"descriptor", descriptor, "options", options);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Prints expressions that set the options field of all descriptors.
|
||||||
|
void Generator::FixAllDescriptorOptions() const {
|
||||||
|
// Prints an expression that sets the file descriptor's options.
|
||||||
|
string file_options = OptionsValue(
|
||||||
|
"FileOptions", file_->options().SerializeAsString());
|
||||||
|
if (file_options != "None") {
|
||||||
|
PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
|
||||||
|
}
|
||||||
|
// Prints expressions that set the options for all top level enums.
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); ++i) {
|
||||||
|
const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
|
||||||
|
FixOptionsForEnum(enum_descriptor);
|
||||||
|
}
|
||||||
|
// Prints expressions that set the options for all top level extensions.
|
||||||
|
for (int i = 0; i < file_->extension_count(); ++i) {
|
||||||
|
const FieldDescriptor& field = *file_->extension(i);
|
||||||
|
FixOptionsForField(field);
|
||||||
|
}
|
||||||
|
// Prints expressions that set the options for all messages, nested enums,
|
||||||
|
// nested extensions and message fields.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); ++i) {
|
||||||
|
FixOptionsForMessage(*file_->message_type(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints expressions that set the options for an enum descriptor and its
|
||||||
|
// value descriptors.
|
||||||
|
void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
|
||||||
|
string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
|
||||||
|
string enum_options = OptionsValue(
|
||||||
|
"EnumOptions", enum_descriptor.options().SerializeAsString());
|
||||||
|
if (enum_options != "None") {
|
||||||
|
PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < enum_descriptor.value_count(); ++i) {
|
||||||
|
const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
|
||||||
|
string value_options = OptionsValue(
|
||||||
|
"EnumValueOptions", value_descriptor.options().SerializeAsString());
|
||||||
|
if (value_options != "None") {
|
||||||
|
PrintDescriptorOptionsFixingCode(
|
||||||
|
StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
|
||||||
|
value_descriptor.name().c_str()),
|
||||||
|
value_options, printer_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints expressions that set the options for field descriptors (including
|
||||||
|
// extensions).
|
||||||
|
void Generator::FixOptionsForField(
|
||||||
|
const FieldDescriptor& field) const {
|
||||||
|
string field_options = OptionsValue(
|
||||||
|
"FieldOptions", field.options().SerializeAsString());
|
||||||
|
if (field_options != "None") {
|
||||||
|
string field_name;
|
||||||
|
if (field.is_extension()) {
|
||||||
|
if (field.extension_scope() == NULL) {
|
||||||
|
// Top level extensions.
|
||||||
|
field_name = field.name();
|
||||||
|
} else {
|
||||||
|
field_name = FieldReferencingExpression(
|
||||||
|
field.extension_scope(), field, "extensions_by_name");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
field_name = FieldReferencingExpression(
|
||||||
|
field.containing_type(), field, "fields_by_name");
|
||||||
|
}
|
||||||
|
PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints expressions that set the options for a message and all its inner
|
||||||
|
// types (nested messages, nested enums, extensions, fields).
|
||||||
|
void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
|
||||||
|
// Nested messages.
|
||||||
|
for (int i = 0; i < descriptor.nested_type_count(); ++i) {
|
||||||
|
FixOptionsForMessage(*descriptor.nested_type(i));
|
||||||
|
}
|
||||||
|
// Enums.
|
||||||
|
for (int i = 0; i < descriptor.enum_type_count(); ++i) {
|
||||||
|
FixOptionsForEnum(*descriptor.enum_type(i));
|
||||||
|
}
|
||||||
|
// Fields.
|
||||||
|
for (int i = 0; i < descriptor.field_count(); ++i) {
|
||||||
|
const FieldDescriptor& field = *descriptor.field(i);
|
||||||
|
FixOptionsForField(field);
|
||||||
|
}
|
||||||
|
// Extensions.
|
||||||
|
for (int i = 0; i < descriptor.extension_count(); ++i) {
|
||||||
|
const FieldDescriptor& field = *descriptor.extension(i);
|
||||||
|
FixOptionsForField(field);
|
||||||
|
}
|
||||||
|
// Message option for this message.
|
||||||
|
string message_options = OptionsValue(
|
||||||
|
"MessageOptions", descriptor.options().SerializeAsString());
|
||||||
|
if (message_options != "None") {
|
||||||
|
string descriptor_name = ModuleLevelDescriptorName(descriptor);
|
||||||
|
PrintDescriptorOptionsFixingCode(descriptor_name,
|
||||||
|
message_options,
|
||||||
|
printer_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace python
|
} // namespace python
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
@ -66,7 +66,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
|
|||||||
// CodeGenerator methods.
|
// CodeGenerator methods.
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* generator_context,
|
||||||
string* error) const;
|
string* error) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -104,6 +104,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
|
|||||||
void FixForeignFieldsInField(const Descriptor* containing_type,
|
void FixForeignFieldsInField(const Descriptor* containing_type,
|
||||||
const FieldDescriptor& field,
|
const FieldDescriptor& field,
|
||||||
const string& python_dict_name) const;
|
const string& python_dict_name) const;
|
||||||
|
void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
|
||||||
string FieldReferencingExpression(const Descriptor* containing_type,
|
string FieldReferencingExpression(const Descriptor* containing_type,
|
||||||
const FieldDescriptor& field,
|
const FieldDescriptor& field,
|
||||||
const string& python_dict_name) const;
|
const string& python_dict_name) const;
|
||||||
@ -137,6 +138,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
|
|||||||
void PrintSerializedPbInterval(
|
void PrintSerializedPbInterval(
|
||||||
const DescriptorT& descriptor, DescriptorProtoT& proto) const;
|
const DescriptorT& descriptor, DescriptorProtoT& proto) const;
|
||||||
|
|
||||||
|
void FixAllDescriptorOptions() const;
|
||||||
|
void FixOptionsForField(const FieldDescriptor& field) const;
|
||||||
|
void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
|
||||||
|
void FixOptionsForMessage(const Descriptor& descriptor) const;
|
||||||
|
|
||||||
// Very coarse-grained lock to ensure that Generate() is reentrant.
|
// Very coarse-grained lock to ensure that Generate() is reentrant.
|
||||||
// Guards file_, printer_ and file_descriptor_serialized_.
|
// Guards file_, printer_ and file_descriptor_serialized_.
|
||||||
mutable Mutex mutex_;
|
mutable Mutex mutex_;
|
@ -56,19 +56,19 @@ class TestGenerator : public CodeGenerator {
|
|||||||
|
|
||||||
virtual bool Generate(const FileDescriptor* file,
|
virtual bool Generate(const FileDescriptor* file,
|
||||||
const string& parameter,
|
const string& parameter,
|
||||||
OutputDirectory* output_directory,
|
GeneratorContext* context,
|
||||||
string* error) const {
|
string* error) const {
|
||||||
TryInsert("test_pb2.py", "imports", output_directory);
|
TryInsert("test_pb2.py", "imports", context);
|
||||||
TryInsert("test_pb2.py", "module_scope", output_directory);
|
TryInsert("test_pb2.py", "module_scope", context);
|
||||||
TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory);
|
TryInsert("test_pb2.py", "class_scope:foo.Bar", context);
|
||||||
TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory);
|
TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryInsert(const string& filename, const string& insertion_point,
|
void TryInsert(const string& filename, const string& insertion_point,
|
||||||
OutputDirectory* output_directory) const {
|
GeneratorContext* context) const {
|
||||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
output_directory->OpenForInsert(filename, insertion_point));
|
context->OpenForInsert(filename, insertion_point));
|
||||||
io::Printer printer(output.get(), '$');
|
io::Printer printer(output.get(), '$');
|
||||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||||
}
|
}
|
@ -32,13 +32,16 @@
|
|||||||
|
|
||||||
#include <google/protobuf/compiler/subprocess.h>
|
#include <google/protobuf/compiler/subprocess.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
#include <google/protobuf/message.h>
|
#include <google/protobuf/message.h>
|
||||||
#include <google/protobuf/stubs/substitute.h>
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
@ -96,7 +99,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup STARTUPINFO to redirect handles.
|
// Setup STARTUPINFO to redirect handles.
|
||||||
STARTUPINFO startup_info;
|
STARTUPINFOA startup_info;
|
||||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||||
startup_info.cb = sizeof(startup_info);
|
startup_info.cb = sizeof(startup_info);
|
||||||
startup_info.dwFlags = STARTF_USESTDHANDLES;
|
startup_info.dwFlags = STARTF_USESTDHANDLES;
|
||||||
@ -115,16 +118,16 @@ void Subprocess::Start(const string& program, SearchMode search_mode) {
|
|||||||
// Create the process.
|
// Create the process.
|
||||||
PROCESS_INFORMATION process_info;
|
PROCESS_INFORMATION process_info;
|
||||||
|
|
||||||
if (CreateProcess((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
|
if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
|
||||||
(search_mode == SEARCH_PATH) ? name_copy : NULL,
|
(search_mode == SEARCH_PATH) ? name_copy : NULL,
|
||||||
NULL, // process security attributes
|
NULL, // process security attributes
|
||||||
NULL, // thread security attributes
|
NULL, // thread security attributes
|
||||||
TRUE, // inherit handles?
|
TRUE, // inherit handles?
|
||||||
0, // obscure creation flags
|
0, // obscure creation flags
|
||||||
NULL, // environment (inherit from parent)
|
NULL, // environment (inherit from parent)
|
||||||
NULL, // current directory (inherit from parent)
|
NULL, // current directory (inherit from parent)
|
||||||
&startup_info,
|
&startup_info,
|
||||||
&process_info)) {
|
&process_info)) {
|
||||||
child_handle_ = process_info.hProcess;
|
child_handle_ = process_info.hProcess;
|
||||||
CloseHandleOrDie(process_info.hThread);
|
CloseHandleOrDie(process_info.hThread);
|
||||||
child_stdin_ = stdin_pipe_write;
|
child_stdin_ = stdin_pipe_write;
|
||||||
@ -292,8 +295,8 @@ void Subprocess::Start(const string& program, SearchMode search_mode) {
|
|||||||
int stdin_pipe[2];
|
int stdin_pipe[2];
|
||||||
int stdout_pipe[2];
|
int stdout_pipe[2];
|
||||||
|
|
||||||
pipe(stdin_pipe);
|
GOOGLE_CHECK(pipe(stdin_pipe) != -1);
|
||||||
pipe(stdout_pipe);
|
GOOGLE_CHECK(pipe(stdout_pipe) != -1);
|
||||||
|
|
||||||
char* argv[2] = { strdup(program.c_str()), NULL };
|
char* argv[2] = { strdup(program.c_str()), NULL };
|
||||||
|
|
||||||
@ -321,9 +324,11 @@ void Subprocess::Start(const string& program, SearchMode search_mode) {
|
|||||||
|
|
||||||
// Write directly to STDERR_FILENO to avoid stdio code paths that may do
|
// Write directly to STDERR_FILENO to avoid stdio code paths that may do
|
||||||
// stuff that is unsafe here.
|
// stuff that is unsafe here.
|
||||||
write(STDERR_FILENO, argv[0], strlen(argv[0]));
|
int ignored;
|
||||||
|
ignored = write(STDERR_FILENO, argv[0], strlen(argv[0]));
|
||||||
const char* message = ": program not found or is not executable\n";
|
const char* message = ": program not found or is not executable\n";
|
||||||
write(STDERR_FILENO, message, strlen(message));
|
ignored = write(STDERR_FILENO, message, strlen(message));
|
||||||
|
(void) ignored;
|
||||||
|
|
||||||
// Must use _exit() rather than exit() to avoid flushing output buffers
|
// Must use _exit() rather than exit() to avoid flushing output buffers
|
||||||
// that will also be flushed by the parent.
|
// that will also be flushed by the parent.
|
@ -40,9 +40,10 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -52,7 +53,7 @@ class Message;
|
|||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
// Utility class for launching sub-processes.
|
// Utility class for launching sub-processes.
|
||||||
class Subprocess {
|
class LIBPROTOC_EXPORT Subprocess {
|
||||||
public:
|
public:
|
||||||
Subprocess();
|
Subprocess();
|
||||||
~Subprocess();
|
~Subprocess();
|
||||||
@ -76,7 +77,7 @@ class Subprocess {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Given an error code, returns a human-readable error message. This is
|
// Given an error code, returns a human-readable error message. This is
|
||||||
// defined here so that CommandLineInterface can share it.
|
// defined here so that CommandLineInterface can share it.
|
||||||
static string Subprocess::Win32ErrorMessage(DWORD error_code);
|
static string Win32ErrorMessage(DWORD error_code);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
@ -39,45 +39,51 @@ fail() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_TMPDIR=.
|
||||||
|
PROTOC=./protoc
|
||||||
|
|
||||||
echo '
|
echo '
|
||||||
|
syntax = "proto2";
|
||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
option java_package = "test.jar";
|
option java_package = "test.jar";
|
||||||
option java_outer_classname = "Outer";
|
option java_outer_classname = "Outer";
|
||||||
message Foo {}
|
message Foo {}
|
||||||
message Bar {}
|
message Bar {}
|
||||||
' > testzip.proto
|
' > $TEST_TMPDIR/testzip.proto
|
||||||
|
|
||||||
./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \
|
$PROTOC \
|
||||||
testzip.proto || fail 'protoc failed.'
|
--cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \
|
||||||
|
--java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \
|
||||||
|
|| fail 'protoc failed.'
|
||||||
|
|
||||||
echo "Testing output to zip..."
|
echo "Testing output to zip..."
|
||||||
if unzip -h > /dev/null; then
|
if unzip -h > /dev/null; then
|
||||||
unzip -t testzip.zip > testzip.list || fail 'unzip failed.'
|
unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
|
||||||
|
|
||||||
grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \
|
grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'testzip.pb.cc not found in output zip.'
|
|| fail 'testzip.pb.cc not found in output zip.'
|
||||||
grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \
|
grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'testzip.pb.h not found in output zip.'
|
|| fail 'testzip.pb.h not found in output zip.'
|
||||||
grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \
|
grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'testzip_pb2.py not found in output zip.'
|
|| fail 'testzip_pb2.py not found in output zip.'
|
||||||
grep -i 'manifest' testzip.list > /dev/null \
|
grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
&& fail 'Zip file contained manifest.'
|
&& fail 'Zip file contained manifest.'
|
||||||
else
|
else
|
||||||
echo "Warning: 'unzip' command not available. Skipping test."
|
echo "Warning: 'unzip' command not available. Skipping test."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Testing output to jar..."
|
echo "Testing output to jar..."
|
||||||
if jar c testzip.proto > /dev/null; then
|
if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
|
||||||
jar tf testzip.jar > testzip.list || fail 'jar failed.'
|
jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.'
|
||||||
|
|
||||||
grep '^test/jar/Foo\.java$' testzip.list > /dev/null \
|
grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'Foo.java not found in output jar.'
|
|| fail 'Foo.java not found in output jar.'
|
||||||
grep '^test/jar/Bar\.java$' testzip.list > /dev/null \
|
grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'Bar.java not found in output jar.'
|
|| fail 'Bar.java not found in output jar.'
|
||||||
grep '^test/jar/Outer\.java$' testzip.list > /dev/null \
|
grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'Outer.java not found in output jar.'
|
|| fail 'Outer.java not found in output jar.'
|
||||||
grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \
|
grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \
|
||||||
|| fail 'Manifest not ofund in output jar.'
|
|| fail 'Manifest not found in output jar.'
|
||||||
else
|
else
|
||||||
echo "Warning: 'jar' command not available. Skipping test."
|
echo "Warning: 'jar' command not available. Skipping test."
|
||||||
fi
|
fi
|
@ -28,6 +28,36 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// Author: ambrose@google.com (Ambrose Feinstein),
|
// Author: ambrose@google.com (Ambrose Feinstein),
|
||||||
// kenton@google.com (Kenton Varda)
|
// kenton@google.com (Kenton Varda)
|
||||||
//
|
//
|
||||||
@ -183,6 +213,6 @@ bool ZipWriter::WriteDirectory() {
|
|||||||
return output.HadError();
|
return output.HadError();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace google
|
|
||||||
} // namespace protobuf
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,93 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class ZipWriter {
|
||||||
|
public:
|
||||||
|
ZipWriter(io::ZeroCopyOutputStream* raw_output);
|
||||||
|
~ZipWriter();
|
||||||
|
|
||||||
|
bool Write(const string& filename, const string& contents);
|
||||||
|
bool WriteDirectory();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct FileInfo {
|
||||||
|
string name;
|
||||||
|
uint32 offset;
|
||||||
|
uint32 size;
|
||||||
|
uint32 crc32;
|
||||||
|
};
|
||||||
|
|
||||||
|
io::ZeroCopyOutputStream* raw_output_;
|
||||||
|
vector<FileInfo> files_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,10 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <google/protobuf/stubs/common.h>
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
|
||||||
|
#ifdef TYPE_BOOL
|
||||||
|
#undef TYPE_BOOL
|
||||||
|
#endif // TYPE_BOOL
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
namespace protobuf {
|
namespace protobuf {
|
||||||
@ -89,6 +93,7 @@ class ServiceOptions;
|
|||||||
class MethodOptions;
|
class MethodOptions;
|
||||||
class FileOptions;
|
class FileOptions;
|
||||||
class UninterpretedOption;
|
class UninterpretedOption;
|
||||||
|
class SourceCodeInfo;
|
||||||
|
|
||||||
// Defined in message.h
|
// Defined in message.h
|
||||||
class Message;
|
class Message;
|
||||||
@ -100,6 +105,20 @@ class FileDescriptorTables;
|
|||||||
// Defined in unknown_field_set.h.
|
// Defined in unknown_field_set.h.
|
||||||
class UnknownField;
|
class UnknownField;
|
||||||
|
|
||||||
|
// NB, all indices are zero-based.
|
||||||
|
struct SourceLocation {
|
||||||
|
int start_line;
|
||||||
|
int end_line;
|
||||||
|
int start_column;
|
||||||
|
int end_column;
|
||||||
|
|
||||||
|
// Doc comments found at the source location.
|
||||||
|
// TODO(kenton): Maybe this struct should have been named SourceInfo or
|
||||||
|
// something instead. Oh well.
|
||||||
|
string leading_comments;
|
||||||
|
string trailing_comments;
|
||||||
|
};
|
||||||
|
|
||||||
// Describes a type of protocol message, or a particular group within a
|
// Describes a type of protocol message, or a particular group within a
|
||||||
// message. To obtain the Descriptor for a given message object, call
|
// message. To obtain the Descriptor for a given message object, call
|
||||||
// Message::GetDescriptor(). Generated message classes also have a
|
// Message::GetDescriptor(). Generated message classes also have a
|
||||||
@ -236,6 +255,13 @@ class LIBPROTOBUF_EXPORT Descriptor {
|
|||||||
// this message type's scope.
|
// this message type's scope.
|
||||||
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
|
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this message declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef MessageOptions OptionsType;
|
typedef MessageOptions OptionsType;
|
||||||
|
|
||||||
@ -243,6 +269,10 @@ class LIBPROTOBUF_EXPORT Descriptor {
|
|||||||
// correct depth
|
// correct depth
|
||||||
void DebugString(int depth, string *contents) const;
|
void DebugString(int depth, string *contents) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
const FileDescriptor* file_;
|
const FileDescriptor* file_;
|
||||||
@ -388,15 +418,19 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
|
|||||||
// when parsing formats which prefer to use camel-case naming style.
|
// when parsing formats which prefer to use camel-case naming style.
|
||||||
const string& camelcase_name() const;
|
const string& camelcase_name() const;
|
||||||
|
|
||||||
Type type() const; // Declared type of this field.
|
Type type() const; // Declared type of this field.
|
||||||
CppType cpp_type() const; // C++ type of this field.
|
const char* type_name() const; // Name of the declared type.
|
||||||
Label label() const; // optional/required/repeated
|
CppType cpp_type() const; // C++ type of this field.
|
||||||
|
const char* cpp_type_name() const; // Name of the C++ type.
|
||||||
|
Label label() const; // optional/required/repeated
|
||||||
|
|
||||||
bool is_required() const; // shorthand for label() == LABEL_REQUIRED
|
bool is_required() const; // shorthand for label() == LABEL_REQUIRED
|
||||||
bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL
|
bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL
|
||||||
bool is_repeated() const; // shorthand for label() == LABEL_REPEATED
|
bool is_repeated() const; // shorthand for label() == LABEL_REPEATED
|
||||||
bool is_packable() const; // shorthand for is_repeated() &&
|
bool is_packable() const; // shorthand for is_repeated() &&
|
||||||
// IsTypePackable(type())
|
// IsTypePackable(type())
|
||||||
|
bool is_packed() const; // shorthand for is_packable() &&
|
||||||
|
// options().packed()
|
||||||
|
|
||||||
// Index of this field within the message's field array, or the file or
|
// Index of this field within the message's field array, or the file or
|
||||||
// extension scope's extensions array.
|
// extension scope's extensions array.
|
||||||
@ -479,6 +513,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
|
|||||||
// Return true iff [packed = true] is valid for fields of this type.
|
// Return true iff [packed = true] is valid for fields of this type.
|
||||||
static inline bool IsTypePackable(Type field_type);
|
static inline bool IsTypePackable(Type field_type);
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this field declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef FieldOptions OptionsType;
|
typedef FieldOptions OptionsType;
|
||||||
|
|
||||||
@ -490,6 +531,10 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
|
|||||||
// types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
|
// types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
|
||||||
string DefaultValueAsString(bool quote_string_type) const;
|
string DefaultValueAsString(bool quote_string_type) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
const string* lowercase_name_;
|
const string* lowercase_name_;
|
||||||
@ -527,6 +572,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
|
|||||||
|
|
||||||
static const char * const kTypeToName[MAX_TYPE + 1];
|
static const char * const kTypeToName[MAX_TYPE + 1];
|
||||||
|
|
||||||
|
static const char * const kCppTypeToName[MAX_CPPTYPE + 1];
|
||||||
|
|
||||||
static const char * const kLabelToName[MAX_LABEL + 1];
|
static const char * const kLabelToName[MAX_LABEL + 1];
|
||||||
|
|
||||||
// Must be constructed using DescriptorPool.
|
// Must be constructed using DescriptorPool.
|
||||||
@ -583,12 +630,23 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
|
|||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
string DebugString() const;
|
string DebugString() const;
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this enum declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef EnumOptions OptionsType;
|
typedef EnumOptions OptionsType;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
void DebugString(int depth, string *contents) const;
|
void DebugString(int depth, string *contents) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
const FileDescriptor* file_;
|
const FileDescriptor* file_;
|
||||||
@ -650,12 +708,23 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
|
|||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
string DebugString() const;
|
string DebugString() const;
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this enum value declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef EnumValueOptions OptionsType;
|
typedef EnumValueOptions OptionsType;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
void DebugString(int depth, string *contents) const;
|
void DebugString(int depth, string *contents) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
int number_;
|
int number_;
|
||||||
@ -703,19 +772,29 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
|
|||||||
|
|
||||||
// Look up a MethodDescriptor by name.
|
// Look up a MethodDescriptor by name.
|
||||||
const MethodDescriptor* FindMethodByName(const string& name) const;
|
const MethodDescriptor* FindMethodByName(const string& name) const;
|
||||||
|
|
||||||
// See Descriptor::CopyTo().
|
// See Descriptor::CopyTo().
|
||||||
void CopyTo(ServiceDescriptorProto* proto) const;
|
void CopyTo(ServiceDescriptorProto* proto) const;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
string DebugString() const;
|
string DebugString() const;
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this service declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef ServiceOptions OptionsType;
|
typedef ServiceOptions OptionsType;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
void DebugString(string *contents) const;
|
void DebugString(string *contents) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
const FileDescriptor* file_;
|
const FileDescriptor* file_;
|
||||||
@ -768,12 +847,23 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
|
|||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
string DebugString() const;
|
string DebugString() const;
|
||||||
|
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of this method declaration. Returns false and leaves
|
||||||
|
// |*out_location| unchanged iff location information was not available.
|
||||||
|
bool GetSourceLocation(SourceLocation* out_location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef MethodOptions OptionsType;
|
typedef MethodOptions OptionsType;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
void DebugString(int depth, string *contents) const;
|
void DebugString(int depth, string *contents) const;
|
||||||
|
|
||||||
|
// Walks up the descriptor tree to generate the source location path
|
||||||
|
// to this descriptor from the file root.
|
||||||
|
void GetLocationPath(vector<int>* output) const;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
const string* full_name_;
|
const string* full_name_;
|
||||||
const ServiceDescriptor* service_;
|
const ServiceDescriptor* service_;
|
||||||
@ -791,6 +881,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
|
|||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Describes a whole .proto file. To get the FileDescriptor for a compiled-in
|
// Describes a whole .proto file. To get the FileDescriptor for a compiled-in
|
||||||
// file, get the descriptor for something defined in that file and call
|
// file, get the descriptor for something defined in that file and call
|
||||||
// descriptor->file(). Use DescriptorPool to construct your own descriptors.
|
// descriptor->file(). Use DescriptorPool to construct your own descriptors.
|
||||||
@ -813,6 +904,22 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
|
|||||||
// These are returned in the order they were defined in the .proto file.
|
// These are returned in the order they were defined in the .proto file.
|
||||||
const FileDescriptor* dependency(int index) const;
|
const FileDescriptor* dependency(int index) const;
|
||||||
|
|
||||||
|
// The number of files public imported by this one.
|
||||||
|
// The public dependency list is a subset of the dependency list.
|
||||||
|
int public_dependency_count() const;
|
||||||
|
// Gets a public imported file by index, where 0 <= index <
|
||||||
|
// public_dependency_count().
|
||||||
|
// These are returned in the order they were defined in the .proto file.
|
||||||
|
const FileDescriptor* public_dependency(int index) const;
|
||||||
|
|
||||||
|
// The number of files that are imported for weak fields.
|
||||||
|
// The weak dependency list is a subset of the dependency list.
|
||||||
|
int weak_dependency_count() const;
|
||||||
|
// Gets a weak imported file by index, where 0 <= index <
|
||||||
|
// weak_dependency_count().
|
||||||
|
// These are returned in the order they were defined in the .proto file.
|
||||||
|
const FileDescriptor* weak_dependency(int index) const;
|
||||||
|
|
||||||
// Number of top-level message types defined in this file. (This does not
|
// Number of top-level message types defined in this file. (This does not
|
||||||
// include nested types.)
|
// include nested types.)
|
||||||
int message_type_count() const;
|
int message_type_count() const;
|
||||||
@ -866,12 +973,28 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
|
|||||||
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
|
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
|
||||||
|
|
||||||
// See Descriptor::CopyTo().
|
// See Descriptor::CopyTo().
|
||||||
|
// Notes:
|
||||||
|
// - This method does NOT copy source code information since it is relatively
|
||||||
|
// large and rarely needed. See CopySourceCodeInfoTo() below.
|
||||||
void CopyTo(FileDescriptorProto* proto) const;
|
void CopyTo(FileDescriptorProto* proto) const;
|
||||||
|
// Write the source code information of this FileDescriptor into the given
|
||||||
|
// FileDescriptorProto. See CopyTo() above.
|
||||||
|
void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
|
||||||
|
|
||||||
// See Descriptor::DebugString().
|
// See Descriptor::DebugString().
|
||||||
string DebugString() const;
|
string DebugString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Source Location ---------------------------------------------------
|
||||||
|
|
||||||
|
// Updates |*out_location| to the source location of the complete
|
||||||
|
// extent of the declaration or declaration-part denoted by |path|.
|
||||||
|
// Returns false and leaves |*out_location| unchanged iff location
|
||||||
|
// information was not available. (See SourceCodeInfo for
|
||||||
|
// description of path encoding.)
|
||||||
|
bool GetSourceLocation(const vector<int>& path,
|
||||||
|
SourceLocation* out_location) const;
|
||||||
|
|
||||||
typedef FileOptions OptionsType;
|
typedef FileOptions OptionsType;
|
||||||
|
|
||||||
const string* name_;
|
const string* name_;
|
||||||
@ -879,6 +1002,10 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
|
|||||||
const DescriptorPool* pool_;
|
const DescriptorPool* pool_;
|
||||||
int dependency_count_;
|
int dependency_count_;
|
||||||
const FileDescriptor** dependencies_;
|
const FileDescriptor** dependencies_;
|
||||||
|
int public_dependency_count_;
|
||||||
|
int* public_dependencies_;
|
||||||
|
int weak_dependency_count_;
|
||||||
|
int* weak_dependencies_;
|
||||||
int message_type_count_;
|
int message_type_count_;
|
||||||
Descriptor* message_types_;
|
Descriptor* message_types_;
|
||||||
int enum_type_count_;
|
int enum_type_count_;
|
||||||
@ -890,6 +1017,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
|
|||||||
const FileOptions* options_;
|
const FileOptions* options_;
|
||||||
|
|
||||||
const FileDescriptorTables* tables_;
|
const FileDescriptorTables* tables_;
|
||||||
|
const SourceCodeInfo* source_code_info_;
|
||||||
// IMPORTANT: If you add a new field, make sure to search for all instances
|
// IMPORTANT: If you add a new field, make sure to search for all instances
|
||||||
// of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
|
// of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
|
||||||
// descriptor.cc and update them to initialize the field.
|
// descriptor.cc and update them to initialize the field.
|
||||||
@ -899,6 +1027,8 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
|
|||||||
friend class Descriptor;
|
friend class Descriptor;
|
||||||
friend class FieldDescriptor;
|
friend class FieldDescriptor;
|
||||||
friend class EnumDescriptor;
|
friend class EnumDescriptor;
|
||||||
|
friend class EnumValueDescriptor;
|
||||||
|
friend class MethodDescriptor;
|
||||||
friend class ServiceDescriptor;
|
friend class ServiceDescriptor;
|
||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
|
||||||
};
|
};
|
||||||
@ -1106,7 +1236,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
|
|||||||
// For internal use only: Gets a non-const pointer to the generated pool.
|
// For internal use only: Gets a non-const pointer to the generated pool.
|
||||||
// This is called at static-initialization time only, so thread-safety is
|
// This is called at static-initialization time only, so thread-safety is
|
||||||
// not a concern. If both an underlay and a fallback database are present,
|
// not a concern. If both an underlay and a fallback database are present,
|
||||||
// the fallback database takes precedence.
|
// the underlay takes precedence.
|
||||||
static DescriptorPool* internal_generated_pool();
|
static DescriptorPool* internal_generated_pool();
|
||||||
|
|
||||||
// For internal use only: Changes the behavior of BuildFile() such that it
|
// For internal use only: Changes the behavior of BuildFile() such that it
|
||||||
@ -1132,6 +1262,11 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
|
|||||||
friend class FileDescriptor;
|
friend class FileDescriptor;
|
||||||
friend class DescriptorBuilder;
|
friend class DescriptorBuilder;
|
||||||
|
|
||||||
|
// Return true if the given name is a sub-symbol of any non-package
|
||||||
|
// descriptor that already exists in the descriptor pool. (The full
|
||||||
|
// definition of such types is already known.)
|
||||||
|
bool IsSubSymbolOfBuiltType(const string& name) const;
|
||||||
|
|
||||||
// Tries to find something in the fallback database and link in the
|
// Tries to find something in the fallback database and link in the
|
||||||
// corresponding proto file. Returns true if successful, in which case
|
// corresponding proto file. Returns true if successful, in which case
|
||||||
// the caller should search for the thing again. These are declared
|
// the caller should search for the thing again. These are declared
|
||||||
@ -1203,7 +1338,7 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range,
|
|||||||
const Descriptor::ExtensionRange*)
|
const Descriptor::ExtensionRange*)
|
||||||
PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
|
PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
|
||||||
const FieldDescriptor*)
|
const FieldDescriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
|
||||||
@ -1220,7 +1355,7 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*)
|
|||||||
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*)
|
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, experimental_map_key,
|
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, experimental_map_key,
|
||||||
const FieldDescriptor*)
|
const FieldDescriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool)
|
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 )
|
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 )
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 )
|
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 )
|
||||||
@ -1240,13 +1375,13 @@ PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*)
|
|||||||
PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int)
|
||||||
PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value,
|
PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value,
|
||||||
const EnumValueDescriptor*)
|
const EnumValueDescriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name)
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int)
|
PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*)
|
PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, name)
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, full_name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, full_name)
|
||||||
@ -1254,24 +1389,25 @@ PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*)
|
|||||||
PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int)
|
||||||
PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method,
|
PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method,
|
||||||
const MethodDescriptor*)
|
const MethodDescriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name)
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*)
|
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*)
|
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*)
|
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
|
||||||
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
|
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int)
|
||||||
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int)
|
||||||
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int)
|
||||||
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int)
|
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int)
|
||||||
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions);
|
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions)
|
||||||
|
|
||||||
PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*)
|
PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*)
|
||||||
PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*)
|
PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*)
|
||||||
@ -1342,10 +1478,18 @@ inline int MethodDescriptor::index() const {
|
|||||||
return this - service_->methods_;
|
return this - service_->methods_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const char* FieldDescriptor::type_name() const {
|
||||||
|
return kTypeToName[type_];
|
||||||
|
}
|
||||||
|
|
||||||
inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
|
inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
|
||||||
return kTypeToCppTypeMap[type_];
|
return kTypeToCppTypeMap[type_];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const char* FieldDescriptor::cpp_type_name() const {
|
||||||
|
return kCppTypeToName[kTypeToCppTypeMap[type_]];
|
||||||
|
}
|
||||||
|
|
||||||
inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
|
inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
|
||||||
return kTypeToCppTypeMap[type];
|
return kTypeToCppTypeMap[type];
|
||||||
}
|
}
|
||||||
@ -1361,6 +1505,16 @@ inline const FileDescriptor* FileDescriptor::dependency(int index) const {
|
|||||||
return dependencies_[index];
|
return dependencies_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const FileDescriptor* FileDescriptor::public_dependency(
|
||||||
|
int index) const {
|
||||||
|
return dependencies_[public_dependencies_[index]];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const FileDescriptor* FileDescriptor::weak_dependency(
|
||||||
|
int index) const {
|
||||||
|
return dependencies_[weak_dependencies_[index]];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
||||||
|
|
||||||
} // namespace google
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,11 @@ message FileDescriptorProto {
|
|||||||
|
|
||||||
// Names of files imported by this file.
|
// Names of files imported by this file.
|
||||||
repeated string dependency = 3;
|
repeated string dependency = 3;
|
||||||
|
// Indexes of the public imported files in the dependency list above.
|
||||||
|
repeated int32 public_dependency = 10;
|
||||||
|
// Indexes of the weak imported files in the dependency list.
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
repeated int32 weak_dependency = 11;
|
||||||
|
|
||||||
// All top-level definitions in this file.
|
// All top-level definitions in this file.
|
||||||
repeated DescriptorProto message_type = 4;
|
repeated DescriptorProto message_type = 4;
|
||||||
@ -67,6 +72,12 @@ message FileDescriptorProto {
|
|||||||
repeated FieldDescriptorProto extension = 7;
|
repeated FieldDescriptorProto extension = 7;
|
||||||
|
|
||||||
optional FileOptions options = 8;
|
optional FileOptions options = 8;
|
||||||
|
|
||||||
|
// This field contains optional information about the original source code.
|
||||||
|
// You may safely remove this entire field whithout harming runtime
|
||||||
|
// functionality of the descriptors -- the information is needed only by
|
||||||
|
// development tools.
|
||||||
|
optional SourceCodeInfo source_code_info = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes a message type.
|
// Describes a message type.
|
||||||
@ -95,13 +106,13 @@ message FieldDescriptorProto {
|
|||||||
// Order is weird for historical reasons.
|
// Order is weird for historical reasons.
|
||||||
TYPE_DOUBLE = 1;
|
TYPE_DOUBLE = 1;
|
||||||
TYPE_FLOAT = 2;
|
TYPE_FLOAT = 2;
|
||||||
TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
|
||||||
// take 10 bytes. Use TYPE_SINT64 if negative
|
// negative values are likely.
|
||||||
// values are likely.
|
TYPE_INT64 = 3;
|
||||||
TYPE_UINT64 = 4;
|
TYPE_UINT64 = 4;
|
||||||
TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
|
||||||
// take 10 bytes. Use TYPE_SINT32 if negative
|
// negative values are likely.
|
||||||
// values are likely.
|
TYPE_INT32 = 5;
|
||||||
TYPE_FIXED64 = 6;
|
TYPE_FIXED64 = 6;
|
||||||
TYPE_FIXED32 = 7;
|
TYPE_FIXED32 = 7;
|
||||||
TYPE_BOOL = 8;
|
TYPE_BOOL = 8;
|
||||||
@ -193,6 +204,7 @@ message MethodDescriptorProto {
|
|||||||
optional MethodOptions options = 4;
|
optional MethodOptions options = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// Options
|
// Options
|
||||||
|
|
||||||
@ -214,10 +226,15 @@ message MethodDescriptorProto {
|
|||||||
// through 99999. It is up to you to ensure that you do not use the
|
// through 99999. It is up to you to ensure that you do not use the
|
||||||
// same number for multiple options.
|
// same number for multiple options.
|
||||||
// * For options which will be published and used publicly by multiple
|
// * For options which will be published and used publicly by multiple
|
||||||
// independent entities, e-mail kenton@google.com to reserve extension
|
// independent entities, e-mail protobuf-global-extension-registry@google.com
|
||||||
// numbers. Simply tell me how many you need and I'll send you back a
|
// to reserve extension numbers. Simply provide your project name (e.g.
|
||||||
// set of numbers to use -- there's no need to explain how you intend to
|
// Object-C plugin) and your porject website (if available) -- there's no need
|
||||||
// use them. If this turns out to be popular, a web service will be set up
|
// to explain how you intend to use them. Usually you only need one extension
|
||||||
|
// number. You can declare multiple options with only one extension number by
|
||||||
|
// putting them in a sub-message. See the Custom Options section of the docs
|
||||||
|
// for examples:
|
||||||
|
// http://code.google.com/apis/protocolbuffers/docs/proto.html#options
|
||||||
|
// If this turns out to be popular, a web service will be set up
|
||||||
// to automatically assign option numbers.
|
// to automatically assign option numbers.
|
||||||
|
|
||||||
|
|
||||||
@ -245,6 +262,12 @@ message FileOptions {
|
|||||||
// top-level extensions defined in the file.
|
// top-level extensions defined in the file.
|
||||||
optional bool java_multiple_files = 10 [default=false];
|
optional bool java_multiple_files = 10 [default=false];
|
||||||
|
|
||||||
|
// If set true, then the Java code generator will generate equals() and
|
||||||
|
// hashCode() methods for all messages defined in the .proto file. This is
|
||||||
|
// purely a speed optimization, as the AbstractMessage base class includes
|
||||||
|
// reflection-based implementations of these methods.
|
||||||
|
optional bool java_generate_equals_and_hash = 20 [default=false];
|
||||||
|
|
||||||
// Generated classes can be optimized for speed or code size.
|
// Generated classes can be optimized for speed or code size.
|
||||||
enum OptimizeMode {
|
enum OptimizeMode {
|
||||||
SPEED = 1; // Generate complete code for parsing, serialization,
|
SPEED = 1; // Generate complete code for parsing, serialization,
|
||||||
@ -254,6 +277,9 @@ message FileOptions {
|
|||||||
}
|
}
|
||||||
optional OptimizeMode optimize_for = 9 [default=SPEED];
|
optional OptimizeMode optimize_for = 9 [default=SPEED];
|
||||||
|
|
||||||
|
// Sets the Go package where structs generated from this .proto will be
|
||||||
|
// placed. There is no default.
|
||||||
|
optional string go_package = 11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -264,13 +290,12 @@ message FileOptions {
|
|||||||
// early versions of proto2.
|
// early versions of proto2.
|
||||||
//
|
//
|
||||||
// Generic services are now considered deprecated in favor of using plugins
|
// Generic services are now considered deprecated in favor of using plugins
|
||||||
// that generate code specific to your particular RPC system. If you are
|
// that generate code specific to your particular RPC system. Therefore,
|
||||||
// using such a plugin, set these to false. In the future, we may change
|
// these default to false. Old code which depends on generic services should
|
||||||
// the default to false, so if you explicitly want generic services, you
|
// explicitly set them to true.
|
||||||
// should explicitly set these to true.
|
optional bool cc_generic_services = 16 [default=false];
|
||||||
optional bool cc_generic_services = 16 [default=true];
|
optional bool java_generic_services = 17 [default=false];
|
||||||
optional bool java_generic_services = 17 [default=true];
|
optional bool py_generic_services = 18 [default=false];
|
||||||
optional bool py_generic_services = 18 [default=true];
|
|
||||||
|
|
||||||
// The parser stores options it doesn't recognize here. See above.
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
repeated UninterpretedOption uninterpreted_option = 999;
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
@ -333,6 +358,37 @@ message FieldOptions {
|
|||||||
optional bool packed = 2;
|
optional bool packed = 2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
|
// inner message's contents will not be parsed but instead stored in encoded
|
||||||
|
// form. The inner message will actually be parsed when it is first accessed.
|
||||||
|
//
|
||||||
|
// This is only a hint. Implementations are free to choose whether to use
|
||||||
|
// eager or lazy parsing regardless of the value of this option. However,
|
||||||
|
// setting this option true suggests that the protocol author believes that
|
||||||
|
// using lazy parsing on this field is worth the additional bookkeeping
|
||||||
|
// overhead typically needed to implement it.
|
||||||
|
//
|
||||||
|
// This option does not affect the public interface of any generated code;
|
||||||
|
// all method signatures remain the same. Furthermore, thread-safety of the
|
||||||
|
// interface is not affected by this option; const methods remain safe to
|
||||||
|
// call from multiple threads concurrently, while non-const methods continue
|
||||||
|
// to require exclusive access.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Note that implementations may choose not to check required fields within
|
||||||
|
// a lazy sub-message. That is, calling IsInitialized() on the outher message
|
||||||
|
// may return true even if the inner message has missing required fields.
|
||||||
|
// This is necessary because otherwise the inner message would have to be
|
||||||
|
// parsed in order to perform the check, defeating the purpose of lazy
|
||||||
|
// parsing. An implementation which chooses not to check required fields
|
||||||
|
// must be consistent about it. That is, for any particular sub-message, the
|
||||||
|
// implementation must either *always* check its required fields, or *never*
|
||||||
|
// check its required fields, regardless of whether or not the message has
|
||||||
|
// been parsed.
|
||||||
|
optional bool lazy = 5 [default=false];
|
||||||
|
|
||||||
// Is this field deprecated?
|
// Is this field deprecated?
|
||||||
// Depending on the target platform, this can emit Deprecated annotations
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
// for accessors, or it will be completely ignored; in the very least, this
|
// for accessors, or it will be completely ignored; in the very least, this
|
||||||
@ -353,6 +409,9 @@ message FieldOptions {
|
|||||||
// TODO: Fully-implement this, then remove the "experimental_" prefix.
|
// TODO: Fully-implement this, then remove the "experimental_" prefix.
|
||||||
optional string experimental_map_key = 9;
|
optional string experimental_map_key = 9;
|
||||||
|
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
optional bool weak = 10 [default=false];
|
||||||
|
|
||||||
// The parser stores options it doesn't recognize here. See above.
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
repeated UninterpretedOption uninterpreted_option = 999;
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
@ -362,6 +421,10 @@ message FieldOptions {
|
|||||||
|
|
||||||
message EnumOptions {
|
message EnumOptions {
|
||||||
|
|
||||||
|
// Set this option to false to disallow mapping different tag names to a same
|
||||||
|
// value.
|
||||||
|
optional bool allow_alias = 2 [default=true];
|
||||||
|
|
||||||
// The parser stores options it doesn't recognize here. See above.
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
repeated UninterpretedOption uninterpreted_option = 999;
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
@ -405,6 +468,7 @@ message MethodOptions {
|
|||||||
extensions 1000 to max;
|
extensions 1000 to max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// A message representing a option the parser does not recognize. This only
|
// A message representing a option the parser does not recognize. This only
|
||||||
// appears in options protos created by the compiler::Parser class.
|
// appears in options protos created by the compiler::Parser class.
|
||||||
// DescriptorPool resolves these when building Descriptor objects. Therefore,
|
// DescriptorPool resolves these when building Descriptor objects. Therefore,
|
||||||
@ -430,4 +494,127 @@ message UninterpretedOption {
|
|||||||
optional int64 negative_int_value = 5;
|
optional int64 negative_int_value = 5;
|
||||||
optional double double_value = 6;
|
optional double double_value = 6;
|
||||||
optional bytes string_value = 7;
|
optional bytes string_value = 7;
|
||||||
|
optional string aggregate_value = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Optional source code info
|
||||||
|
|
||||||
|
// Encapsulates information about the original source file from which a
|
||||||
|
// FileDescriptorProto was generated.
|
||||||
|
message SourceCodeInfo {
|
||||||
|
// A Location identifies a piece of source code in a .proto file which
|
||||||
|
// corresponds to a particular definition. This information is intended
|
||||||
|
// to be useful to IDEs, code indexers, documentation generators, and similar
|
||||||
|
// tools.
|
||||||
|
//
|
||||||
|
// For example, say we have a file like:
|
||||||
|
// message Foo {
|
||||||
|
// optional string foo = 1;
|
||||||
|
// }
|
||||||
|
// Let's look at just the field definition:
|
||||||
|
// optional string foo = 1;
|
||||||
|
// ^ ^^ ^^ ^ ^^^
|
||||||
|
// a bc de f ghi
|
||||||
|
// We have the following locations:
|
||||||
|
// span path represents
|
||||||
|
// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
|
||||||
|
// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
|
||||||
|
// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
|
||||||
|
// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
|
||||||
|
// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - A location may refer to a repeated field itself (i.e. not to any
|
||||||
|
// particular index within it). This is used whenever a set of elements are
|
||||||
|
// logically enclosed in a single code segment. For example, an entire
|
||||||
|
// extend block (possibly containing multiple extension definitions) will
|
||||||
|
// have an outer location whose path refers to the "extensions" repeated
|
||||||
|
// field without an index.
|
||||||
|
// - Multiple locations may have the same path. This happens when a single
|
||||||
|
// logical declaration is spread out across multiple places. The most
|
||||||
|
// obvious example is the "extend" block again -- there may be multiple
|
||||||
|
// extend blocks in the same scope, each of which will have the same path.
|
||||||
|
// - A location's span is not always a subset of its parent's span. For
|
||||||
|
// example, the "extendee" of an extension declaration appears at the
|
||||||
|
// beginning of the "extend" block and is shared by all extensions within
|
||||||
|
// the block.
|
||||||
|
// - Just because a location's span is a subset of some other location's span
|
||||||
|
// does not mean that it is a descendent. For example, a "group" defines
|
||||||
|
// both a type and a field in a single declaration. Thus, the locations
|
||||||
|
// corresponding to the type and field and their components will overlap.
|
||||||
|
// - Code which tries to interpret locations should probably be designed to
|
||||||
|
// ignore those that it doesn't understand, as more types of locations could
|
||||||
|
// be recorded in the future.
|
||||||
|
repeated Location location = 1;
|
||||||
|
message Location {
|
||||||
|
// Identifies which part of the FileDescriptorProto was defined at this
|
||||||
|
// location.
|
||||||
|
//
|
||||||
|
// Each element is a field number or an index. They form a path from
|
||||||
|
// the root FileDescriptorProto to the place where the definition. For
|
||||||
|
// example, this path:
|
||||||
|
// [ 4, 3, 2, 7, 1 ]
|
||||||
|
// refers to:
|
||||||
|
// file.message_type(3) // 4, 3
|
||||||
|
// .field(7) // 2, 7
|
||||||
|
// .name() // 1
|
||||||
|
// This is because FileDescriptorProto.message_type has field number 4:
|
||||||
|
// repeated DescriptorProto message_type = 4;
|
||||||
|
// and DescriptorProto.field has field number 2:
|
||||||
|
// repeated FieldDescriptorProto field = 2;
|
||||||
|
// and FieldDescriptorProto.name has field number 1:
|
||||||
|
// optional string name = 1;
|
||||||
|
//
|
||||||
|
// Thus, the above path gives the location of a field name. If we removed
|
||||||
|
// the last element:
|
||||||
|
// [ 4, 3, 2, 7 ]
|
||||||
|
// this path refers to the whole field declaration (from the beginning
|
||||||
|
// of the label to the terminating semicolon).
|
||||||
|
repeated int32 path = 1 [packed=true];
|
||||||
|
|
||||||
|
// Always has exactly three or four elements: start line, start column,
|
||||||
|
// end line (optional, otherwise assumed same as start line), end column.
|
||||||
|
// These are packed into a single field for efficiency. Note that line
|
||||||
|
// and column numbers are zero-based -- typically you will want to add
|
||||||
|
// 1 to each before displaying to a user.
|
||||||
|
repeated int32 span = 2 [packed=true];
|
||||||
|
|
||||||
|
// If this SourceCodeInfo represents a complete declaration, these are any
|
||||||
|
// comments appearing before and after the declaration which appear to be
|
||||||
|
// attached to the declaration.
|
||||||
|
//
|
||||||
|
// A series of line comments appearing on consecutive lines, with no other
|
||||||
|
// tokens appearing on those lines, will be treated as a single comment.
|
||||||
|
//
|
||||||
|
// Only the comment content is provided; comment markers (e.g. //) are
|
||||||
|
// stripped out. For block comments, leading whitespace and an asterisk
|
||||||
|
// will be stripped from the beginning of each line other than the first.
|
||||||
|
// Newlines are included in the output.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// optional int32 foo = 1; // Comment attached to foo.
|
||||||
|
// // Comment attached to bar.
|
||||||
|
// optional int32 bar = 2;
|
||||||
|
//
|
||||||
|
// optional string baz = 3;
|
||||||
|
// // Comment attached to baz.
|
||||||
|
// // Another line attached to baz.
|
||||||
|
//
|
||||||
|
// // Comment attached to qux.
|
||||||
|
// //
|
||||||
|
// // Another line attached to qux.
|
||||||
|
// optional double qux = 4;
|
||||||
|
//
|
||||||
|
// optional string corge = 5;
|
||||||
|
// /* Block comment attached
|
||||||
|
// * to corge. Leading asterisks
|
||||||
|
// * will be removed. */
|
||||||
|
// /* Block comment attached to
|
||||||
|
// * grault. */
|
||||||
|
// optional int32 grault = 6;
|
||||||
|
optional string leading_comments = 3;
|
||||||
|
optional string trailing_comments = 4;
|
||||||
|
}
|
||||||
}
|
}
|
@ -39,7 +39,7 @@
|
|||||||
#include <google/protobuf/descriptor.pb.h>
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
#include <google/protobuf/wire_format_lite_inl.h>
|
#include <google/protobuf/wire_format_lite_inl.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/stubs/stl_util-inl.h>
|
#include <google/protobuf/stubs/stl_util.h>
|
||||||
#include <google/protobuf/stubs/map-util.h>
|
#include <google/protobuf/stubs/map-util.h>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@ -101,7 +101,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
|
|||||||
|
|
||||||
if (iter == by_symbol_.end()) {
|
if (iter == by_symbol_.end()) {
|
||||||
// Apparently the map is currently empty. Just insert and be done with it.
|
// Apparently the map is currently empty. Just insert and be done with it.
|
||||||
by_symbol_.insert(make_pair(name, value));
|
by_symbol_.insert(typename map<string, Value>::value_type(name, value));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
|
|||||||
|
|
||||||
// Insert the new symbol using the iterator as a hint, the new entry will
|
// Insert the new symbol using the iterator as a hint, the new entry will
|
||||||
// appear immediately before the one the iterator is pointing at.
|
// appear immediately before the one the iterator is pointing at.
|
||||||
by_symbol_.insert(iter, make_pair(name, value));
|
by_symbol_.insert(iter, typename map<string, Value>::value_type(name, value));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user