mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
958 lines
34 KiB
C++
958 lines
34 KiB
C++
// 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 <thirdparty/protobuf/compiler/cpp/string_field.h>
|
|
|
|
#include <thirdparty/protobuf/io/printer.h>
|
|
#include <thirdparty/protobuf/stubs/strutil.h>
|
|
#include <thirdparty/protobuf/compiler/cpp/helpers.h>
|
|
#include <thirdparty/protobuf/descriptor.pb.h>
|
|
|
|
|
|
namespace google {
|
|
namespace protobuf {
|
|
namespace compiler {
|
|
namespace cpp {
|
|
|
|
namespace {
|
|
|
|
void SetStringVariables(const FieldDescriptor* descriptor,
|
|
std::map<std::string, std::string>* variables,
|
|
const Options& options) {
|
|
SetCommonFieldVariables(descriptor, variables, options);
|
|
|
|
const std::string kNS = "::" + (*variables)["proto_ns"] + "::internal::";
|
|
const std::string kArenaStringPtr = kNS + "ArenaStringPtr";
|
|
|
|
(*variables)["default"] = DefaultValue(options, descriptor);
|
|
(*variables)["default_length"] =
|
|
StrCat(descriptor->default_value_string().length());
|
|
(*variables)["default_variable_name"] = MakeDefaultName(descriptor);
|
|
(*variables)["default_variable_field"] = MakeDefaultFieldName(descriptor);
|
|
|
|
if (descriptor->default_value_string().empty()) {
|
|
(*variables)["default_string"] = kNS + "GetEmptyStringAlreadyInited()";
|
|
(*variables)["default_value"] = "&" + (*variables)["default_string"];
|
|
(*variables)["lazy_variable_args"] = "";
|
|
} else {
|
|
(*variables)["lazy_variable"] =
|
|
StrCat(QualifiedClassName(descriptor->containing_type(), options),
|
|
"::", MakeDefaultFieldName(descriptor));
|
|
|
|
(*variables)["default_string"] = (*variables)["lazy_variable"] + ".get()";
|
|
(*variables)["default_value"] = "nullptr";
|
|
(*variables)["lazy_variable_args"] = (*variables)["lazy_variable"] + ", ";
|
|
}
|
|
|
|
(*variables)["pointer_type"] =
|
|
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
|
(*variables)["setter"] =
|
|
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
|
|
(*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
|
|
// 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();
|
|
|
|
if (options.opensource_runtime) {
|
|
(*variables)["string_piece"] = "::std::string";
|
|
} else {
|
|
(*variables)["string_piece"] = "::StringPiece";
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// ===================================================================
|
|
|
|
StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
|
|
const Options& options)
|
|
: FieldGenerator(descriptor, options),
|
|
inlined_(IsStringInlined(descriptor, options)) {
|
|
SetStringVariables(descriptor, &variables_, options);
|
|
}
|
|
|
|
StringFieldGenerator::~StringFieldGenerator() {}
|
|
|
|
void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (!inlined_) {
|
|
format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
|
|
} else {
|
|
// Skips the automatic destruction; rather calls it explicitly if
|
|
// allocating arena is null. This is required to support message-owned
|
|
// arena (go/path-to-arenas) where a root proto is destroyed but
|
|
// InlinedStringField may have arena-allocated memory.
|
|
format("::$proto_ns$::internal::InlinedStringField $name$_;\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (!descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"static const ::$proto_ns$::internal::LazyString"
|
|
" $default_variable_name$;\n");
|
|
}
|
|
if (inlined_) {
|
|
// `_init_inline_xxx` is used for initializing default instances.
|
|
format("static std::true_type _init_inline_$name$_;\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateAccessorDeclarations(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
// 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.
|
|
|
|
bool unknown_ctype = descriptor_->options().ctype() !=
|
|
EffectiveStringCType(descriptor_, options_);
|
|
|
|
if (unknown_ctype) {
|
|
format.Outdent();
|
|
format(
|
|
" private:\n"
|
|
" // Hidden due to unknown ctype option.\n");
|
|
format.Indent();
|
|
}
|
|
|
|
format(
|
|
"$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
|
|
"template <typename ArgT0 = const std::string&, typename... ArgT>\n"
|
|
"$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
|
|
descriptor_);
|
|
format(
|
|
"$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
|
|
"PROTOBUF_NODISCARD $deprecated_attr$std::string* "
|
|
"${1$$release_name$$}$();\n"
|
|
"$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
|
|
"$name$);\n",
|
|
descriptor_);
|
|
format(
|
|
"private:\n"
|
|
"const std::string& _internal_$name$() const;\n"
|
|
"inline PROTOBUF_ALWAYS_INLINE void "
|
|
"_internal_set_$name$(const std::string& value);\n"
|
|
"std::string* _internal_mutable_$name$();\n");
|
|
if (inlined_) {
|
|
format(
|
|
"inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() "
|
|
"const;\n");
|
|
}
|
|
format("public:\n");
|
|
|
|
if (unknown_ctype) {
|
|
format.Outdent();
|
|
format(" public:\n");
|
|
format.Indent();
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateInlineAccessorDefinitions(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"inline const std::string& $classname$::$name$() const {\n"
|
|
"$annotate_get$"
|
|
" // @@protoc_insertion_point(field_get:$full_name$)\n");
|
|
if (!descriptor_->default_value_string().empty()) {
|
|
format(
|
|
" if ($field$.IsDefault()) return "
|
|
"$default_variable_field$.get();\n");
|
|
}
|
|
format(
|
|
" return _internal_$name$();\n"
|
|
"}\n");
|
|
if (!inlined_) {
|
|
format(
|
|
"template <typename ArgT0, typename... ArgT>\n"
|
|
"inline PROTOBUF_ALWAYS_INLINE\n"
|
|
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
|
|
"$maybe_prepare_split_message$"
|
|
" $set_hasbit$\n"
|
|
" $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
|
|
" args..., GetArenaForAllocation());\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
|
"}\n");
|
|
} else {
|
|
format(
|
|
"template <typename ArgT0, typename... ArgT>\n"
|
|
"inline PROTOBUF_ALWAYS_INLINE\n"
|
|
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
|
|
"$maybe_prepare_split_message$"
|
|
" $set_hasbit$\n"
|
|
" $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
|
|
" args..., GetArenaForAllocation(), _internal_$name$_donated(), "
|
|
"&$donating_states_word$, $mask_for_undonate$, this);\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
|
"}\n"
|
|
"inline bool $classname$::_internal_$name$_donated() const {\n"
|
|
" bool value = $inlined_string_donated$\n"
|
|
" return value;\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline std::string* $classname$::mutable_$name$() {\n"
|
|
"$maybe_prepare_split_message$"
|
|
" std::string* _s = _internal_mutable_$name$();\n"
|
|
"$annotate_mutable$"
|
|
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
|
" return _s;\n"
|
|
"}\n"
|
|
"inline const std::string& $classname$::_internal_$name$() const {\n"
|
|
" return $field$.Get();\n"
|
|
"}\n"
|
|
"inline void $classname$::_internal_set_$name$(const std::string& "
|
|
"value) {\n"
|
|
" $set_hasbit$\n");
|
|
if (!inlined_) {
|
|
format(
|
|
" $field$.Set(value, GetArenaForAllocation());\n"
|
|
"}\n");
|
|
} else {
|
|
format(
|
|
" $field$.Set(value, GetArenaForAllocation(),\n"
|
|
" _internal_$name$_donated(), &$donating_states_word$, "
|
|
"$mask_for_undonate$, this);\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
|
|
" $set_hasbit$\n");
|
|
if (!inlined_) {
|
|
format(
|
|
" return $field$.Mutable($lazy_variable_args$"
|
|
"GetArenaForAllocation());\n"
|
|
"}\n");
|
|
} else {
|
|
format(
|
|
" return $field$.Mutable($lazy_variable_args$"
|
|
"GetArenaForAllocation(), _internal_$name$_donated(), "
|
|
"&$donating_states_word$, $mask_for_undonate$, this);\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline std::string* $classname$::$release_name$() {\n"
|
|
"$annotate_release$"
|
|
"$maybe_prepare_split_message$"
|
|
" // @@protoc_insertion_point(field_release:$full_name$)\n");
|
|
|
|
if (HasHasbit(descriptor_)) {
|
|
format(
|
|
" if (!_internal_has_$name$()) {\n"
|
|
" return nullptr;\n"
|
|
" }\n"
|
|
" $clear_hasbit$\n");
|
|
if (!inlined_) {
|
|
format(" auto* p = $field$.Release();\n");
|
|
if (descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
|
|
" if ($field$.IsDefault()) {\n"
|
|
" $field$.Set(\"\", GetArenaForAllocation());\n"
|
|
" }\n"
|
|
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
|
|
}
|
|
format(" return p;\n");
|
|
} else {
|
|
format(
|
|
" return $field$.Release(GetArenaForAllocation(), "
|
|
"_internal_$name$_donated());\n");
|
|
}
|
|
} else {
|
|
format(" return $field$.Release();\n");
|
|
}
|
|
|
|
format(
|
|
"}\n"
|
|
"inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
|
|
"$maybe_prepare_split_message$"
|
|
" if ($name$ != nullptr) {\n"
|
|
" $set_hasbit$\n"
|
|
" } else {\n"
|
|
" $clear_hasbit$\n"
|
|
" }\n");
|
|
if (!inlined_) {
|
|
format(" $field$.SetAllocated($name$, GetArenaForAllocation());\n");
|
|
if (descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
|
|
" if ($field$.IsDefault()) {\n"
|
|
" $field$.Set(\"\", GetArenaForAllocation());\n"
|
|
" }\n"
|
|
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
|
|
}
|
|
} else {
|
|
// Currently, string fields with default value can't be inlined.
|
|
format(
|
|
" $field$.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
|
|
"_internal_$name$_donated(), &$donating_states_word$, "
|
|
"$mask_for_undonate$, this);\n");
|
|
}
|
|
format(
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
|
"}\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (!descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"const ::$proto_ns$::internal::LazyString "
|
|
"$classname$::$default_variable_field$"
|
|
"{{{$default$, $default_length$}}, {nullptr}};\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (descriptor_->default_value_string().empty()) {
|
|
format("$field$.ClearToEmpty();\n");
|
|
} else {
|
|
GOOGLE_DCHECK(!inlined_);
|
|
format(
|
|
"$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateMessageClearingCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
// Two-dimension specialization here: supporting arenas, field presence, or
|
|
// not, and default value is the empty string or not. Complexity here ensures
|
|
// the minimal number of branches / amount of extraneous code at runtime
|
|
// (given that the below methods are inlined one-liners)!
|
|
|
|
// If we have a hasbit, then the Clear() method of the protocol buffer
|
|
// will have checked that this field is set. If so, we can avoid redundant
|
|
// checks against the default variable.
|
|
const bool must_be_present = HasHasbit(descriptor_);
|
|
|
|
if (inlined_ && must_be_present) {
|
|
// Calling mutable_$name$() gives us a string reference and sets the has bit
|
|
// for $name$ (in proto2). We may get here when the string field is inlined
|
|
// but the string's contents have not been changed by the user, so we cannot
|
|
// make an assertion about the contents of the string and could never make
|
|
// an assertion about the string instance.
|
|
//
|
|
// For non-inlined strings, we distinguish from non-default by comparing
|
|
// instances, rather than contents.
|
|
format("$DCHK$(!$field$.IsDefault());\n");
|
|
}
|
|
|
|
if (descriptor_->default_value_string().empty()) {
|
|
if (must_be_present) {
|
|
format("$field$.ClearNonDefaultToEmpty();\n");
|
|
} else {
|
|
format("$field$.ClearToEmpty();\n");
|
|
}
|
|
} else {
|
|
// Clear to a non-empty default is more involved, as we try to use the
|
|
// Arena if one is present and may need to reallocate the string.
|
|
format(
|
|
"$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
// TODO(gpike): improve this
|
|
format("_this->_internal_set_$name$(from._internal_$name$());\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (!inlined_) {
|
|
format(
|
|
"::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
|
|
" &$field$, lhs_arena,\n"
|
|
" &other->$field$, rhs_arena\n"
|
|
");\n");
|
|
} else {
|
|
format(
|
|
"::$proto_ns$::internal::InlinedStringField::InternalSwap(\n"
|
|
" &$field$, lhs_arena, "
|
|
"($inlined_string_donated_array$[0] & 0x1u) == 0, this,\n"
|
|
" &other->$field$, rhs_arena, "
|
|
"(other->$inlined_string_donated_array$[0] & 0x1u) == 0, other);\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (inlined_ && descriptor_->default_value_string().empty()) {
|
|
return;
|
|
}
|
|
GOOGLE_DCHECK(!inlined_);
|
|
format("$field$.InitDefault();\n");
|
|
if (IsString(descriptor_, options_) &&
|
|
descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
|
|
" $field$.Set(\"\", GetArenaForAllocation());\n"
|
|
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateCreateSplitMessageCode(
|
|
io::Printer* printer) const {
|
|
GOOGLE_CHECK(ShouldSplit(descriptor_, options_));
|
|
GOOGLE_CHECK(!inlined_);
|
|
Formatter format(printer, variables_);
|
|
format("ptr->$name$_.InitDefault();\n");
|
|
if (IsString(descriptor_, options_) &&
|
|
descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
|
|
" ptr->$name$_.Set(\"\", GetArenaForAllocation());\n"
|
|
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateCopyConstructorCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
GenerateConstructorCode(printer);
|
|
if (inlined_) {
|
|
format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
|
|
}
|
|
|
|
if (HasHasbit(descriptor_)) {
|
|
format("if (from._internal_has_$name$()) {\n");
|
|
} else {
|
|
format("if (!from._internal_$name$().empty()) {\n");
|
|
}
|
|
|
|
format.Indent();
|
|
|
|
if (!inlined_) {
|
|
format(
|
|
"_this->$field$.Set(from._internal_$name$(), \n"
|
|
" _this->GetArenaForAllocation());\n");
|
|
} else {
|
|
format(
|
|
"_this->$field$.Set(from._internal_$name$(),\n"
|
|
" _this->GetArenaForAllocation(), _this->_internal_$name$_donated(), "
|
|
"&_this->$donating_states_word$, $mask_for_undonate$, _this);\n");
|
|
}
|
|
|
|
format.Outdent();
|
|
format("}\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (!inlined_) {
|
|
if (ShouldSplit(descriptor_, options_)) {
|
|
format("$cached_split_ptr$->$name$_.Destroy();\n");
|
|
return;
|
|
}
|
|
format("$field$.Destroy();\n");
|
|
return;
|
|
}
|
|
// Explicitly calls ~InlinedStringField as its automatic call is disabled.
|
|
// Destructor has been implicitly skipped as a union, and even the
|
|
// message-owned arena is enabled, arena could still be missing for
|
|
// Arena::CreateMessage(nullptr).
|
|
GOOGLE_DCHECK(!ShouldSplit(descriptor_, options_));
|
|
format("$field$.~InlinedStringField();\n");
|
|
}
|
|
|
|
ArenaDtorNeeds StringFieldGenerator::NeedsArenaDestructor() const {
|
|
return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateArenaDestructorCode(
|
|
io::Printer* printer) const {
|
|
if (!inlined_) return;
|
|
Formatter format(printer, variables_);
|
|
// _this is the object being destructed (we are inside a static method here).
|
|
format(
|
|
"if (!_this->_internal_$name$_donated()) {\n"
|
|
" _this->$field$.~InlinedStringField();\n"
|
|
"}\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
|
GenerateUtf8CheckCodeForString(
|
|
descriptor_, options_, false,
|
|
"this->_internal_$name$().data(), "
|
|
"static_cast<int>(this->_internal_$name$().length()),\n",
|
|
format);
|
|
}
|
|
format(
|
|
"target = stream->Write$declared_type$MaybeAliased(\n"
|
|
" $number$, this->_internal_$name$(), target);\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"total_size += $tag_size$ +\n"
|
|
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
|
|
" this->_internal_$name$());\n");
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateConstexprAggregateInitializer(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (inlined_) {
|
|
format("/*decltype($field$)*/{nullptr, false}");
|
|
return;
|
|
}
|
|
if (descriptor_->default_value_string().empty()) {
|
|
format(
|
|
"/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
|
|
"::_pbi::ConstantInitialized{}}");
|
|
} else {
|
|
format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateAggregateInitializer(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
if (ShouldSplit(descriptor_, options_)) {
|
|
GOOGLE_CHECK(!inlined_);
|
|
format("decltype(Impl_::Split::$name$_){}");
|
|
return;
|
|
}
|
|
if (!inlined_) {
|
|
format("decltype($field$){}");
|
|
} else {
|
|
format("decltype($field$)(arena)");
|
|
}
|
|
}
|
|
|
|
void StringFieldGenerator::GenerateCopyAggregateInitializer(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("decltype($field$){}");
|
|
}
|
|
|
|
// ===================================================================
|
|
|
|
StringOneofFieldGenerator::StringOneofFieldGenerator(
|
|
const FieldDescriptor* descriptor, const Options& options)
|
|
: StringFieldGenerator(descriptor, options) {
|
|
SetCommonOneofFieldVariables(descriptor, &variables_);
|
|
variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
|
|
variables_["oneof_index"] =
|
|
StrCat(descriptor->containing_oneof()->index());
|
|
}
|
|
|
|
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
|
|
|
|
void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"inline const std::string& $classname$::$name$() const {\n"
|
|
"$annotate_get$"
|
|
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
|
" return _internal_$name$();\n"
|
|
"}\n"
|
|
"template <typename ArgT0, typename... ArgT>\n"
|
|
"inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
|
|
" if (!_internal_has_$name$()) {\n"
|
|
" clear_$oneof_name$();\n"
|
|
" set_has_$name$();\n"
|
|
" $field$.InitDefault();\n"
|
|
" }\n"
|
|
" $field$.$setter$("
|
|
" static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
|
"}\n"
|
|
"inline std::string* $classname$::mutable_$name$() {\n"
|
|
" std::string* _s = _internal_mutable_$name$();\n"
|
|
"$annotate_mutable$"
|
|
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
|
" return _s;\n"
|
|
"}\n"
|
|
"inline const std::string& $classname$::_internal_$name$() const {\n"
|
|
" if (_internal_has_$name$()) {\n"
|
|
" return $field$.Get();\n"
|
|
" }\n"
|
|
" return $default_string$;\n"
|
|
"}\n"
|
|
"inline void $classname$::_internal_set_$name$(const std::string& "
|
|
"value) {\n"
|
|
" if (!_internal_has_$name$()) {\n"
|
|
" clear_$oneof_name$();\n"
|
|
" set_has_$name$();\n"
|
|
" $field$.InitDefault();\n"
|
|
" }\n"
|
|
" $field$.Set(value, GetArenaForAllocation());\n"
|
|
"}\n");
|
|
format(
|
|
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
|
|
" if (!_internal_has_$name$()) {\n"
|
|
" clear_$oneof_name$();\n"
|
|
" set_has_$name$();\n"
|
|
" $field$.InitDefault();\n"
|
|
" }\n"
|
|
" return $field$.Mutable($lazy_variable_args$"
|
|
" GetArenaForAllocation());\n"
|
|
"}\n"
|
|
"inline std::string* $classname$::$release_name$() {\n"
|
|
"$annotate_release$"
|
|
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
|
" if (_internal_has_$name$()) {\n"
|
|
" clear_has_$oneof_name$();\n"
|
|
" return $field$.Release();\n"
|
|
" } else {\n"
|
|
" return nullptr;\n"
|
|
" }\n"
|
|
"}\n"
|
|
"inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
|
|
" if (has_$oneof_name$()) {\n"
|
|
" clear_$oneof_name$();\n"
|
|
" }\n"
|
|
" if ($name$ != nullptr) {\n"
|
|
" set_has_$name$();\n"
|
|
" $field$.InitAllocated($name$, GetArenaForAllocation());\n"
|
|
" }\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
|
"}\n");
|
|
}
|
|
|
|
void StringOneofFieldGenerator::GenerateClearingCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("$field$.Destroy();\n");
|
|
}
|
|
|
|
void StringOneofFieldGenerator::GenerateMessageClearingCode(
|
|
io::Printer* printer) const {
|
|
return GenerateClearingCode(printer);
|
|
}
|
|
|
|
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 {
|
|
// Nothing required here.
|
|
}
|
|
|
|
// ===================================================================
|
|
|
|
RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
|
|
const FieldDescriptor* descriptor, const Options& options)
|
|
: FieldGenerator(descriptor, options) {
|
|
SetStringVariables(descriptor, &variables_, options);
|
|
}
|
|
|
|
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
|
|
|
void RepeatedStringFieldGenerator::GeneratePrivateMembers(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
// See comment above about unknown ctypes.
|
|
bool unknown_ctype = descriptor_->options().ctype() !=
|
|
EffectiveStringCType(descriptor_, options_);
|
|
|
|
if (unknown_ctype) {
|
|
format.Outdent();
|
|
format(
|
|
" private:\n"
|
|
" // Hidden due to unknown ctype option.\n");
|
|
format.Indent();
|
|
}
|
|
|
|
format(
|
|
"$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
|
|
"$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
|
|
"$deprecated_attr$void ${1$set_$name$$}$(int index, const "
|
|
"std::string& value);\n"
|
|
"$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
|
|
"value);\n"
|
|
"$deprecated_attr$void ${1$set_$name$$}$(int index, const "
|
|
"char* value);\n",
|
|
descriptor_);
|
|
if (!options_.opensource_runtime) {
|
|
format(
|
|
"$deprecated_attr$void ${1$set_$name$$}$(int index, "
|
|
"StringPiece value);\n",
|
|
descriptor_);
|
|
}
|
|
format(
|
|
"$deprecated_attr$void ${1$set_$name$$}$("
|
|
"int index, const $pointer_type$* value, size_t size);\n"
|
|
"$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
|
|
"$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
|
|
"$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
|
|
"$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
|
|
descriptor_);
|
|
if (!options_.opensource_runtime) {
|
|
format(
|
|
"$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
|
|
descriptor_);
|
|
}
|
|
format(
|
|
"$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
|
|
"value, size_t size)"
|
|
";\n"
|
|
"$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
|
|
"${1$$name$$}$() "
|
|
"const;\n"
|
|
"$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
|
|
"${1$mutable_$name$$}$()"
|
|
";\n"
|
|
"private:\n"
|
|
"const std::string& ${1$_internal_$name$$}$(int index) const;\n"
|
|
"std::string* _internal_add_$name$();\n"
|
|
"public:\n",
|
|
descriptor_);
|
|
|
|
if (unknown_ctype) {
|
|
format.Outdent();
|
|
format(" public:\n");
|
|
format.Indent();
|
|
}
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"inline std::string* $classname$::add_$name$() {\n"
|
|
" std::string* _s = _internal_add_$name$();\n"
|
|
"$annotate_add_mutable$"
|
|
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
|
|
" return _s;\n"
|
|
"}\n");
|
|
if (options_.safe_boundary_check) {
|
|
format(
|
|
"inline const std::string& $classname$::_internal_$name$(int index) "
|
|
"const {\n"
|
|
" return $field$.InternalCheckedGet(\n"
|
|
" index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
|
|
"}\n");
|
|
} else {
|
|
format(
|
|
"inline const std::string& $classname$::_internal_$name$(int index) "
|
|
"const {\n"
|
|
" return $field$.Get(index);\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline const std::string& $classname$::$name$(int index) const {\n"
|
|
"$annotate_get$"
|
|
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
|
" return _internal_$name$(index);\n"
|
|
"}\n"
|
|
"inline std::string* $classname$::mutable_$name$(int index) {\n"
|
|
"$annotate_mutable$"
|
|
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
|
" return $field$.Mutable(index);\n"
|
|
"}\n"
|
|
"inline void $classname$::set_$name$(int index, const std::string& "
|
|
"value) "
|
|
"{\n"
|
|
" $field$.Mutable(index)->assign(value);\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
|
"}\n"
|
|
"inline void $classname$::set_$name$(int index, std::string&& value) {\n"
|
|
" $field$.Mutable(index)->assign(std::move(value));\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
|
"}\n"
|
|
"inline void $classname$::set_$name$(int index, const char* value) {\n"
|
|
" $null_check$"
|
|
" $field$.Mutable(index)->assign(value);\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
|
"}\n");
|
|
if (!options_.opensource_runtime) {
|
|
format(
|
|
"inline void "
|
|
"$classname$::set_$name$(int index, StringPiece value) {\n"
|
|
" $field$.Mutable(index)->assign(value.data(), value.size());\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline void "
|
|
"$classname$::set_$name$"
|
|
"(int index, const $pointer_type$* value, size_t size) {\n"
|
|
" $field$.Mutable(index)->assign(\n"
|
|
" reinterpret_cast<const char*>(value), size);\n"
|
|
"$annotate_set$"
|
|
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
|
|
"}\n"
|
|
"inline std::string* $classname$::_internal_add_$name$() {\n"
|
|
" return $field$.Add();\n"
|
|
"}\n"
|
|
"inline void $classname$::add_$name$(const std::string& value) {\n"
|
|
" $field$.Add()->assign(value);\n"
|
|
"$annotate_add$"
|
|
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
|
"}\n"
|
|
"inline void $classname$::add_$name$(std::string&& value) {\n"
|
|
" $field$.Add(std::move(value));\n"
|
|
"$annotate_add$"
|
|
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
|
"}\n"
|
|
"inline void $classname$::add_$name$(const char* value) {\n"
|
|
" $null_check$"
|
|
" $field$.Add()->assign(value);\n"
|
|
"$annotate_add$"
|
|
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
|
|
"}\n");
|
|
if (!options_.opensource_runtime) {
|
|
format(
|
|
"inline void $classname$::add_$name$(StringPiece value) {\n"
|
|
" $field$.Add()->assign(value.data(), value.size());\n"
|
|
"$annotate_add$"
|
|
" // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
|
|
"}\n");
|
|
}
|
|
format(
|
|
"inline void "
|
|
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
|
|
" $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
|
|
"$annotate_add$"
|
|
" // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
|
|
"}\n"
|
|
"inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
|
|
"$classname$::$name$() const {\n"
|
|
"$annotate_list$"
|
|
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
|
" return $field$;\n"
|
|
"}\n"
|
|
"inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
|
|
"$classname$::mutable_$name$() {\n"
|
|
"$annotate_mutable_list$"
|
|
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
|
" return &$field$;\n"
|
|
"}\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateClearingCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("$field$.Clear();\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateMergingCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("_this->$field$.MergeFrom(from.$field$);\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateSwappingCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("$field$.InternalSwap(&other->$field$);\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateDestructorCode(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format("$field$.~RepeatedPtrField();\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
|
|
" const auto& s = this->_internal_$name$(i);\n");
|
|
// format("for (const std::string& s : this->$name$()) {\n");
|
|
format.Indent();
|
|
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
|
GenerateUtf8CheckCodeForString(descriptor_, options_, false,
|
|
"s.data(), static_cast<int>(s.length()),\n",
|
|
format);
|
|
}
|
|
format.Outdent();
|
|
format(
|
|
" target = stream->Write$declared_type$($number$, s, target);\n"
|
|
"}\n");
|
|
}
|
|
|
|
void RepeatedStringFieldGenerator::GenerateByteSize(
|
|
io::Printer* printer) const {
|
|
Formatter format(printer, variables_);
|
|
format(
|
|
"total_size += $tag_size$ *\n"
|
|
" ::$proto_ns$::internal::FromIntSize($field$.size());\n"
|
|
"for (int i = 0, n = $field$.size(); i < n; i++) {\n"
|
|
" total_size += "
|
|
"::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
|
|
" $field$.Get(i));\n"
|
|
"}\n");
|
|
}
|
|
|
|
} // namespace cpp
|
|
} // namespace compiler
|
|
} // namespace protobuf
|
|
} // namespace google
|