base: DestinyCore upstream @2d631f4e (fork SylvaniaCore ; sql/old retire)

This commit is contained in:
SylvaniaCore deploy
2026-06-17 09:00:37 +00:00
commit f8fcb8ad38
4834 changed files with 2810723 additions and 0 deletions
@@ -0,0 +1,288 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <set>
#include <map>
#include "google/protobuf/compiler/cpp/cpp_enum.h"
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include <google/protobuf/io/printer.h>
#include "google/protobuf/stubs/strutil.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
// generation of the GOOGLE_ARRAYSIZE constant.
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
int32 max_value = descriptor->value(0)->number();
for (int i = 0; i < descriptor->value_count(); i++) {
if (descriptor->value(i)->number() > max_value) {
max_value = descriptor->value(i)->number();
}
}
return max_value != kint32max;
}
} // namespace
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
options_(options),
generate_array_size_(ShouldGenerateArraySize(descriptor)) {
}
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
vars["short_name"] = descriptor_->name();
printer->Print(vars, "enum $classname$ {\n");
printer->Indent();
const EnumValueDescriptor* min_value = descriptor_->value(0);
const EnumValueDescriptor* max_value = descriptor_->value(0);
for (int i = 0; i < descriptor_->value_count(); i++) {
vars["name"] = descriptor_->value(i)->name();
// In C++, an value of -2147483648 gets interpreted as the negative of
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
// compiler warning. This works around that issue.
vars["number"] = Int32ToString(descriptor_->value(i)->number());
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
"" : classname_ + "_";
if (i > 0) printer->Print(",\n");
printer->Print(vars, "$prefix$$name$ = $number$");
if (descriptor_->value(i)->number() < min_value->number()) {
min_value = descriptor_->value(i);
}
if (descriptor_->value(i)->number() > max_value->number()) {
max_value = descriptor_->value(i);
}
}
printer->Outdent();
printer->Print("\n};\n");
vars["min_name"] = min_value->name();
vars["max_name"] = max_value->name();
if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
vars["dllexport"] = options_.dllexport_decl + " ";
}
printer->Print(vars,
"$dllexport$bool $classname$_IsValid(int value);\n"
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n");
if (generate_array_size_) {
printer->Print(vars,
"const int $prefix$$short_name$_ARRAYSIZE = "
"$prefix$$short_name$_MAX + 1;\n\n");
}
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(vars,
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
// The _Name and _Parse methods
printer->Print(vars,
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
" return ::google::protobuf::internal::NameOfEnum(\n"
" $classname$_descriptor(), value);\n"
"}\n");
printer->Print(vars,
"inline bool $classname$_Parse(\n"
" const ::std::string& name, $classname$* value) {\n"
" return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
" $classname$_descriptor(), name, value);\n"
"}\n");
}
}
void EnumGenerator::
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(
"template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n"
"template <>\n"
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
" return $classname$_descriptor();\n"
"}\n",
"classname", ClassName(descriptor_, true));
}
}
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
map<string, string> vars;
vars["nested_name"] = descriptor_->name();
vars["classname"] = classname_;
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
for (int j = 0; j < descriptor_->value_count(); j++) {
vars["tag"] = descriptor_->value(j)->name();
printer->Print(vars,
"static const $nested_name$ $tag$ = $classname$_$tag$;\n");
}
printer->Print(vars,
"static inline bool $nested_name$_IsValid(int value) {\n"
" return $classname$_IsValid(value);\n"
"}\n"
"static const $nested_name$ $nested_name$_MIN =\n"
" $classname$_$nested_name$_MIN;\n"
"static const $nested_name$ $nested_name$_MAX =\n"
" $classname$_$nested_name$_MAX;\n");
if (generate_array_size_) {
printer->Print(vars,
"static const int $nested_name$_ARRAYSIZE =\n"
" $classname$_$nested_name$_ARRAYSIZE;\n");
}
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(vars,
"static inline const ::google::protobuf::EnumDescriptor*\n"
"$nested_name$_descriptor() {\n"
" return $classname$_descriptor();\n"
"}\n");
printer->Print(vars,
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
" return $classname$_Name(value);\n"
"}\n");
printer->Print(vars,
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
" $nested_name$* value) {\n"
" return $classname$_Parse(name, value);\n"
"}\n");
}
}
void EnumGenerator::GenerateDescriptorInitializer(
io::Printer* printer, int index) {
map<string, string> vars;
vars["classname"] = classname_;
vars["index"] = SimpleItoa(index);
if (descriptor_->containing_type() == NULL) {
printer->Print(vars,
"$classname$_descriptor_ = file->enum_type($index$);\n");
} else {
vars["parent"] = ClassName(descriptor_->containing_type(), false);
printer->Print(vars,
"$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
}
}
void EnumGenerator::GenerateMethods(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(vars,
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
" protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n");
}
printer->Print(vars,
"bool $classname$_IsValid(int value) {\n"
" switch(value) {\n");
// Multiple values may have the same number. Make sure we only cover
// each number once by first constructing a set containing all valid
// numbers, then printing a case statement for each element.
set<int> numbers;
for (int j = 0; j < descriptor_->value_count(); j++) {
const EnumValueDescriptor* value = descriptor_->value(j);
numbers.insert(value->number());
}
for (set<int>::iterator iter = numbers.begin();
iter != numbers.end(); ++iter) {
printer->Print(
" case $number$:\n",
"number", Int32ToString(*iter));
}
printer->Print(vars,
" return true;\n"
" default:\n"
" return false;\n"
" }\n"
"}\n"
"\n");
if (descriptor_->containing_type() != NULL) {
// We need to "define" the static constants which were declared in the
// header, to give the linker a place to put them. Or at least the C++
// standard says we have to. MSVC actually insists tha we do _not_ define
// them again in the .cc file.
printer->Print("#ifndef _MSC_VER\n");
vars["parent"] = ClassName(descriptor_->containing_type(), false);
vars["nested_name"] = descriptor_->name();
for (int i = 0; i < descriptor_->value_count(); i++) {
vars["value"] = descriptor_->value(i)->name();
printer->Print(vars,
"const $classname$ $parent$::$value$;\n");
}
printer->Print(vars,
"const $classname$ $parent$::$nested_name$_MIN;\n"
"const $classname$ $parent$::$nested_name$_MAX;\n");
if (generate_array_size_) {
printer->Print(vars,
"const int $parent$::$nested_name$_ARRAYSIZE;\n");
}
printer->Print("#endif // _MSC_VER\n");
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,103 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#include <string>
#include "google/protobuf/compiler/cpp/cpp_options.h"
#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit EnumGenerator(const EnumDescriptor* descriptor,
const Options& options);
~EnumGenerator();
// Header stuff.
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
// nested enums.
void GenerateDefinition(io::Printer* printer);
// Generate specialization of GetEnumDescriptor<MyEnum>().
// Precondition: in ::google::protobuf namespace.
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
// For enums nested within a message, generate code to import all the enum's
// symbols (e.g. the enum type name, all its values, etc.) into the class's
// namespace. This should be placed inside the class definition in the
// header.
void GenerateSymbolImports(io::Printer* printer);
// Source file stuff.
// Generate code that initializes the global variable storing the enum's
// descriptor.
void GenerateDescriptorInitializer(io::Printer* printer, int index);
// Generate non-inline methods related to the enum, such as IsValidValue().
// Goes in the .cc file.
void GenerateMethods(io::Printer* printer);
private:
const EnumDescriptor* descriptor_;
string classname_;
Options options_;
// whether to generate the *_ARRAYSIZE constant.
bool generate_array_size_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
@@ -0,0 +1,433 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_enum_field.h"
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include "google/protobuf/stubs/strutil.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void SetEnumVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
(*variables)["default"] = Int32ToString(default_value->number());
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
EnumFieldGenerator::
EnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetEnumVariables(descriptor, &variables_, options);
}
EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "int $name$_;\n");
}
void EnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $name$() const$deprecation$;\n"
"inline void set_$name$($type$ value)$deprecation$;\n");
}
void EnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" assert($type$_IsValid(value));\n"
" set_has_$name$();\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void EnumFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "set_$name$(from.$name$());\n");
}
void EnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
}
void EnumFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
void EnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
" input, &value)));\n"
"if ($type$_IsValid(value)) {\n"
" set_$name$(static_cast< $type$ >(value));\n");
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(variables_,
"} else {\n"
" mutable_unknown_fields()->AddVarint($number$, value);\n");
} else {
printer->Print(
"} else {\n"
" unknown_fields_stream.WriteVarint32(tag);\n"
" unknown_fields_stream.WriteVarint32(value);\n");
}
printer->Print(variables_,
"}\n");
}
void EnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
" $number$, this->$name$(), output);\n");
}
void EnumFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
" $number$, this->$name$(), target);\n");
}
void EnumFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
}
// ===================================================================
EnumOneofFieldGenerator::
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: EnumFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
void EnumOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
" if (has_$name$()) {\n"
" return static_cast< $type$ >($oneof_prefix$$name$_);\n"
" }\n"
" return static_cast< $type$ >($default$);\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" assert($type$_IsValid(value));\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
"}\n");
}
void EnumOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
}
void EnumOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void EnumOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
" $classname$_default_oneof_instance_->$name$_ = $default$;\n");
}
// ===================================================================
RepeatedEnumFieldGenerator::
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetEnumVariables(descriptor, &variables_, options);
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField<int> $name$_;\n");
if (descriptor_->options().packed()
&& HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
}
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $name$(int index) const$deprecation$;\n"
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
"inline void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
"inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
" assert($type$_IsValid(value));\n"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
" assert($type$_IsValid(value));\n"
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedField<int>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::google::protobuf::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Clear();\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedEnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void RepeatedEnumFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_, "_$name$_cached_byte_size_ = 0;\n");
}
}
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
// Don't use ReadRepeatedPrimitive here so that the enum can be validated.
printer->Print(variables_,
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
" input, &value)));\n"
"if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n");
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(variables_,
"} else {\n"
" mutable_unknown_fields()->AddVarint($number$, value);\n");
} else {
printer->Print(
"} else {\n"
" unknown_fields_stream.WriteVarint32(tag);\n"
" unknown_fields_stream.WriteVarint32(value);\n");
}
printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
if (!descriptor_->options().packed()) {
// We use a non-inlined implementation in this case, since this path will
// rarely be executed.
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
" input,\n"
" &$type$_IsValid,\n"
" this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
"::google::protobuf::uint32 length;\n"
"DO_(input->ReadVarint32(&length));\n"
"::google::protobuf::io::CodedInputStream::Limit limit = "
"input->PushLimit(length);\n"
"while (input->BytesUntilLimit() > 0) {\n"
" int value;\n"
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
" input, &value)));\n"
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
" }\n"
"}\n"
"input->PopLimit(limit);\n");
}
}
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
if (descriptor_->options().packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
" ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
" $number$,\n"
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
" output);\n"
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
" this->$name$(i), output);\n");
} else {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
" $number$, this->$name$(i), output);\n");
}
printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
if (descriptor_->options().packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
" $number$,\n"
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
" target);\n"
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
" _$name$_cached_byte_size_, target);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
" this->$name$(i), target);\n");
} else {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
" $number$, this->$name$(i), target);\n");
}
printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
" int data_size = 0;\n");
printer->Indent();
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
" this->$name$(i));\n"
"}\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
}
printer->Outdent();
printer->Print("}\n");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,122 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
#include <map>
#include <string>
#include "google/protobuf/compiler/cpp/cpp_field.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumFieldGenerator : public FieldGenerator {
public:
explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
};
class EnumOneofFieldGenerator : public EnumFieldGenerator {
public:
explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~EnumOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
};
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
@@ -0,0 +1,210 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_extension.h"
#include <map>
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include "google/protobuf/stubs/strutil.h"
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
// Returns the fully-qualified class name of the message that this field
// extends. This function is used in the Google-internal code to handle some
// legacy cases.
string ExtendeeClassName(const FieldDescriptor* descriptor) {
const Descriptor* extendee = descriptor->containing_type();
return ClassName(extendee, true);
}
} // anonymous namespace
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
options_(options) {
// Construct type_traits_.
if (descriptor_->is_repeated()) {
type_traits_ = "Repeated";
}
switch (descriptor_->cpp_type()) {
case FieldDescriptor::CPPTYPE_ENUM:
type_traits_.append("EnumTypeTraits< ");
type_traits_.append(ClassName(descriptor_->enum_type(), true));
type_traits_.append(", ");
type_traits_.append(ClassName(descriptor_->enum_type(), true));
type_traits_.append("_IsValid>");
break;
case FieldDescriptor::CPPTYPE_STRING:
type_traits_.append("StringTypeTraits");
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
type_traits_.append("MessageTypeTraits< ");
type_traits_.append(ClassName(descriptor_->message_type(), true));
type_traits_.append(" >");
break;
default:
type_traits_.append("PrimitiveTypeTraits< ");
type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
type_traits_.append(" >");
break;
}
}
ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
vars["name" ] = descriptor_->name();
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
vars["constant_name"] = FieldConstantName(descriptor_);
// If this is a class member, it needs to be declared "static". Otherwise,
// it needs to be "extern". In the latter case, it also needs the DLL
// export/import specifier.
if (descriptor_->extension_scope() == NULL) {
vars["qualifier"] = "extern";
if (!options_.dllexport_decl.empty()) {
vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
}
} else {
vars["qualifier"] = "static";
}
printer->Print(vars,
"static const int $constant_name$ = $number$;\n"
"$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
" $name$;\n"
);
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
// If this is a class member, it needs to be declared in its class scope.
string scope = (descriptor_->extension_scope() == NULL) ? "" :
ClassName(descriptor_->extension_scope(), false) + "::";
string name = scope + descriptor_->name();
map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["type_traits" ] = type_traits_;
vars["name" ] = name;
vars["constant_name"] = FieldConstantName(descriptor_);
vars["default" ] = DefaultValue(descriptor_);
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
vars["scope" ] = scope;
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
// We need to declare a global string which will contain the default value.
// We cannot declare it at class scope because that would require exposing
// it in the header which would be annoying for other reasons. So we
// replace :: with _ in the name and declare it as a global.
string global_name = StringReplace(name, "::", "_", true);
vars["global_name"] = global_name;
printer->Print(vars,
"const ::std::string $global_name$_default($default$);\n");
// Update the default to refer to the string global.
vars["default"] = global_name + "_default";
}
// Likewise, class members need to declare the field constant variable.
if (descriptor_->extension_scope() != NULL) {
printer->Print(vars,
"#ifndef _MSC_VER\n"
"const int $scope$$constant_name$;\n"
"#endif\n");
}
printer->Print(vars,
"::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
" $name$($constant_name$, $default$);\n");
}
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
vars["is_packed" ] = (descriptor_->is_repeated() &&
descriptor_->options().packed())
? "true" : "false";
switch (descriptor_->cpp_type()) {
case FieldDescriptor::CPPTYPE_ENUM:
printer->Print(vars,
"::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
" &$extendee$::default_instance(),\n"
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
printer->Print(
" &$type$_IsValid);\n",
"type", ClassName(descriptor_->enum_type(), true));
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
printer->Print(vars,
"::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
" &$extendee$::default_instance(),\n"
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
printer->Print(
" &$type$::default_instance());\n",
"type", ClassName(descriptor_->message_type(), true));
break;
default:
printer->Print(vars,
"::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
" &$extendee$::default_instance(),\n"
" $number$, $field_type$, $is_repeated$, $is_packed$);\n");
break;
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,86 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
#include <string>
#include <google/protobuf/stubs/common.h>
#include "google/protobuf/compiler/cpp/cpp_options.h"
namespace google {
namespace protobuf {
class FieldDescriptor; // descriptor.h
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace cpp {
// Generates code for an extension, which may be within the scope of some
// message or may be at file scope. This is much simpler than FieldGenerator
// since extensions are just simple identifiers with interesting types.
class ExtensionGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
const Options& options);
~ExtensionGenerator();
// Header stuff.
void GenerateDeclaration(io::Printer* printer);
// Source file stuff.
void GenerateDefinition(io::Printer* printer);
// Generate code to register the extension.
void GenerateRegistration(io::Printer* printer);
private:
const FieldDescriptor* descriptor_;
string type_traits_;
Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
@@ -0,0 +1,166 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_field.h"
#include <memory>
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include "google/protobuf/compiler/cpp/cpp_primitive_field.h"
#include "google/protobuf/compiler/cpp/cpp_string_field.h"
#include "google/protobuf/compiler/cpp/cpp_enum_field.h"
#include "google/protobuf/compiler/cpp/cpp_message_field.h"
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/common.h>
#include "google/protobuf/stubs/strutil.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
using internal::WireFormat;
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options) {
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = SimpleItoa(descriptor->index());
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["deprecation"] = descriptor->options().deprecated()
? " PROTOBUF_DEPRECATED" : "";
(*variables)["cppget"] = "Get";
}
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
(*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_.";
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
}
FieldGenerator::~FieldGenerator() {}
void FieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
// Reaching here indicates a bug. Cases are:
// - This FieldGenerator should support packing, but this method should be
// overridden.
// - This FieldGenerator doesn't support packing, and this method should
// never have been called.
GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
<< "called on field generator that does not support packing.";
}
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
field_generators_(
new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
}
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
const Options& options) {
if (field->is_repeated()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // RepeatedStringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
return new RepeatedStringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field, options);
default:
return new RepeatedPrimitiveFieldGenerator(field, options);
}
} else if (field->containing_oneof()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageOneofFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringOneofFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
return new StringOneofFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumOneofFieldGenerator(field, options);
default:
return new PrimitiveOneofFieldGenerator(field, options);
}
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
return new StringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumFieldGenerator(field, options);
default:
return new PrimitiveFieldGenerator(field, options);
}
}
}
FieldGeneratorMap::~FieldGeneratorMap() {}
const FieldGenerator& FieldGeneratorMap::get(
const FieldDescriptor* field) const {
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
return *field_generators_[field->index()];
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,185 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
#include <map>
#include <memory>
#include <string>
#include <google/protobuf/descriptor.h>
#include "google/protobuf/compiler/cpp/cpp_options.h"
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace cpp {
// Helper function: set variables in the map that are the same for all
// field code generators.
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
// 'deprecation'].
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options);
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables);
class FieldGenerator {
public:
FieldGenerator() {}
virtual ~FieldGenerator();
// Generate lines of code declaring members fields of the message class
// needed to represent this field. These are placed inside the message
// class.
virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
// Generate static default variable for this field. These are placed inside
// the message class. Most field types don't need this, so the default
// implementation is empty.
virtual void GenerateStaticMembers(io::Printer* printer) const {}
// Generate prototypes for all of the accessor functions related to this
// field. These are placed inside the class definition.
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
// Generate inline definitions of accessor functions for this field.
// These are placed inside the header after all class definitions.
virtual void GenerateInlineAccessorDefinitions(
io::Printer* printer) const = 0;
// Generate definitions of accessors that aren't inlined. These are
// placed somewhere in the .cc file.
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const {}
// Generate lines of code (statements, not declarations) which clear the
// field. This is used to define the clear_$name$() method as well as
// the Clear() method for the whole message.
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
// Generate lines of code (statements, not declarations) which merges the
// contents of the field from the current message to the target message,
// which is stored in the generated code variable "from".
// This is used to fill in the MergeFrom method for the whole message.
// Details of this usage can be found in message.cc under the
// GenerateMergeFrom method.
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
// Generate lines of code (statements, not declarations) which swaps
// this field and the corresponding field of another message, which
// is stored in the generated code variable "other". This is used to
// define the Swap method. Details of usage can be found in
// message.cc under the GenerateSwap method.
virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
// Generate initialization code for private members declared by
// GeneratePrivateMembers(). These go into the message class's SharedCtor()
// method, invoked by each of the generated constructors.
virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
// Generate any code that needs to go in the class's SharedDtor() method,
// invoked by the destructor.
// Most field types don't need this, so the default implementation is empty.
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
// message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
// Generate lines to decode this field from a packed value, which will be
// placed inside the message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
const;
// Generate lines to serialize this field, which are placed within the
// message's SerializeWithCachedSizes() method.
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
// Generate lines to serialize this field directly to the array "target",
// which are placed within the message's SerializeWithCachedSizesToArray()
// method. This must also advance "target" past the written bytes.
virtual void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const = 0;
// Generate lines to compute the serialized size of this field, which
// are placed in the message's ByteSize() method.
virtual void GenerateByteSize(io::Printer* printer) const = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
private:
const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Options& options);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
@@ -0,0 +1,494 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <limits>
#include <map>
#include <vector>
#include <google/protobuf/stubs/hash.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/strutil.h"
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
string DotsToUnderscores(const string& name) {
return StringReplace(name, ".", "_", true);
}
string DotsToColons(const string& name) {
return StringReplace(name, ".", "::", true);
}
const char* const kKeywordList[] = {
"and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
"catch", "char", "class", "compl", "const", "const_cast", "continue",
"default", "delete", "do", "double", "dynamic_cast", "else", "enum",
"explicit", "extern", "false", "float", "for", "friend", "goto", "if",
"inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
"operator", "or", "or_eq", "private", "protected", "public", "register",
"reinterpret_cast", "return", "short", "signed", "sizeof", "static",
"static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
"typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
"void", "volatile", "wchar_t", "while", "xor", "xor_eq"
};
hash_set<string> MakeKeywordsMap() {
hash_set<string> result;
for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) {
result.insert(kKeywordList[i]);
}
return result;
}
hash_set<string> kKeywords = MakeKeywordsMap();
// 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
string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
string result;
// Note: I distrust ctype.h due to locales.
for (int i = 0; i < input.size(); i++) {
if ('a' <= input[i] && input[i] <= 'z') {
if (cap_next_letter) {
result += input[i] + ('A' - 'a');
} else {
result += input[i];
}
cap_next_letter = false;
} else if ('A' <= input[i] && input[i] <= 'Z') {
// Capital letters are left as-is.
result += input[i];
cap_next_letter = false;
} else if ('0' <= input[i] && input[i] <= '9') {
result += input[i];
cap_next_letter = true;
} else {
cap_next_letter = true;
}
}
return result;
}
const char kThickSeparator[] =
"// ===================================================================\n";
const char kThinSeparator[] =
"// -------------------------------------------------------------------\n";
string ClassName(const Descriptor* descriptor, bool qualified) {
// Find "outer", the descriptor of the top-level message in which
// "descriptor" is embedded.
const Descriptor* outer = descriptor;
while (outer->containing_type() != NULL) outer = outer->containing_type();
const string& outer_name = outer->full_name();
string inner_name = descriptor->full_name().substr(outer_name.size());
if (qualified) {
return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
} else {
return outer->name() + DotsToUnderscores(inner_name);
}
}
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
if (enum_descriptor->containing_type() == NULL) {
if (qualified) {
return "::" + DotsToColons(enum_descriptor->full_name());
} else {
return enum_descriptor->name();
}
} else {
string result = ClassName(enum_descriptor->containing_type(), qualified);
result += '_';
result += enum_descriptor->name();
return result;
}
}
string SuperClassName(const Descriptor* descriptor) {
return HasDescriptorMethods(descriptor->file()) ?
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
}
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
if (kKeywords.count(result) > 0) {
result.append("_");
}
return result;
}
string FieldConstantName(const FieldDescriptor *field) {
string field_name = UnderscoresToCamelCase(field->name(), true);
string result = "k" + field_name + "FieldNumber";
if (!field->is_extension() &&
field->containing_type()->FindFieldByCamelcaseName(
field->camelcase_name()) != field) {
// This field's camelcase name is not unique. As a hack, add the field
// number to the constant name. This makes the constant rather useless,
// but what can we do?
result += "_" + SimpleItoa(field->number());
}
return result;
}
string FieldMessageTypeName(const FieldDescriptor* field) {
// Note: The Google-internal version of Protocol Buffers uses this function
// as a hook point for hacks to support legacy code.
return ClassName(field->message_type(), true);
}
string StripProto(const string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
} else {
return StripSuffixString(filename, ".proto");
}
}
const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
switch (type) {
case FieldDescriptor::CPPTYPE_INT32 : return "::google::protobuf::int32";
case FieldDescriptor::CPPTYPE_INT64 : return "::google::protobuf::int64";
case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
case FieldDescriptor::CPPTYPE_FLOAT : return "float";
case FieldDescriptor::CPPTYPE_BOOL : return "bool";
case FieldDescriptor::CPPTYPE_ENUM : return "int";
case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
// No default because we want the compiler to complain if any new
// CppTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32 : return "Int32";
case FieldDescriptor::TYPE_INT64 : return "Int64";
case FieldDescriptor::TYPE_UINT32 : return "UInt32";
case FieldDescriptor::TYPE_UINT64 : return "UInt64";
case FieldDescriptor::TYPE_SINT32 : return "SInt32";
case FieldDescriptor::TYPE_SINT64 : return "SInt64";
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
case FieldDescriptor::TYPE_FLOAT : return "Float";
case FieldDescriptor::TYPE_DOUBLE : return "Double";
case FieldDescriptor::TYPE_BOOL : return "Bool";
case FieldDescriptor::TYPE_ENUM : return "Enum";
case FieldDescriptor::TYPE_STRING : return "String";
case FieldDescriptor::TYPE_BYTES : return "Bytes";
case FieldDescriptor::TYPE_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 "";
}
string Int32ToString(int number) {
// gcc rejects the decimal form of kint32min.
if (number == kint32min) {
GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error);
return "(~0x7fffffff)";
} else {
return SimpleItoa(number);
}
}
string Int64ToString(int64 number) {
// gcc rejects the decimal form of kint64min
if (number == kint64min) {
// Make sure we are in a 2's complement system.
GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff),
kint64min_value_error);
return "GOOGLE_LONGLONG(~0x7fffffffffffffff)";
}
return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
}
string DefaultValue(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return Int32ToString(field->default_value_int32());
case FieldDescriptor::CPPTYPE_UINT32:
return SimpleItoa(field->default_value_uint32()) + "u";
case FieldDescriptor::CPPTYPE_INT64:
return Int64ToString(field->default_value_int64());
case FieldDescriptor::CPPTYPE_UINT64:
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
case FieldDescriptor::CPPTYPE_DOUBLE: {
double value = field->default_value_double();
if (value == numeric_limits<double>::infinity()) {
return "::google::protobuf::internal::Infinity()";
} else if (value == -numeric_limits<double>::infinity()) {
return "-::google::protobuf::internal::Infinity()";
} else if (value != value) {
return "::google::protobuf::internal::NaN()";
} else {
return SimpleDtoa(value);
}
}
case FieldDescriptor::CPPTYPE_FLOAT:
{
float value = field->default_value_float();
if (value == numeric_limits<float>::infinity()) {
return "static_cast<float>(::google::protobuf::internal::Infinity())";
} else if (value == -numeric_limits<float>::infinity()) {
return "static_cast<float>(-::google::protobuf::internal::Infinity())";
} else if (value != value) {
return "static_cast<float>(::google::protobuf::internal::NaN())";
} else {
string float_value = SimpleFtoa(value);
// If floating point value contains a period (.) or an exponent
// (either E or e), then append suffix 'f' to make it a float
// literal.
if (float_value.find_first_of(".eE") != string::npos) {
float_value.push_back('f');
}
return float_value;
}
}
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case FieldDescriptor::CPPTYPE_ENUM:
// Lazy: Generate a static_cast because we don't have a helper function
// that constructs the full name of an enum value.
return strings::Substitute(
"static_cast< $0 >($1)",
ClassName(field->enum_type(), true),
Int32ToString(field->default_value_enum()->number()));
case FieldDescriptor::CPPTYPE_STRING:
return "\"" + EscapeTrigraphs(
CEscape(field->default_value_string())) +
"\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
return FieldMessageTypeName(field) + "::default_instance()";
}
// Can't actually get here; make compiler happy. (We could add a default
// case above but then we wouldn't get the nice compiler warning when a
// new type is added.)
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
// Convert a file name into a valid identifier.
string FilenameIdentifier(const string& filename) {
string result;
for (int i = 0; i < filename.size(); i++) {
if (ascii_isalnum(filename[i])) {
result.push_back(filename[i]);
} else {
// Not alphanumeric. To avoid any possibility of name conflicts we
// use the hex code for the character.
result.push_back('_');
char buffer[kFastToBufferSize];
result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer));
}
}
return result;
}
// Return the name of the AddDescriptors() function for a given file.
string GlobalAddDescriptorsName(const string& filename) {
return "protobuf_AddDesc_" + FilenameIdentifier(filename);
}
// Return the name of the AssignDescriptors() function for a given file.
string GlobalAssignDescriptorsName(const string& filename) {
return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
}
// Return the name of the ShutdownFile() function for a given file.
string GlobalShutdownFileName(const string& filename) {
return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
}
// Return the qualified C++ name for a file level symbol.
string QualifiedFileLevelSymbol(const string& package, const string& name) {
if (package.empty()) {
return StrCat("::", name);
}
return StrCat("::", DotsToColons(package), "::", name);
}
// Escape C++ trigraphs by escaping question marks to \?
string EscapeTrigraphs(const string& to_escape) {
return StringReplace(to_escape, "?", "\\?", true);
}
// Escaped function name to eliminate naming conflict.
string SafeFunctionName(const Descriptor* descriptor,
const FieldDescriptor* field,
const string& prefix) {
// Do not use FieldName() since it will escape keywords.
string name = field->name();
LowerString(&name);
string function_name = prefix + name;
if (descriptor->FindFieldByName(function_name)) {
// Single underscore will also make it conflicting with the private data
// member. We use double underscore to escape function names.
function_name.append("__");
} else if (kKeywords.count(name) > 0) {
// If the field name is a keyword, we append the underscore back to keep it
// consistent with other function names.
function_name.append("_");
}
return function_name;
}
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;
}
bool IsStringOrMessage(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
case FieldDescriptor::CPPTYPE_INT64:
case FieldDescriptor::CPPTYPE_UINT32:
case FieldDescriptor::CPPTYPE_UINT64:
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_BOOL:
case FieldDescriptor::CPPTYPE_ENUM:
return false;
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
return true;
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,206 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
#include <map>
#include <string>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
namespace io {
class Printer;
}
namespace compiler {
namespace cpp {
// Commonly-used separator comments. Thick is a line of '=', thin is a line
// of '-'.
extern const char kThickSeparator[];
extern const char kThinSeparator[];
// Returns the non-nested type name for the given type. If "qualified" is
// true, prefix the type with the full namespace. For example, if you had:
// package foo.bar;
// message Baz { message Qux {} }
// Then the qualified ClassName for Qux would be:
// ::foo::bar::Baz_Qux
// While the non-qualified version would be:
// Baz_Qux
string ClassName(const Descriptor* descriptor, bool qualified);
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
string SuperClassName(const Descriptor* descriptor);
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
// anyway, so normally this just returns field->name().
string FieldName(const FieldDescriptor* field);
// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);
// Returns the scope where the field was defined (for extensions, this is
// different from the message type to which the field applies).
inline const Descriptor* FieldScope(const FieldDescriptor* field) {
return field->is_extension() ?
field->extension_scope() : field->containing_type();
}
// Returns the fully-qualified type name field->message_type(). Usually this
// is just ClassName(field->message_type(), true);
string FieldMessageTypeName(const FieldDescriptor* field);
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
// Note: non-built-in type names will be qualified, meaning they will start
// with a ::. If you are using the type as a template parameter, you will
// need to insure there is a space between the < and the ::, because the
// ridiculous C++ standard defines "<:" to be a synonym for "[".
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
// Get the declared type name in CamelCase format, as is used e.g. for the
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
// Return the code that evaluates to the number when compiled.
string Int32ToString(int number);
// Return the code that evaluates to the number when compiled.
string Int64ToString(int64 number);
// Get code that evaluates to the field's default value.
string DefaultValue(const FieldDescriptor* field);
// Convert a file name into a valid identifier.
string FilenameIdentifier(const string& filename);
// Return the name of the AddDescriptors() function for a given file.
string GlobalAddDescriptorsName(const string& filename);
// Return the name of the AssignDescriptors() function for a given file.
string GlobalAssignDescriptorsName(const string& filename);
// Return the qualified C++ name for a file level symbol.
string QualifiedFileLevelSymbol(const string& package, const string& name);
// Return the name of the ShutdownFile() function for a given file.
string GlobalShutdownFileName(const string& filename);
// Escape C++ trigraphs by escaping question marks to \?
string EscapeTrigraphs(const string& to_escape);
// Escaped function name to eliminate naming conflict.
string SafeFunctionName(const Descriptor* descriptor,
const FieldDescriptor* field,
const string& prefix);
// Do message classes in this file use UnknownFieldSet?
// Otherwise, messages will store unknown fields in a string
inline bool UseUnknownFieldSet(const FileDescriptor* file) {
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
// standard methods for which reflection-based fallback implementations exist?
inline bool HasGeneratedMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::CODE_SIZE;
}
// Do message classes in this file have descriptor and reflection methods?
inline bool HasDescriptorMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate generic services for this file?
inline bool HasGenericServices(const FileDescriptor* file) {
return file->service_count() > 0 &&
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
file->options().cc_generic_services();
}
// Should string fields in this file verify that their contents are UTF-8?
inline bool HasUtf8Verification(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate a separate, super-optimized code path for serializing to
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
// size.
inline bool HasFastArraySerialization(const FileDescriptor* file) {
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);
// Returns true if the field's CPPTYPE is string or message.
bool IsStringOrMessage(const FieldDescriptor* field);
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,175 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#include <memory>
#include <string>
#include <vector>
#include "google/protobuf/compiler/cpp/cpp_field.h"
#include "google/protobuf/compiler/cpp/cpp_options.h"
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumGenerator; // enum.h
class ExtensionGenerator; // extension.h
class MessageGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit MessageGenerator(const Descriptor* descriptor,
const Options& options);
~MessageGenerator();
// Header stuff.
// Generate foward declarations for this class and all its nested types.
void GenerateForwardDeclaration(io::Printer* printer);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
void GenerateEnumDefinitions(io::Printer* printer);
// Generate specializations of GetEnumDescriptor<MyEnum>().
// Precondition: in ::google::protobuf namespace.
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
// Generate definitions for this class and all its nested types.
void GenerateClassDefinition(io::Printer* printer);
// Generate definitions of inline methods (placed at the end of the header
// file).
void GenerateInlineMethods(io::Printer* printer);
// Source file stuff.
// Generate code which declares all the global descriptor pointers which
// will be initialized by the methods below.
void GenerateDescriptorDeclarations(io::Printer* printer);
// Generate code that initializes the global variable storing the message's
// descriptor.
void GenerateDescriptorInitializer(io::Printer* printer, int index);
// Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
// for all types.
void GenerateTypeRegistrations(io::Printer* printer);
// Generates code that allocates the message's default instance.
void GenerateDefaultInstanceAllocator(io::Printer* printer);
// Generates code that initializes the message's default instance. This
// is separate from allocating because all default instances must be
// allocated before any can be initialized.
void GenerateDefaultInstanceInitializer(io::Printer* printer);
// Generates code that should be run when ShutdownProtobufLibrary() is called,
// to delete all dynamically-allocated objects.
void GenerateShutdownCode(io::Printer* printer);
// Generate all non-inline methods for this class.
void GenerateClassMethods(io::Printer* printer);
private:
// Generate declarations and definitions of accessors for fields.
void GenerateFieldAccessorDeclarations(io::Printer* printer);
void GenerateFieldAccessorDefinitions(io::Printer* printer);
// Generate the field offsets array.
void GenerateOffsets(io::Printer* printer);
// Generate constructors and destructor.
void GenerateStructors(io::Printer* printer);
// The compiler typically generates multiple copies of each constructor and
// destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
// Placing common code in a separate method reduces the generated code size.
//
// Generate the shared constructor code.
void GenerateSharedConstructorCode(io::Printer* printer);
// Generate the shared destructor code.
void GenerateSharedDestructorCode(io::Printer* printer);
// Generate standard Message methods.
void GenerateClear(io::Printer* printer);
void GenerateOneofClear(io::Printer* printer);
void GenerateMergeFromCodedStream(io::Printer* printer);
void GenerateSerializeWithCachedSizes(io::Printer* printer);
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
bool to_array);
void GenerateByteSize(io::Printer* printer);
void GenerateMergeFrom(io::Printer* printer);
void GenerateCopyFrom(io::Printer* printer);
void GenerateSwap(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer);
// Helpers for GenerateSerializeWithCachedSizes().
void GenerateSerializeOneField(io::Printer* printer,
const FieldDescriptor* field,
bool unbounded);
void GenerateSerializeOneExtensionRange(
io::Printer* printer, const Descriptor::ExtensionRange* range,
bool unbounded);
const Descriptor* descriptor_;
string classname_;
Options options_;
FieldGeneratorMap field_generators_;
vector< vector<string> > runs_of_fields_; // that might be trivially cleared
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
bool uses_string_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
@@ -0,0 +1,375 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_message_field.h"
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include <google/protobuf/io/printer.h>
#include "google/protobuf/stubs/strutil.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
(*variables)["stream_writer"] = (*variables)["declared_type"] +
(HasFastArraySerialization(descriptor->message_type()->file()) ?
"MaybeToArray" :
"");
// NOTE: Escaped here to unblock proto1->proto2 migration.
// TODO(liujisi): Extend this to apply for other conflicting methods.
(*variables)["release_name"] =
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetMessageVariables(descriptor, &variables_, options);
}
MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "$type$* $name$_;\n");
}
void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $name$() const$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::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_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"
"inline $type$* $classname$::mutable_$name$() {\n"
" set_has_$name$();\n"
" if ($name$_ == NULL) $name$_ = new $type$;\n"
" // @@protoc_insertion_point(field_mutable:$full_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"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($name$_ != NULL) $name$_->$type$::Clear();\n");
}
void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
}
void MessageFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
}
void MessageFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = NULL;\n");
}
void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
" input, mutable_$name$()));\n");
} else {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
" $number$, input, mutable_$name$()));\n");
}
}
void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(), output);\n");
}
void MessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
" $number$, this->$name$(), target);\n");
}
void MessageFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
" this->$name$());\n");
}
// ===================================================================
MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: MessageFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$() const {\n"
" return has_$name$() ? *$oneof_prefix$$name$_\n"
" : $type$::default_instance();\n"
"}\n"
"inline $type$* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = new $type$;\n"
" }\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
"inline $type$* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
" $oneof_prefix$$name$_ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
"}\n");
}
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
// if it is the active field, it cannot be NULL.
printer->Print(variables_,
"delete $oneof_prefix$$name$_;\n");
}
void MessageOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void MessageOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
// Don't print any constructor code. The field is in a union. We allocate
// space only when this field is used.
}
// ===================================================================
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetMessageVariables(descriptor, &variables_, options);
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
}
void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $name$(int index) const$deprecation$;\n"
"inline $type$* mutable_$name$(int index)$deprecation$;\n"
"inline $type$* add_$name$()$deprecation$;\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
" $name$() const$deprecation$;\n"
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
"inline $type$* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
"inline $type$* $classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
" return $name$_.Add();\n"
"}\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Clear();\n");
}
void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void RepeatedMessageFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
" input, add_$name$()));\n");
} else {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
" $number$, input, add_$name$()));\n");
}
}
void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(i), output);\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
" $number$, this->$name$(i), target);\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"total_size += $tag_size$ * this->$name$_size();\n"
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" total_size +=\n"
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
" this->$name$(i));\n"
"}\n");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,121 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
#include <map>
#include <string>
#include "google/protobuf/compiler/cpp/cpp_field.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MessageFieldGenerator : public FieldGenerator {
public:
explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~MessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
};
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
@@ -0,0 +1,58 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: rennie@google.com (Jeffrey Rennie)
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
#include <string>
#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// Generator options:
struct Options {
Options() : safe_boundary_check(false) {
}
string dllexport_decl;
bool safe_boundary_check;
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
@@ -0,0 +1,453 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_primitive_field.h"
#include "google/protobuf/compiler/cpp/cpp_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 cpp {
using internal::WireFormatLite;
namespace {
// 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,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
(*variables)["wire_format_field_type"] =
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
void PrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "$type$ $name$_;\n");
}
void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $name$() const$deprecation$;\n"
"inline void set_$name$($type$ value)$deprecation$;\n");
}
void PrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" set_has_$name$();\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void PrimitiveFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "set_$name$(from.$name$());\n");
}
void PrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
}
void PrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" $type$, $wire_format_field_type$>(\n"
" input, &$name$_)));\n"
"set_has_$name$();\n");
}
void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$("
"$number$, this->$name$(), output);\n");
}
void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
"$number$, this->$name$(), target);\n");
}
void PrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
printer->Print(variables_,
"total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$());\n");
} else {
printer->Print(variables_,
"total_size += $tag_size$ + $fixed_size$;\n");
}
}
// ===================================================================
PrimitiveOneofFieldGenerator::
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: PrimitiveFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
" return $default$;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
"}\n");
}
void PrimitiveOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
}
void PrimitiveOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void PrimitiveOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(
variables_,
" $classname$_default_oneof_instance_->$name$_ = $default$;\n");
}
void PrimitiveOneofFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"clear_$oneof_name$();\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" $type$, $wire_format_field_type$>(\n"
" input, &$oneof_prefix$$name$_)));\n"
"set_has_$name$();\n");
}
// ===================================================================
RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
if (descriptor->options().packed()) {
variables_["packed_reader"] = "ReadPackedPrimitive";
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
} else {
variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
variables_["repeated_reader"] = "ReadRepeatedPrimitive";
}
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
}
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $name$(int index) const$deprecation$;\n"
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
"inline void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
" $name$() const$deprecation$;\n"
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get(index);\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Clear();\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_, "_$name$_cached_byte_size_ = 0;\n");
}
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
" $type$, $wire_format_field_type$>(\n"
" $tag_size$, $tag$, input, this->mutable_$name$())));\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
" $type$, $wire_format_field_type$>(\n"
" input, this->mutable_$name$())));\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
if (descriptor_->options().packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
" ::google::protobuf::internal::WireFormatLite::WriteTag("
"$number$, "
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
"output);\n"
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
" this->$name$(i), output);\n");
} else {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
" $number$, this->$name$(i), output);\n");
}
printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
if (descriptor_->options().packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
" $number$,\n"
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
" target);\n"
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
" _$name$_cached_byte_size_, target);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
} else {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
}
printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
" int data_size = 0;\n");
printer->Indent();
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
" $declared_type$Size(this->$name$(i));\n"
"}\n");
} else {
printer->Print(variables_,
"data_size = $fixed_size$ * this->$name$_size();\n");
}
if (descriptor_->options().packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
}
printer->Outdent();
printer->Print("}\n");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,123 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
#include <map>
#include <string>
#include "google/protobuf/compiler/cpp/cpp_field.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
};
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~PrimitiveOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
};
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
@@ -0,0 +1,642 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include "google/protobuf/compiler/cpp/cpp_string_field.h"
#include "google/protobuf/compiler/cpp/cpp_helpers.h"
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include "google/protobuf/stubs/strutil.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void SetStringVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_length"] =
SimpleItoa(descriptor->default_value_string().length());
(*variables)["default_variable"] = descriptor->default_value_string().empty()
? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
: "_default_" + FieldName(descriptor) + "_";
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
// NOTE: Escaped here to unblock proto1->proto2 migration.
// TODO(liujisi): Extend this to apply for other conflicting methods.
(*variables)["release_name"] =
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
StringFieldGenerator::
StringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
StringFieldGenerator::~StringFieldGenerator() {}
void StringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "::std::string* $name$_;\n");
}
void StringFieldGenerator::
GenerateStaticMembers(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
printer->Print(variables_, "static ::std::string* $default_variable$;\n");
}
}
void StringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// If we're using StringFieldGenerator for a field with a ctype, it's
// because that ctype isn't actually implemented. In particular, this is
// true of ctype=CORD and ctype=STRING_PIECE in the open source release.
// We aren't releasing Cord because it has too many Google-specific
// dependencies and we aren't releasing StringPiece because it's hardly
// useful outside of Google and because it would get confusing to have
// multiple instances of the StringPiece class in different libraries (PCRE
// already includes it for their C++ bindings, which came from Google).
//
// In any case, we make all the accessors private while still actually
// using a string to represent the field internally. This way, we can
// guarantee that if we do ever implement the ctype, it won't break any
// existing users who might be -- for whatever reason -- already using .proto
// files that applied the ctype. The field can still be accessed via the
// reflection interface since the reflection interface is independent of
// the string's underlying representation.
if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
" // Hidden due to unknown ctype option.\n");
printer->Indent();
}
printer->Print(variables_,
"inline const ::std::string& $name$() const$deprecation$;\n"
"inline void set_$name$(const ::std::string& value)$deprecation$;\n"
"inline void set_$name$(const char* value)$deprecation$;\n"
"inline void set_$name$(const $pointer_type$* value, size_t size)"
"$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) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
}
}
void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return *$name$_;\n"
"}\n"
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
" set_has_$name$();\n"
" if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(const char* value) {\n"
" set_has_$name$();\n"
" if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
"inline "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" set_has_$name$();\n"
" if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" set_has_$name$();\n"
" if ($name$_ == $default_variable$) {\n");
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" $name$_ = new ::std::string;\n");
} else {
printer->Print(variables_,
" $name$_ = new ::std::string(*$default_variable$);\n");
}
printer->Print(variables_,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_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"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
// Initialized in GenerateDefaultInstanceAllocator.
printer->Print(variables_,
"::std::string* $classname$::$default_variable$ = NULL;\n");
}
}
void StringFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
"if ($name$_ != $default_variable$) {\n"
" $name$_->clear();\n"
"}\n");
} else {
printer->Print(variables_,
"if ($name$_ != $default_variable$) {\n"
" $name$_->assign(*$default_variable$);\n"
"}\n");
}
}
void StringFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "set_$name$(from.$name$());\n");
}
void StringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
}
void StringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = const_cast< ::std::string*>($default_variable$);\n");
}
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($name$_ != $default_variable$) {\n"
" delete $name$_;\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::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
" \"$name$\");\n");
}
}
void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
" \"$name$\");\n");
}
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
" $number$, this->$name$(), output);\n");
}
void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
" \"$name$\");\n");
}
printer->Print(variables_,
"target =\n"
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
" $number$, this->$name$(), target);\n");
}
void StringFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$());\n");
}
// ===================================================================
StringOneofFieldGenerator::
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: StringFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$() const {\n"
" if (has_$name$()) {\n"
" return *$oneof_prefix$$name$_;\n"
" }\n");
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" return ::google::protobuf::internal::GetEmptyStringAlreadyInited();\n");
} else {
printer->Print(variables_,
" return *$default_variable$;\n");
}
printer->Print(variables_,
"}\n"
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = new ::std::string;\n"
" }\n"
" $oneof_prefix$$name$_->assign(value);\n"
"}\n"
"inline void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = new ::std::string;\n"
" }\n"
" $oneof_prefix$$name$_->assign(value);\n"
"}\n"
"inline "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = new ::std::string;\n"
" }\n"
" $oneof_prefix$$name$_->assign(\n"
" reinterpret_cast<const char*>(value), size);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n");
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" $oneof_prefix$$name$_ = new ::std::string;\n");
} else {
printer->Print(variables_,
" $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\n");
}
printer->Print(variables_,
" }\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
"inline ::std::string* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" ::std::string* temp = $oneof_prefix$$name$_;\n"
" $oneof_prefix$$name$_ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
"inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n"
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
"}\n");
}
void StringOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_,
"delete $oneof_prefix$$name$_;\n");
}
void StringOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" $classname$_default_oneof_instance_->$name$_ = "
"$classname$::$default_variable$;\n");
} else {
printer->Print(variables_,
" $classname$_default_oneof_instance_->$name$_ = "
"$default_variable$;\n");
}
}
void StringOneofFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has_$name$()) {\n"
" delete $oneof_prefix$$name$_;\n"
"}\n");
}
// ===================================================================
RepeatedStringFieldGenerator::
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
void RepeatedStringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
}
void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// See comment above about unknown ctypes.
if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
" // Hidden due to unknown ctype option.\n");
printer->Indent();
}
printer->Print(variables_,
"inline const ::std::string& $name$(int index) const$deprecation$;\n"
"inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
"inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
"inline void set_$name$(int index, const char* value)$deprecation$;\n"
"inline "
"void set_$name$(int index, const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
"inline ::std::string* add_$name$()$deprecation$;\n"
"inline void add_$name$(const ::std::string& value)$deprecation$;\n"
"inline void add_$name$(const char* value)$deprecation$;\n"
"inline void add_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
"$deprecation$;\n"
"inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
"$deprecation$;\n");
if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
}
}
void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
"inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" $name$_.Mutable(index)->assign(value);\n"
"}\n"
"inline void $classname$::set_$name$(int index, const char* value) {\n"
" $name$_.Mutable(index)->assign(value);\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
"inline void "
"$classname$::set_$name$"
"(int index, const $pointer_type$* value, size_t size) {\n"
" $name$_.Mutable(index)->assign(\n"
" reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline ::std::string* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
"inline void $classname$::add_$name$(const ::std::string& value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
"inline void $classname$::add_$name$(const char* value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
"}\n"
"inline void "
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
"}\n");
printer->Print(variables_,
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
void RepeatedStringFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Clear();\n");
}
void RepeatedStringFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void RepeatedStringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedStringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->add_$name$()));\n");
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(this->$name$_size() - 1).data(),\n"
" this->$name$(this->$name$_size() - 1).length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
" \"$name$\");\n");
}
}
void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
" \"$name$\");\n");
}
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
" $number$, this->$name$(i), output);\n"
"}\n");
}
void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
" \"$name$\");\n");
}
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
"}\n");
}
void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"total_size += $tag_size$ * this->$name$_size();\n"
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$(i));\n"
"}\n");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
@@ -0,0 +1,127 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
#include <map>
#include <string>
#include "google/protobuf/compiler/cpp/cpp_field.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class StringFieldGenerator : public FieldGenerator {
public:
explicit StringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~StringFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateStaticMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(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 GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
};
class StringOneofFieldGenerator : public StringFieldGenerator {
public:
explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~StringOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
};
class RepeatedStringFieldGenerator : public FieldGenerator {
public:
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedStringFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
@@ -0,0 +1,232 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
//
// Deals with the fact that hash_map is not defined everywhere.
#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
#define GOOGLE_PROTOBUF_STUBS_HASH_H__
#include <string.h>
#include <google/protobuf/stubs/common.h>
#include "config.h"
#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
#include HASH_MAP_H
#include HASH_SET_H
#else
#define MISSING_HASH
#include <map>
#include <set>
#endif
namespace google {
namespace protobuf {
#ifdef MISSING_HASH
// This system doesn't have hash_map or hash_set. Emulate them using map and
// set.
// Make hash<T> be the same as less<T>. Note that everywhere where custom
// hash functions are defined in the protobuf code, they are also defined such
// that they can be used as "less" functions, which is required by MSVC anyway.
template <typename Key>
struct hash {
// Dummy, just to make derivative hash functions compile.
int operator()(const Key& key) {
GOOGLE_LOG(FATAL) << "Should never be called.";
return 0;
}
inline bool operator()(const Key& a, const Key& b) const {
return a < b;
}
};
// Make sure char* is compared by value.
template <>
struct hash<const char*> {
// Dummy, just to make derivative hash functions compile.
int operator()(const char* key) {
GOOGLE_LOG(FATAL) << "Should never be called.";
return 0;
}
inline bool operator()(const char* a, const char* b) const {
return strcmp(a, b) < 0;
}
};
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_map : public std::map<Key, Data, HashFcn> {
public:
hash_map(int = 0) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_set : public std::set<Key, HashFcn> {
public:
hash_set(int = 0) {}
};
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
template <typename Key>
struct hash : public HASH_NAMESPACE::hash_compare<Key> {
};
// MSVC's hash_compare<const char*> hashes based on the string contents but
// compares based on the string pointer. WTF?
class CstringLess {
public:
inline bool operator()(const char* a, const char* b) const {
return strcmp(a, b) < 0;
}
};
template <>
struct hash<const char*>
: public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
};
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_map : public HASH_NAMESPACE::hash_map<
Key, Data, HashFcn> {
public:
hash_map(int = 0) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_set : public HASH_NAMESPACE::hash_set<
Key, HashFcn> {
public:
hash_set(int = 0) {}
};
#else
template <typename Key>
struct hash : public HASH_NAMESPACE::hash<Key> {
};
template <typename Key>
struct hash<const Key*> {
inline size_t operator()(const Key* key) const {
return reinterpret_cast<size_t>(key);
}
};
// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
// we go ahead and provide our own implementation.
template <>
struct hash<const char*> {
inline size_t operator()(const char* str) const {
size_t result = 0;
for (; *str != '\0'; str++) {
result = 5 * result + *str;
}
return result;
}
};
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key> >
class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
Key, Data, HashFcn, EqualKey> {
public:
hash_map(int = 0) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key> >
class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
};
#endif
template <>
struct hash<string> {
inline size_t operator()(const string& key) const {
return hash<const char*>()(key.c_str());
}
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
inline size_t operator()(const string& a, const string& b) const {
return a < b;
}
};
template <typename First, typename Second>
struct hash<pair<First, Second> > {
inline size_t operator()(const pair<First, Second>& key) const {
size_t first_hash = hash<First>()(key.first);
size_t second_hash = hash<Second>()(key.second);
// FIXME(kenton): What is the best way to compute this hash? I have
// no idea! This seems a bit better than an XOR.
return first_hash * ((1 << 16) - 1) + second_hash;
}
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
inline size_t operator()(const pair<First, Second>& a,
const pair<First, Second>& b) const {
return a < b;
}
};
// Used by GCC/SGI STL only. (Why isn't this provided by the standard
// library? :( )
struct streq {
inline bool operator()(const char* a, const char* b) const {
return strcmp(a, b) == 0;
}
};
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,562 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// from google3/strings/strutil.h
#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
#include <stdlib.h>
#include <vector>
#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
#ifdef _MSC_VER
#define strtoll _strtoi64
#define strtoull _strtoui64
#elif defined(__DECCXX) && defined(__osf__)
// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
#define strtoll strtol
#define strtoull strtoul
#endif
// ----------------------------------------------------------------------
// ascii_isalnum()
// Check if an ASCII character is alphanumeric. We can't use ctype's
// isalnum() because it is affected by locale. This function is applied
// to identifiers in the protocol buffer language, not to natural-language
// strings, so locale should not be taken into account.
// ascii_isdigit()
// Like above, but only accepts digits.
// ----------------------------------------------------------------------
inline bool ascii_isalnum(char c) {
return ('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9');
}
inline bool ascii_isdigit(char c) {
return ('0' <= c && c <= '9');
}
// ----------------------------------------------------------------------
// HasPrefixString()
// Check if a string begins with a given prefix.
// StripPrefixString()
// Given a string and a putative prefix, returns the string minus the
// prefix string if the prefix matches, otherwise the original
// string.
// ----------------------------------------------------------------------
inline bool HasPrefixString(const string& str,
const string& prefix) {
return str.size() >= prefix.size() &&
str.compare(0, prefix.size(), prefix) == 0;
}
inline string StripPrefixString(const string& str, const string& prefix) {
if (HasPrefixString(str, prefix)) {
return str.substr(prefix.size());
} else {
return str;
}
}
// ----------------------------------------------------------------------
// HasSuffixString()
// Return true if str ends in suffix.
// StripSuffixString()
// Given a string and a putative suffix, returns the string minus the
// suffix string if the suffix matches, otherwise the original
// string.
// ----------------------------------------------------------------------
inline bool HasSuffixString(const string& str,
const string& suffix) {
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
inline string StripSuffixString(const string& str, const string& suffix) {
if (HasSuffixString(str, suffix)) {
return str.substr(0, str.size() - suffix.size());
} else {
return str;
}
}
// ----------------------------------------------------------------------
// StripString
// Replaces any occurrence of the character 'remove' (or the characters
// in 'remove') with the character 'replacewith'.
// Good for keeping html characters or protocol characters (\t) out
// of places where they might cause a problem.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
char replacewith);
// ----------------------------------------------------------------------
// LowerString()
// UpperString()
// ToUpper()
// Convert the characters in "s" to lowercase or uppercase. ASCII-only:
// these functions intentionally ignore locale because they are applied to
// identifiers used in the Protocol Buffer language, not to natural-language
// strings.
// ----------------------------------------------------------------------
inline void LowerString(string * s) {
string::iterator end = s->end();
for (string::iterator i = s->begin(); i != end; ++i) {
// tolower() changes based on locale. We don't want this!
if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
}
}
inline void UpperString(string * s) {
string::iterator end = s->end();
for (string::iterator i = s->begin(); i != end; ++i) {
// toupper() changes based on locale. We don't want this!
if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
}
}
inline string ToUpper(const string& s) {
string out = s;
UpperString(&out);
return out;
}
// ----------------------------------------------------------------------
// StringReplace()
// Give me a string and two patterns "old" and "new", and I replace
// the first instance of "old" in the string with "new", if it
// exists. RETURN a new string, regardless of whether the replacement
// happened or not.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
const string& newsub, bool replace_all);
// ----------------------------------------------------------------------
// SplitStringUsing()
// Split a string using a character delimiter. Append the components
// to 'result'. If there are consecutive delimiters, this function skips
// over all of them.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
vector<string>* res);
// Split a string using one or more byte delimiters, presented
// as a nul-terminated c string. Append the components to 'result'.
// If there are consecutive delimiters, this function will return
// corresponding empty strings. If you want to drop the empty
// strings, try SplitStringUsing().
//
// If "full" is the empty string, yields an empty string as the only value.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
const char* delim,
vector<string>* result);
// ----------------------------------------------------------------------
// Split()
// Split a string using a character delimiter.
// ----------------------------------------------------------------------
inline vector<string> Split(
const string& full, const char* delim, bool skip_empty = true) {
vector<string> result;
if (skip_empty) {
SplitStringUsing(full, delim, &result);
} else {
SplitStringAllowEmpty(full, delim, &result);
}
return result;
}
// ----------------------------------------------------------------------
// JoinStrings()
// These methods concatenate a vector of strings into a C++ string, using
// the C-string "delim" as a separator between components. There are two
// flavors of the function, one flavor returns the concatenated string,
// another takes a pointer to the target string. In the latter case the
// target string is cleared and overwritten.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void JoinStrings(const vector<string>& components,
const char* delim, string* result);
inline string JoinStrings(const vector<string>& components,
const char* delim) {
string result;
JoinStrings(components, delim, &result);
return result;
}
// ----------------------------------------------------------------------
// UnescapeCEscapeSequences()
// Copies "source" to "dest", rewriting C-style escape sequences
// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
// equivalents. "dest" must be sufficiently large to hold all
// the characters in the rewritten string (i.e. at least as large
// as strlen(source) + 1 should be safe, since the replacements
// are always shorter than the original escaped sequences). It's
// safe for source and dest to be the same. RETURNS the length
// of dest.
//
// It allows hex sequences \xhh, or generally \xhhhhh with an
// arbitrary number of hex digits, but all of them together must
// specify a value of a single byte (e.g. \x0045 is equivalent
// to \x45, and \x1234 is erroneous).
//
// It also allows escape sequences of the form \uhhhh (exactly four
// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
// hex digits, upper or lower case) to specify a Unicode code
// point. The dest array will contain the UTF8-encoded version of
// that code-point (e.g., if source contains \u2019, then dest will
// contain the three bytes 0xE2, 0x80, and 0x99).
//
// Errors: In the first form of the call, errors are reported with
// LOG(ERROR). The same is true for the second form of the call if
// the pointer to the string vector is NULL; otherwise, error
// messages are stored in the vector. In either case, the effect on
// the dest array is not defined, but rest of the source will be
// processed.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
vector<string> *errors);
// ----------------------------------------------------------------------
// UnescapeCEscapeString()
// This does the same thing as UnescapeCEscapeSequences, but creates
// a new string. The caller does not need to worry about allocating
// a dest buffer. This should be used for non performance critical
// tasks such as printing debug messages. It is safe for src and dest
// to be the same.
//
// The second call stores its errors in a supplied string vector.
// If the string vector pointer is NULL, it reports the errors with LOG().
//
// In the first and second calls, the length of dest is returned. In the
// the third call, the new string is returned.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
vector<string> *errors);
LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);
// ----------------------------------------------------------------------
// CEscapeString()
// Copies 'src' to 'dest', escaping dangerous characters using
// C-style escape sequences. This is very useful for preparing query
// flags. 'src' and 'dest' should not overlap.
// Returns the number of bytes written to 'dest' (not including the \0)
// or -1 if there was insufficient space.
//
// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len,
char* dest, int dest_len);
// ----------------------------------------------------------------------
// CEscape()
// More convenient form of CEscapeString: returns result as a "string".
// This version is slower than CEscapeString() because it does more
// allocation. However, it is much more convenient to use in
// non-speed-critical code like logging messages etc.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string CEscape(const string& src);
namespace strings {
// Like CEscape() but does not escape bytes with the upper bit set.
LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
// Like CEscape() but uses hex (\x) escapes instead of octals.
LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
} // namespace strings
// ----------------------------------------------------------------------
// strto32()
// strtou32()
// strto64()
// strtou64()
// Architecture-neutral plug compatible replacements for strtol() and
// strtoul(). Long's have different lengths on ILP-32 and LP-64
// platforms, so using these is safer, from the point of view of
// overflow behavior, than using the standard libc functions.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr,
int base);
LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr,
int base);
inline int32 strto32(const char *nptr, char **endptr, int base) {
if (sizeof(int32) == sizeof(long))
return strtol(nptr, endptr, base);
else
return strto32_adaptor(nptr, endptr, base);
}
inline uint32 strtou32(const char *nptr, char **endptr, int base) {
if (sizeof(uint32) == sizeof(unsigned long))
return strtoul(nptr, endptr, base);
else
return strtou32_adaptor(nptr, endptr, base);
}
// For now, long long is 64-bit on all the platforms we care about, so these
// functions can simply pass the call to strto[u]ll.
inline int64 strto64(const char *nptr, char **endptr, int base) {
GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
sizeof_int64_is_not_sizeof_long_long);
return strtoll(nptr, endptr, base);
}
inline uint64 strtou64(const char *nptr, char **endptr, int base) {
GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
sizeof_uint64_is_not_sizeof_long_long);
return strtoull(nptr, endptr, base);
}
// ----------------------------------------------------------------------
// safe_strto32()
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p);
inline bool safe_strto32(string text, int32* value) {
return safe_int(text, value);
}
// ----------------------------------------------------------------------
// FastIntToBuffer()
// FastHexToBuffer()
// FastHex64ToBuffer()
// FastHex32ToBuffer()
// FastTimeToBuffer()
// These are intended for speed. FastIntToBuffer() assumes the
// integer is non-negative. FastHexToBuffer() puts output in
// hex rather than decimal. FastTimeToBuffer() puts the output
// into RFC822 format.
//
// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
// padded to exactly 16 bytes (plus one byte for '\0')
//
// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
// padded to exactly 8 bytes (plus one byte for '\0')
//
// All functions take the output buffer as an arg.
// They all return a pointer to the beginning of the output,
// which may not be the beginning of the input buffer.
// ----------------------------------------------------------------------
// Suggested buffer size for FastToBuffer functions. Also works with
// DoubleToBuffer() and FloatToBuffer().
static const int kFastToBufferSize = 32;
LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer);
char* FastUInt32ToBuffer(uint32 i, char* buffer); // inline below
char* FastUInt64ToBuffer(uint64 i, char* buffer); // inline below
LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer);
// at least 22 bytes long
inline char* FastIntToBuffer(int i, char* buffer) {
return (sizeof(i) == 4 ?
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
}
inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
return (sizeof(i) == 4 ?
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
}
inline char* FastLongToBuffer(long i, char* buffer) {
return (sizeof(i) == 4 ?
FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
}
inline char* FastULongToBuffer(unsigned long i, char* buffer) {
return (sizeof(i) == 4 ?
FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
}
// ----------------------------------------------------------------------
// FastInt32ToBufferLeft()
// FastUInt32ToBufferLeft()
// FastInt64ToBufferLeft()
// FastUInt64ToBufferLeft()
//
// Like the Fast*ToBuffer() functions above, these are intended for speed.
// Unlike the Fast*ToBuffer() functions, however, these functions write
// their output to the beginning of the buffer (hence the name, as the
// output is left-aligned). The caller is responsible for ensuring that
// the buffer has enough space to hold the output.
//
// Returns a pointer to the end of the string (i.e. the null character
// terminating the string).
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer);
LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer);
// Just define these in terms of the above.
inline char* FastUInt32ToBuffer(uint32 i, char* buffer) {
FastUInt32ToBufferLeft(i, buffer);
return buffer;
}
inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
FastUInt64ToBufferLeft(i, buffer);
return buffer;
}
// ----------------------------------------------------------------------
// SimpleItoa()
// Description: converts an integer to a string.
//
// Return value: string
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string SimpleItoa(int i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i);
LIBPROTOBUF_EXPORT string SimpleItoa(long i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i);
LIBPROTOBUF_EXPORT string SimpleItoa(long long i);
LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i);
// ----------------------------------------------------------------------
// SimpleDtoa()
// SimpleFtoa()
// DoubleToBuffer()
// FloatToBuffer()
// Description: converts a double or float to a string which, if
// passed to NoLocaleStrtod(), will produce the exact same original double
// (except in case of NaN; all NaNs are considered the same value).
// We try to keep the string short but it's not guaranteed to be as
// short as possible.
//
// DoubleToBuffer() and FloatToBuffer() write the text to the given
// buffer and return it. The buffer must be at least
// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
// bytes for floats. kFastToBufferSize is also guaranteed to be large
// enough to hold either.
//
// Return value: string
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string SimpleDtoa(double value);
LIBPROTOBUF_EXPORT string SimpleFtoa(float value);
LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
// In practice, doubles should never need more than 24 bytes and floats
// should never need more than 14 (including null terminators), but we
// overestimate to be safe.
static const int kDoubleToBufferSize = 32;
static const int kFloatToBufferSize = 24;
// ----------------------------------------------------------------------
// ToString() are internal help methods used in StrCat() and Join()
// ----------------------------------------------------------------------
namespace internal {
inline string ToString(int i) {
return SimpleItoa(i);
}
inline string ToString(string a) {
return a;
}
} // namespace internal
// ----------------------------------------------------------------------
// StrCat()
// These methods join some strings together.
// ----------------------------------------------------------------------
template <typename T1, typename T2, typename T3, typename T4, typename T5>
string StrCat(
const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) {
return internal::ToString(a) + internal::ToString(b) +
internal::ToString(c) + internal::ToString(d) + internal::ToString(e);
}
template <typename T1, typename T2, typename T3, typename T4>
string StrCat(
const T1& a, const T2& b, const T3& c, const T4& d) {
return internal::ToString(a) + internal::ToString(b) +
internal::ToString(c) + internal::ToString(d);
}
template <typename T1, typename T2, typename T3>
string StrCat(const T1& a, const T2& b, const T3& c) {
return internal::ToString(a) + internal::ToString(b) +
internal::ToString(c);
}
template <typename T1, typename T2>
string StrCat(const T1& a, const T2& b) {
return internal::ToString(a) + internal::ToString(b);
}
// ----------------------------------------------------------------------
// Join()
// These methods concatenate a range of components into a C++ string, using
// the C-string "delim" as a separator between components.
// ----------------------------------------------------------------------
template <typename Iterator>
void Join(Iterator start, Iterator end,
const char* delim, string* result) {
for (Iterator it = start; it != end; ++it) {
if (it != start) {
result->append(delim);
}
result->append(internal::ToString(*it));
}
}
template <typename Range>
string Join(const Range& components,
const char* delim) {
string result;
Join(components.begin(), components.end(), delim, &result);
return result;
}
// ----------------------------------------------------------------------
// ToHex()
// Return a lower-case hex string representation of the given integer.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string ToHex(uint64 num);
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
@@ -0,0 +1,134 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
namespace strings {
using internal::SubstituteArg;
// Returns the number of args in arg_array which were passed explicitly
// to Substitute().
static int CountSubstituteArgs(const SubstituteArg* const* args_array) {
int count = 0;
while (args_array[count] != NULL && args_array[count]->size() != -1) {
++count;
}
return count;
}
string Substitute(
const char* format,
const SubstituteArg& arg0, const SubstituteArg& arg1,
const SubstituteArg& arg2, const SubstituteArg& arg3,
const SubstituteArg& arg4, const SubstituteArg& arg5,
const SubstituteArg& arg6, const SubstituteArg& arg7,
const SubstituteArg& arg8, const SubstituteArg& arg9) {
string result;
SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4,
arg5, arg6, arg7, arg8, arg9);
return result;
}
void SubstituteAndAppend(
string* output, const char* format,
const SubstituteArg& arg0, const SubstituteArg& arg1,
const SubstituteArg& arg2, const SubstituteArg& arg3,
const SubstituteArg& arg4, const SubstituteArg& arg5,
const SubstituteArg& arg6, const SubstituteArg& arg7,
const SubstituteArg& arg8, const SubstituteArg& arg9) {
const SubstituteArg* const args_array[] = {
&arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL
};
// Determine total size needed.
int size = 0;
for (int i = 0; format[i] != '\0'; i++) {
if (format[i] == '$') {
if (ascii_isdigit(format[i+1])) {
int index = format[i+1] - '0';
if (args_array[index]->size() == -1) {
GOOGLE_LOG(DFATAL)
<< "strings::Substitute format string invalid: asked for \"$"
<< index << "\", but only " << CountSubstituteArgs(args_array)
<< " args were given. Full format string was: \""
<< CEscape(format) << "\".";
return;
}
size += args_array[index]->size();
++i; // Skip next char.
} else if (format[i+1] == '$') {
++size;
++i; // Skip next char.
} else {
GOOGLE_LOG(DFATAL)
<< "Invalid strings::Substitute() format string: \""
<< CEscape(format) << "\".";
return;
}
} else {
++size;
}
}
if (size == 0) return;
// Build the string.
int original_size = output->size();
STLStringResizeUninitialized(output, original_size + size);
char* target = string_as_array(output) + original_size;
for (int i = 0; format[i] != '\0'; i++) {
if (format[i] == '$') {
if (ascii_isdigit(format[i+1])) {
const SubstituteArg* src = args_array[format[i+1] - '0'];
memcpy(target, src->data(), src->size());
target += src->size();
++i; // Skip next char.
} else if (format[i+1] == '$') {
*target++ = '$';
++i; // Skip next char.
}
} else {
*target++ = format[i];
}
}
GOOGLE_DCHECK_EQ(target - output->data(), output->size());
}
} // namespace strings
} // namespace protobuf
} // namespace google
@@ -0,0 +1,170 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// from google3/strings/substitute.h
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
namespace google {
namespace protobuf {
namespace strings {
// ----------------------------------------------------------------------
// strings::Substitute()
// strings::SubstituteAndAppend()
// Kind of like StringPrintf, but different.
//
// Example:
// string GetMessage(string first_name, string last_name, int age) {
// return strings::Substitute("My name is $0 $1 and I am $2 years old.",
// first_name, last_name, age);
// }
//
// Differences from StringPrintf:
// * The format string does not identify the types of arguments.
// Instead, the magic of C++ deals with this for us. See below
// for a list of accepted types.
// * Substitutions in the format string are identified by a '$'
// followed by a digit. So, you can use arguments out-of-order and
// use the same argument multiple times.
// * It's much faster than StringPrintf.
//
// Supported types:
// * Strings (const char*, const string&)
// * Note that this means you do not have to add .c_str() to all of
// your strings. In fact, you shouldn't; it will be slower.
// * int32, int64, uint32, uint64: Formatted using SimpleItoa().
// * float, double: Formatted using SimpleFtoa() and SimpleDtoa().
// * bool: Printed as "true" or "false".
//
// SubstituteAndAppend() is like Substitute() but appends the result to
// *output. Example:
//
// string str;
// strings::SubstituteAndAppend(&str,
// "My name is $0 $1 and I am $2 years old.",
// first_name, last_name, age);
//
// Substitute() is significantly faster than StringPrintf(). For very
// large strings, it may be orders of magnitude faster.
// ----------------------------------------------------------------------
namespace internal { // Implementation details.
class SubstituteArg {
public:
inline SubstituteArg(const char* value)
: text_(value), size_(strlen(text_)) {}
inline SubstituteArg(const string& value)
: text_(value.data()), size_(value.size()) {}
// Indicates that no argument was given.
inline explicit SubstituteArg()
: text_(NULL), size_(-1) {}
// Primitives
// We don't overload for signed and unsigned char because if people are
// explicitly declaring their chars as signed or unsigned then they are
// probably actually using them as 8-bit integers and would probably
// prefer an integer representation. But, we don't really know. So, we
// make the caller decide what to do.
inline SubstituteArg(char value)
: text_(scratch_), size_(1) { scratch_[0] = value; }
inline SubstituteArg(short value)
: text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(unsigned short value)
: text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(int value)
: text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(unsigned int value)
: text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(long value)
: text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(unsigned long value)
: text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(long long value)
: text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(unsigned long long value)
: text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(float value)
: text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(double value)
: text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
inline SubstituteArg(bool value)
: text_(value ? "true" : "false"), size_(strlen(text_)) {}
inline const char* data() const { return text_; }
inline int size() const { return size_; }
private:
const char* text_;
int size_;
char scratch_[kFastToBufferSize];
};
} // namespace internal
LIBPROTOBUF_EXPORT string Substitute(
const char* format,
const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
const internal::SubstituteArg& arg9 = internal::SubstituteArg());
LIBPROTOBUF_EXPORT void SubstituteAndAppend(
string* output, const char* format,
const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
const internal::SubstituteArg& arg9 = internal::SubstituteArg());
} // namespace strings
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_