| Index: third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
|
| index c53d5d3e22573470deac7e19f5c44fea75aa41af..fb46e3879104eb1c831636cfcdacdac322e256d6 100644
|
| --- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
|
| @@ -1,6 +1,6 @@
|
| // Protocol Buffers - Google's data interchange format
|
| // Copyright 2008 Google Inc. All rights reserved.
|
| -// http://code.google.com/p/protobuf/
|
| +// 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
|
| @@ -39,6 +39,7 @@
|
|
|
| #include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
| #include <google/protobuf/io/printer.h>
|
| +#include <google/protobuf/stubs/logging.h>
|
| #include <google/protobuf/stubs/common.h>
|
| #include <google/protobuf/stubs/strutil.h>
|
| #include <google/protobuf/stubs/substitute.h>
|
| @@ -51,6 +52,10 @@ namespace cpp {
|
|
|
| namespace {
|
|
|
| +static const char kAnyMessageName[] = "Any";
|
| +static const char kAnyProtoFile[] = "google/protobuf/any.proto";
|
| +static const char kGoogleProtobufPrefix[] = "google/protobuf/";
|
| +
|
| string DotsToUnderscores(const string& name) {
|
| return StringReplace(name, ".", "_", true);
|
| }
|
| @@ -60,16 +65,17 @@ string DotsToColons(const string& name) {
|
| }
|
|
|
| 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"
|
| + "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
|
| + "bool", "break", "case", "catch", "char", "class", "compl", "const",
|
| + "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
|
| + "double", "dynamic_cast", "else", "enum", "explicit", "extern", "false",
|
| + "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
|
| + "namespace", "new", "noexcept", "not", "not_eq", "NULL", "operator", "or",
|
| + "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
|
| + "return", "short", "signed", "sizeof", "static", "static_assert",
|
| + "static_cast", "struct", "switch", "template", "this", "thread_local",
|
| + "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
|
| + "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
|
| };
|
|
|
| hash_set<string> MakeKeywordsMap() {
|
| @@ -82,6 +88,22 @@ hash_set<string> MakeKeywordsMap() {
|
|
|
| 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.
|
| @@ -107,22 +129,6 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
| return result;
|
| }
|
|
|
| -// Returns whether the provided descriptor has an extension. This includes its
|
| -// nested types.
|
| -bool HasExtension(const Descriptor* descriptor) {
|
| - if (descriptor->extension_count() > 0) {
|
| - return true;
|
| - }
|
| - for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
| - if (HasExtension(descriptor->nested_type(i))) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| const char kThickSeparator[] =
|
| "// ===================================================================\n";
|
| const char kThinSeparator[] =
|
| @@ -161,11 +167,23 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
|
| }
|
|
|
|
|
| +string DependentBaseClassTemplateName(const Descriptor* descriptor) {
|
| + return ClassName(descriptor, false) + "_InternalBase";
|
| +}
|
| +
|
| string SuperClassName(const Descriptor* descriptor) {
|
| return HasDescriptorMethods(descriptor->file()) ?
|
| "::google::protobuf::Message" : "::google::protobuf::MessageLite";
|
| }
|
|
|
| +string DependentBaseDownCast() {
|
| + return "reinterpret_cast<T*>(this)->";
|
| +}
|
| +
|
| +string DependentBaseConstDownCast() {
|
| + return "reinterpret_cast<const T*>(this)->";
|
| +}
|
| +
|
| string FieldName(const FieldDescriptor* field) {
|
| string result = field->name();
|
| LowerString(&result);
|
| @@ -175,6 +193,14 @@ string FieldName(const FieldDescriptor* field) {
|
| return result;
|
| }
|
|
|
| +string EnumValueName(const EnumValueDescriptor* enum_value) {
|
| + string result = enum_value->name();
|
| + 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";
|
| @@ -191,6 +217,60 @@ string FieldConstantName(const FieldDescriptor *field) {
|
| return result;
|
| }
|
|
|
| +bool IsFieldDependent(const FieldDescriptor* field) {
|
| + if (field->containing_oneof() != NULL &&
|
| + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
| + return true;
|
| + }
|
| + if (field->is_map()) {
|
| + const Descriptor* map_descriptor = field->message_type();
|
| + for (int i = 0; i < map_descriptor->field_count(); i++) {
|
| + if (IsFieldDependent(map_descriptor->field(i))) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + return false;
|
| + }
|
| + if (field->containing_oneof() != NULL) {
|
| + // Oneof fields will always be dependent.
|
| + //
|
| + // This is a unique case for field codegen. Field generators are
|
| + // responsible for generating all the field-specific accessor
|
| + // functions, except for the clear_*() function; instead, field
|
| + // generators produce inline clearing code.
|
| + //
|
| + // For non-oneof fields, the Message class uses the inline clearing
|
| + // code to define the field's clear_*() function, as well as in the
|
| + // destructor. For oneof fields, the Message class generates a much
|
| + // more complicated clear_*() function, which clears only the oneof
|
| + // member that is set, in addition to clearing methods for each of the
|
| + // oneof members individually.
|
| + //
|
| + // Since oneofs do not have their own generator class, the Message code
|
| + // generation logic would be significantly complicated in order to
|
| + // split dependent and non-dependent manipulation logic based on
|
| + // whether the oneof truly needs to be dependent; so, for oneof fields,
|
| + // we just assume it (and its constituents) should be manipulated by a
|
| + // dependent base class function.
|
| + //
|
| + // This is less precise than how dependent message-typed fields are
|
| + // handled, but the cost is limited to only the generated code for the
|
| + // oneof field, which seems like an acceptable tradeoff.
|
| + return true;
|
| + }
|
| + if (field->file() == field->message_type()->file()) {
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +string DependentTypeName(const FieldDescriptor* field) {
|
| + return "InternalBase_" + field->name() + "_T";
|
| +}
|
| +
|
| 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.
|
| @@ -256,31 +336,35 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
|
| 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:
|
| - // gcc rejects the decimal form of kint32min and kint64min.
|
| - if (field->default_value_int32() == kint32min) {
|
| - // Make sure we are in a 2's complement system.
|
| - GOOGLE_COMPILE_ASSERT(
|
| - (uint32)kint32min == (uint32)0 - (uint32)0x80000000,
|
| - kint32min_value_error);
|
| - return "-0x80000000";
|
| - }
|
| - return SimpleItoa(field->default_value_int32());
|
| + return Int32ToString(field->default_value_int32());
|
| case FieldDescriptor::CPPTYPE_UINT32:
|
| return SimpleItoa(field->default_value_uint32()) + "u";
|
| case FieldDescriptor::CPPTYPE_INT64:
|
| - // See the comments for CPPTYPE_INT32.
|
| - if (field->default_value_int64() == kint64min) {
|
| - // Make sure we are in a 2's complement system.
|
| - GOOGLE_COMPILE_ASSERT(
|
| - (uint64)kint64min ==
|
| - (uint64)0 - (uint64)GOOGLE_LONGLONG(0x8000000000000000),
|
| - kint64min_value_error);
|
| - return "GOOGLE_LONGLONG(-0x8000000000000000)";
|
| - }
|
| - return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
|
| + return Int64ToString(field->default_value_int64());
|
| case FieldDescriptor::CPPTYPE_UINT64:
|
| return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
| case FieldDescriptor::CPPTYPE_DOUBLE: {
|
| @@ -323,7 +407,7 @@ string DefaultValue(const FieldDescriptor* field) {
|
| return strings::Substitute(
|
| "static_cast< $0 >($1)",
|
| ClassName(field->enum_type(), true),
|
| - field->default_value_enum()->number());
|
| + Int32ToString(field->default_value_enum()->number()));
|
| case FieldDescriptor::CPPTYPE_STRING:
|
| return "\"" + EscapeTrigraphs(
|
| CEscape(field->default_value_string())) +
|
| @@ -347,9 +431,7 @@ string FilenameIdentifier(const string& filename) {
|
| } 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));
|
| + StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
|
| }
|
| }
|
| return result;
|
| @@ -370,11 +452,39 @@ 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;
|
| @@ -420,6 +530,25 @@ void PrintHandlingOptionalStaticInitializers(
|
| }
|
|
|
|
|
| +static bool HasMapFields(const Descriptor* descriptor) {
|
| + for (int i = 0; i < descriptor->field_count(); ++i) {
|
| + if (descriptor->field(i)->is_map()) {
|
| + return true;
|
| + }
|
| + }
|
| + for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
| + if (HasMapFields(descriptor->nested_type(i))) return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool HasMapFields(const FileDescriptor* file) {
|
| + for (int i = 0; i < file->message_type_count(); ++i) {
|
| + if (HasMapFields(file->message_type(i))) return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| 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) {
|
| @@ -436,6 +565,134 @@ bool HasEnumDefinitions(const FileDescriptor* file) {
|
| 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;
|
| +}
|
| +
|
| +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
|
| + GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
|
| + // Open-source protobuf release only supports STRING ctype.
|
| + return FieldOptions::STRING;
|
| +
|
| +}
|
| +
|
| +bool IsAnyMessage(const FileDescriptor* descriptor) {
|
| + return descriptor->name() == kAnyProtoFile;
|
| +}
|
| +
|
| +bool IsAnyMessage(const Descriptor* descriptor) {
|
| + return descriptor->name() == kAnyMessageName &&
|
| + descriptor->file()->name() == kAnyProtoFile;
|
| +}
|
| +
|
| +bool IsWellKnownMessage(const FileDescriptor* descriptor) {
|
| + return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix);
|
| +}
|
| +
|
| +enum Utf8CheckMode {
|
| + STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields.
|
| + VERIFY = 1, // Only log an error but parsing will succeed.
|
| + NONE = 2, // No UTF-8 check.
|
| +};
|
| +
|
| +// Which level of UTF-8 enforcemant is placed on this file.
|
| +static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
|
| + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
| + return STRICT;
|
| + } else if (field->file()->options().optimize_for() !=
|
| + FileOptions::LITE_RUNTIME) {
|
| + return VERIFY;
|
| + } else {
|
| + return NONE;
|
| + }
|
| +}
|
| +
|
| +static void GenerateUtf8CheckCode(const FieldDescriptor* field,
|
| + bool for_parse,
|
| + const map<string, string>& variables,
|
| + const char* parameters,
|
| + const char* strict_function,
|
| + const char* verify_function,
|
| + io::Printer* printer) {
|
| + switch (GetUtf8CheckMode(field)) {
|
| + case STRICT: {
|
| + if (for_parse) {
|
| + printer->Print("DO_(");
|
| + }
|
| + printer->Print(
|
| + "::google::protobuf::internal::WireFormatLite::$function$(\n",
|
| + "function", strict_function);
|
| + printer->Indent();
|
| + printer->Print(variables, parameters);
|
| + if (for_parse) {
|
| + printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
|
| + } else {
|
| + printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
|
| + }
|
| + printer->Print("\"$full_name$\")", "full_name", field->full_name());
|
| + if (for_parse) {
|
| + printer->Print(")");
|
| + }
|
| + printer->Print(";\n");
|
| + printer->Outdent();
|
| + break;
|
| + }
|
| + case VERIFY: {
|
| + printer->Print(
|
| + "::google::protobuf::internal::WireFormat::$function$(\n",
|
| + "function", verify_function);
|
| + printer->Indent();
|
| + printer->Print(variables, parameters);
|
| + if (for_parse) {
|
| + printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
|
| + } else {
|
| + printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
|
| + }
|
| + printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
|
| + printer->Outdent();
|
| + break;
|
| + }
|
| + case NONE:
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
|
| + bool for_parse,
|
| + const map<string, string>& variables,
|
| + const char* parameters,
|
| + io::Printer* printer) {
|
| + GenerateUtf8CheckCode(field, for_parse, variables, parameters,
|
| + "VerifyUtf8String", "VerifyUTF8StringNamedField",
|
| + printer);
|
| +}
|
| +
|
| +void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
|
| + bool for_parse,
|
| + const map<string, string>& variables,
|
| + const char* parameters,
|
| + io::Printer* printer) {
|
| + GenerateUtf8CheckCode(field, for_parse, variables, parameters,
|
| + "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
|
| + printer);
|
| +}
|
| +
|
| } // namespace cpp
|
| } // namespace compiler
|
| } // namespace protobuf
|
|
|