diff options
author | thegeorg <[email protected]> | 2022-02-10 16:45:12 +0300 |
---|---|---|
committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:45:12 +0300 |
commit | 49116032d905455a7b1c994e4a696afc885c1e71 (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h | |
parent | 4e839db24a3bbc9f1c610c43d6faaaa99824dcca (diff) |
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h')
-rw-r--r-- | contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h | 1416 |
1 files changed, 708 insertions, 708 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h index 5c48883731b..1cc9329c86f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -35,89 +35,89 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ -#include <algorithm> -#include <cstdint> -#include <iterator> +#include <algorithm> +#include <cstdint> +#include <iterator> #include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/cpp_options.h> -#include <google/protobuf/compiler/cpp/cpp_names.h> -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/port.h> -#include <google/protobuf/stubs/strutil.h> - -// Must be included last. -#include <google/protobuf/port_def.inc> - +#include <string> + +#include <google/protobuf/compiler/cpp/cpp_options.h> +#include <google/protobuf/compiler/cpp/cpp_names.h> +#include <google/protobuf/compiler/scc.h> +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { -namespace compiler { -namespace cpp { - -inline TProtoStringType ProtobufNamespace(const Options& /* options */) { - return "PROTOBUF_NAMESPACE_ID"; -} - -inline TProtoStringType MacroPrefix(const Options& options) { - return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF"; -} - -inline TProtoStringType DeprecatedAttribute(const Options& /* options */, - const FieldDescriptor* d) { - return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : ""; -} - -inline TProtoStringType DeprecatedAttribute(const Options& /* options */, - const EnumValueDescriptor* d) { - return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : ""; -} - +namespace compiler { +namespace cpp { + +inline TProtoStringType ProtobufNamespace(const Options& /* options */) { + return "PROTOBUF_NAMESPACE_ID"; +} + +inline TProtoStringType MacroPrefix(const Options& options) { + return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF"; +} + +inline TProtoStringType DeprecatedAttribute(const Options& /* options */, + const FieldDescriptor* d) { + return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : ""; +} + +inline TProtoStringType DeprecatedAttribute(const Options& /* options */, + const EnumValueDescriptor* d) { + return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : ""; +} + // Commonly-used separator comments. Thick is a line of '=', thin is a line // of '-'. extern const char kThickSeparator[]; extern const char kThinSeparator[]; -void SetCommonVars(const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables); - -void SetUnknownFieldsVariable(const Descriptor* descriptor, - const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables); - -bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename, - TProtoStringType* bootstrap_basename); -bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, - bool bootstrap_flag, TProtoStringType* basename); -bool IsBootstrapProto(const Options& options, const FileDescriptor* file); - -// Name space of the proto file. This namespace is such that the string -// "<namespace>::some_name" is the correct fully qualified namespace. -// This means if the package is empty the namespace is "", and otherwise -// the namespace is "::foo::bar::...::baz" without trailing semi-colons. -TProtoStringType Namespace(const FileDescriptor* d, const Options& options); -TProtoStringType Namespace(const Descriptor* d, const Options& options); -TProtoStringType Namespace(const FieldDescriptor* d, const Options& options); -TProtoStringType Namespace(const EnumDescriptor* d, const Options& options); - -// Returns true if it's safe to reset "field" to zero. -bool CanInitializeByZeroing(const FieldDescriptor* field); - -TProtoStringType ClassName(const Descriptor* descriptor); -TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); - -TProtoStringType QualifiedClassName(const Descriptor* d, const Options& options); -TProtoStringType QualifiedClassName(const EnumDescriptor* d, const Options& options); - -TProtoStringType QualifiedClassName(const Descriptor* d); -TProtoStringType QualifiedClassName(const EnumDescriptor* d); - -// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very -// unreadable at the callsite. +void SetCommonVars(const Options& options, + std::map<TProtoStringType, TProtoStringType>* variables); + +void SetUnknownFieldsVariable(const Descriptor* descriptor, + const Options& options, + std::map<TProtoStringType, TProtoStringType>* variables); + +bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename, + TProtoStringType* bootstrap_basename); +bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, + bool bootstrap_flag, TProtoStringType* basename); +bool IsBootstrapProto(const Options& options, const FileDescriptor* file); + +// Name space of the proto file. This namespace is such that the string +// "<namespace>::some_name" is the correct fully qualified namespace. +// This means if the package is empty the namespace is "", and otherwise +// the namespace is "::foo::bar::...::baz" without trailing semi-colons. +TProtoStringType Namespace(const FileDescriptor* d, const Options& options); +TProtoStringType Namespace(const Descriptor* d, const Options& options); +TProtoStringType Namespace(const FieldDescriptor* d, const Options& options); +TProtoStringType Namespace(const EnumDescriptor* d, const Options& options); + +// Returns true if it's safe to reset "field" to zero. +bool CanInitializeByZeroing(const FieldDescriptor* field); + +TProtoStringType ClassName(const Descriptor* descriptor); +TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); + +TProtoStringType QualifiedClassName(const Descriptor* d, const Options& options); +TProtoStringType QualifiedClassName(const EnumDescriptor* d, const Options& options); + +TProtoStringType QualifiedClassName(const Descriptor* d); +TProtoStringType QualifiedClassName(const EnumDescriptor* d); + +// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very +// unreadable at the callsite. // 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; @@ -126,170 +126,170 @@ TProtoStringType QualifiedClassName(const EnumDescriptor* d); // ::foo::bar::Baz_Qux // While the non-qualified version would be: // Baz_Qux -inline TProtoStringType ClassName(const Descriptor* descriptor, bool qualified) { - return qualified ? QualifiedClassName(descriptor, Options()) - : ClassName(descriptor); -} - -inline TProtoStringType ClassName(const EnumDescriptor* descriptor, bool qualified) { - return qualified ? QualifiedClassName(descriptor, Options()) - : ClassName(descriptor); -} - -// Returns the extension name prefixed with the class name if nested but without -// the package name. -TProtoStringType ExtensionName(const FieldDescriptor* d); - -TProtoStringType QualifiedExtensionName(const FieldDescriptor* d, - const Options& options); -TProtoStringType QualifiedExtensionName(const FieldDescriptor* d); - -// Type name of default instance. -TProtoStringType DefaultInstanceType(const Descriptor* descriptor, - const Options& options); - -// Non-qualified name of the default_instance of this message. -TProtoStringType DefaultInstanceName(const Descriptor* descriptor, - const Options& options); - -// Non-qualified name of the default instance pointer. This is used only for -// implicit weak fields, where we need an extra indirection. -TProtoStringType DefaultInstancePtr(const Descriptor* descriptor, - const Options& options); - +inline TProtoStringType ClassName(const Descriptor* descriptor, bool qualified) { + return qualified ? QualifiedClassName(descriptor, Options()) + : ClassName(descriptor); +} + +inline TProtoStringType ClassName(const EnumDescriptor* descriptor, bool qualified) { + return qualified ? QualifiedClassName(descriptor, Options()) + : ClassName(descriptor); +} + +// Returns the extension name prefixed with the class name if nested but without +// the package name. +TProtoStringType ExtensionName(const FieldDescriptor* d); + +TProtoStringType QualifiedExtensionName(const FieldDescriptor* d, + const Options& options); +TProtoStringType QualifiedExtensionName(const FieldDescriptor* d); + +// Type name of default instance. +TProtoStringType DefaultInstanceType(const Descriptor* descriptor, + const Options& options); + +// Non-qualified name of the default_instance of this message. +TProtoStringType DefaultInstanceName(const Descriptor* descriptor, + const Options& options); + +// Non-qualified name of the default instance pointer. This is used only for +// implicit weak fields, where we need an extra indirection. +TProtoStringType DefaultInstancePtr(const Descriptor* descriptor, + const Options& options); + // Fully qualified name of the default_instance of this message. -TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, - const Options& options); - -// Fully qualified name of the default instance pointer. -TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor, - const Options& options); - -// DescriptorTable variable name. -TProtoStringType DescriptorTableName(const FileDescriptor* file, - const Options& options); - -// When declaring symbol externs from another file, this macro will supply the -// dllexport needed for the target file, if any. -TProtoStringType FileDllExport(const FileDescriptor* file, const Options& options); - -// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite. -TProtoStringType SuperClassName(const Descriptor* descriptor, - const Options& options); - -// Adds an underscore if necessary to prevent conflicting with a keyword. -TProtoStringType ResolveKeyword(const TProtoStringType& name); - +TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, + const Options& options); + +// Fully qualified name of the default instance pointer. +TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor, + const Options& options); + +// DescriptorTable variable name. +TProtoStringType DescriptorTableName(const FileDescriptor* file, + const Options& options); + +// When declaring symbol externs from another file, this macro will supply the +// dllexport needed for the target file, if any. +TProtoStringType FileDllExport(const FileDescriptor* file, const Options& options); + +// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite. +TProtoStringType SuperClassName(const Descriptor* descriptor, + const Options& options); + +// Adds an underscore if necessary to prevent conflicting with a keyword. +TProtoStringType ResolveKeyword(const TProtoStringType& name); + // 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(). -TProtoStringType FieldName(const FieldDescriptor* field); - -// Returns an estimate of the compiler's alignment for the field. This -// can't guarantee to be correct because the generated code could be compiled on -// different systems with different alignment rules. The estimates below assume -// 64-bit pointers. -int EstimateAlignmentSize(const FieldDescriptor* field); - +TProtoStringType FieldName(const FieldDescriptor* field); + +// Returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field); + // Get the unqualified name that should be used for a field's field // number constant. -TProtoStringType FieldConstantName(const FieldDescriptor* field); +TProtoStringType 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(); + 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); -TProtoStringType FieldMessageTypeName(const FieldDescriptor* field, - const Options& options); +TProtoStringType FieldMessageTypeName(const FieldDescriptor* field, + const Options& options); // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.). const char* PrimitiveTypeName(FieldDescriptor::CppType type); -TProtoStringType PrimitiveTypeName(const Options& options, - FieldDescriptor::CppType type); +TProtoStringType PrimitiveTypeName(const Options& options, + 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. -TProtoStringType Int32ToString(int number); +TProtoStringType Int32ToString(int number); // Get code that evaluates to the field's default value. -TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* field); +TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* field); + +// Compatibility function for callers outside proto2. +TProtoStringType DefaultValue(const FieldDescriptor* field); -// Compatibility function for callers outside proto2. -TProtoStringType DefaultValue(const FieldDescriptor* field); - // Convert a file name into a valid identifier. -TProtoStringType FilenameIdentifier(const TProtoStringType& filename); - -// For each .proto file generates a unique name. To prevent collisions of -// symbols in the global namespace -TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename, - const Options& options); -inline TProtoStringType UniqueName(const TProtoStringType& name, const FileDescriptor* d, - const Options& options) { - return UniqueName(name, d->name(), options); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d, - const Options& options) { - return UniqueName(name, d->file(), options); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, const EnumDescriptor* d, - const Options& options) { - return UniqueName(name, d->file(), options); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, - const ServiceDescriptor* d, - const Options& options) { - return UniqueName(name, d->file(), options); -} - -// Versions for call sites that only support the internal runtime (like proto1 -// support). -inline Options InternalRuntimeOptions() { - Options options; - options.opensource_runtime = false; - return options; -} -inline TProtoStringType UniqueName(const TProtoStringType& name, - const TProtoStringType& filename) { - return UniqueName(name, filename, InternalRuntimeOptions()); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, - const FileDescriptor* d) { - return UniqueName(name, d->name(), InternalRuntimeOptions()); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d) { - return UniqueName(name, d->file(), InternalRuntimeOptions()); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, - const EnumDescriptor* d) { - return UniqueName(name, d->file(), InternalRuntimeOptions()); -} -inline TProtoStringType UniqueName(const TProtoStringType& name, - const ServiceDescriptor* d) { - return UniqueName(name, d->file(), InternalRuntimeOptions()); -} - +TProtoStringType FilenameIdentifier(const TProtoStringType& filename); + +// For each .proto file generates a unique name. To prevent collisions of +// symbols in the global namespace +TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename, + const Options& options); +inline TProtoStringType UniqueName(const TProtoStringType& name, const FileDescriptor* d, + const Options& options) { + return UniqueName(name, d->name(), options); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, const EnumDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, + const ServiceDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} + +// Versions for call sites that only support the internal runtime (like proto1 +// support). +inline Options InternalRuntimeOptions() { + Options options; + options.opensource_runtime = false; + return options; +} +inline TProtoStringType UniqueName(const TProtoStringType& name, + const TProtoStringType& filename) { + return UniqueName(name, filename, InternalRuntimeOptions()); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, + const FileDescriptor* d) { + return UniqueName(name, d->name(), InternalRuntimeOptions()); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, + const EnumDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} +inline TProtoStringType UniqueName(const TProtoStringType& name, + const ServiceDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} + // Return the qualified C++ name for a file level symbol. -TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file, - const TProtoStringType& name, - const Options& options); +TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file, + const TProtoStringType& name, + const Options& options); // Escape C++ trigraphs by escaping question marks to \? -TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape); +TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape); // Escaped function name to eliminate naming conflict. -TProtoStringType SafeFunctionName(const Descriptor* descriptor, - const FieldDescriptor* field, - const TProtoStringType& prefix); +TProtoStringType SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const TProtoStringType& prefix); // Returns true if generated messages have public unknown fields accessors inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { @@ -297,8 +297,8 @@ inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { } // Returns the optimize mode for <file>, respecting <options.enforce_lite>. -FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, - const Options& options); +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options); // Determines whether unknown fields will be stored in an UnknownFieldSet or // a string. @@ -307,81 +307,81 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file, return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME; } -inline bool IsWeak(const FieldDescriptor* field, const Options& options) { - if (field->options().weak()) { - GOOGLE_CHECK(!options.opensource_runtime); - return true; - } - return false; -} - -// For a string field, returns the effective ctype. If the actual ctype is -// not supported, returns the default of STRING. -FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, - const Options& options); - -inline bool IsCord(const FieldDescriptor* field, const Options& options) { - return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - EffectiveStringCType(field, options) == FieldOptions::CORD; -} - -inline bool IsStringPiece(const FieldDescriptor* field, - const Options& options) { - return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; -} - -class MessageSCCAnalyzer; - -// Does the given FileDescriptor use lazy fields? -bool HasLazyFields(const FileDescriptor* file, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - -// Is the given field a supported lazy field? -bool IsLazy(const FieldDescriptor* field, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - -inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field, - const Options& options) { - return field->options().lazy() && !field->is_repeated() && - field->type() == FieldDescriptor::TYPE_MESSAGE && - GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME && - !options.opensource_runtime; -} - -inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, - const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - return IsLazy(field, options, scc_analyzer) && !field->options().lazy(); -} - -inline bool IsFieldUsed(const FieldDescriptor* /* field */, - const Options& /* options */) { - return true; -} - -// Returns true if "field" is stripped. -inline bool IsFieldStripped(const FieldDescriptor* /*field*/, - const Options& /*options*/) { - return false; -} - -// Does the file contain any definitions that need extension_set.h? -bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); - -// Does the file have any repeated fields, necessitating the file to include -// repeated_field.h? This does not include repeated extensions, since those are -// all stored internally in an ExtensionSet, not a separate RepeatedField*. -bool HasRepeatedFields(const FileDescriptor* file); - -// Does the file have any string/bytes fields with ctype=STRING_PIECE? This -// does not include extensions, since ctype is ignored for extensions. -bool HasStringPieceFields(const FileDescriptor* file, const Options& options); - -// Does the file have any string/bytes fields with ctype=CORD? This does not -// include extensions, since ctype is ignored for extensions. -bool HasCordFields(const FileDescriptor* file, const Options& options); - +inline bool IsWeak(const FieldDescriptor* field, const Options& options) { + if (field->options().weak()) { + GOOGLE_CHECK(!options.opensource_runtime); + return true; + } + return false; +} + +// For a string field, returns the effective ctype. If the actual ctype is +// not supported, returns the default of STRING. +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, + const Options& options); + +inline bool IsCord(const FieldDescriptor* field, const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::CORD; +} + +inline bool IsStringPiece(const FieldDescriptor* field, + const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; +} + +class MessageSCCAnalyzer; + +// Does the given FileDescriptor use lazy fields? +bool HasLazyFields(const FileDescriptor* file, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + +// Is the given field a supported lazy field? +bool IsLazy(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + +inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field, + const Options& options) { + return field->options().lazy() && !field->is_repeated() && + field->type() == FieldDescriptor::TYPE_MESSAGE && + GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME && + !options.opensource_runtime; +} + +inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + return IsLazy(field, options, scc_analyzer) && !field->options().lazy(); +} + +inline bool IsFieldUsed(const FieldDescriptor* /* field */, + const Options& /* options */) { + return true; +} + +// Returns true if "field" is stripped. +inline bool IsFieldStripped(const FieldDescriptor* /*field*/, + const Options& /*options*/) { + return false; +} + +// Does the file contain any definitions that need extension_set.h? +bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); + +// Does the file have any repeated fields, necessitating the file to include +// repeated_field.h? This does not include repeated extensions, since those are +// all stored internally in an ExtensionSet, not a separate RepeatedField*. +bool HasRepeatedFields(const FileDescriptor* file); + +// Does the file have any string/bytes fields with ctype=STRING_PIECE? This +// does not include extensions, since ctype is ignored for extensions. +bool HasStringPieceFields(const FileDescriptor* file, const Options& options); + +// Does the file have any string/bytes fields with ctype=CORD? This does not +// include extensions, since ctype is ignored for extensions. +bool HasCordFields(const FileDescriptor* file, const Options& options); + // Does the file have any map fields, necessitating the file to include // map_field_inl.h and map.h. bool HasMapFields(const FileDescriptor* file); @@ -410,13 +410,13 @@ inline bool HasGenericServices(const FileDescriptor* file, file->options().cc_generic_services(); } -inline bool IsProto2MessageSet(const Descriptor* descriptor, - const Options& options) { - return !options.opensource_runtime && - options.enforce_mode != EnforceOptimizeMode::kLiteRuntime && - !options.lite_implicit_weak_fields && - descriptor->options().message_set_wire_format() && - descriptor->full_name() == "google.protobuf.bridge.MessageSet"; +inline bool IsProto2MessageSet(const Descriptor* descriptor, + const Options& options) { + return !options.opensource_runtime && + options.enforce_mode != EnforceOptimizeMode::kLiteRuntime && + !options.lite_implicit_weak_fields && + descriptor->options().message_set_wire_format() && + descriptor->full_name() == "google.protobuf.bridge.MessageSet"; } inline bool IsMapEntryMessage(const Descriptor* descriptor) { @@ -426,122 +426,122 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, - bool cap_next_letter); - -inline bool IsProto3(const FileDescriptor* file) { - return file->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - -inline bool HasHasbit(const FieldDescriptor* field) { - // This predicate includes proto3 message fields only if they have "optional". - // Foo submsg1 = 1; // HasHasbit() == false - // optional Foo submsg2 = 2; // HasHasbit() == true - // This is slightly odd, as adding "optional" to a singular proto3 field does - // not change the semantics or API. However whenever any field in a message - // has a hasbit, it forces reflection to include hasbit offsets for *all* - // fields, even if almost all of them are set to -1 (no hasbit). So to avoid - // causing a sudden size regression for ~all proto3 messages, we give proto3 - // message fields a hasbit only if "optional" is present. If the user is - // explicitly writing "optional", it is likely they are writing it on - // primitive fields also. - return (field->has_optional_keyword() || field->is_required()) && - !field->options().weak(); -} - +TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, + bool cap_next_letter); + +inline bool IsProto3(const FileDescriptor* file) { + return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +inline bool HasHasbit(const FieldDescriptor* field) { + // This predicate includes proto3 message fields only if they have "optional". + // Foo submsg1 = 1; // HasHasbit() == false + // optional Foo submsg2 = 2; // HasHasbit() == true + // This is slightly odd, as adding "optional" to a singular proto3 field does + // not change the semantics or API. However whenever any field in a message + // has a hasbit, it forces reflection to include hasbit offsets for *all* + // fields, even if almost all of them are set to -1 (no hasbit). So to avoid + // causing a sudden size regression for ~all proto3 messages, we give proto3 + // message fields a hasbit only if "optional" is present. If the user is + // explicitly writing "optional", it is likely they are writing it on + // primitive fields also. + return (field->has_optional_keyword() || field->is_required()) && + !field->options().weak(); +} + // Returns true if 'enum' semantics are such that unknown values are preserved // in the enum field itself, rather than going to the UnknownFieldSet. -inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { - return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; +inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; } -inline bool IsCrossFileMessage(const FieldDescriptor* field) { - return field->type() == FieldDescriptor::TYPE_MESSAGE && - field->message_type()->file() != field->file(); +inline bool IsCrossFileMessage(const FieldDescriptor* field) { + return field->type() == FieldDescriptor::TYPE_MESSAGE && + field->message_type()->file() != field->file(); } -inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) { - return "_i_give_permission_to_break_this_code_default_" + FieldName(field) + - "_"; +inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) { + return "_i_give_permission_to_break_this_code_default_" + FieldName(field) + + "_"; } -bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options); -bool IsAnyMessage(const Descriptor* descriptor, const Options& options); +bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options); +bool IsAnyMessage(const Descriptor* descriptor, const Options& options); bool IsWellKnownMessage(const FileDescriptor* descriptor); -inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h, - const Options& options) { - // If we are generating a .pb.h file and the proto_h option is enabled, then - // the .pb.h gets an extra suffix. - TProtoStringType filename_identifier = FilenameIdentifier( - file->name() + (pb_h && options.proto_h ? ".pb.h" : "")); - - if (IsWellKnownMessage(file)) { - // For well-known messages we need third_party/protobuf and net/proto2 to - // have distinct include guards, because some source files include both and - // both need to be defined (the third_party copies will be in the - // google::protobuf_opensource namespace). - return MacroPrefix(options) + "_INCLUDED_" + filename_identifier; - } else { - // Ideally this case would use distinct include guards for opensource and - // google3 protos also. (The behavior of "first #included wins" is not - // ideal). But unfortunately some legacy code includes both and depends on - // the identical include guards to avoid compile errors. - // - // We should clean this up so that this case can be removed. - return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier; - } -} - -// Returns the OptimizeMode for this file, furthermore it updates a status -// bool if has_opt_codesize_extension is non-null. If this status bool is true -// it means this file contains an extension that itself is defined as -// optimized_for = CODE_SIZE. -FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, - const Options& options, - bool* has_opt_codesize_extension); -inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, - const Options& options) { - return GetOptimizeFor(file, options, nullptr); -} -inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file, - const Options& options) { - bool has_opt_codesize_extension; - if (GetOptimizeFor(file, options, &has_opt_codesize_extension) == - FileOptions::CODE_SIZE && - has_opt_codesize_extension) { - // If this filedescriptor contains an extension from another file which - // is optimized_for = CODE_SIZE. We need to be careful in the ordering so - // we eagerly build the descriptors in the dependencies before building - // the descriptors of this file. - return true; - } else { - // If we have a generated code based parser we never need eager - // initialization of descriptors of our deps. - return false; - } -} +inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h, + const Options& options) { + // If we are generating a .pb.h file and the proto_h option is enabled, then + // the .pb.h gets an extra suffix. + TProtoStringType filename_identifier = FilenameIdentifier( + file->name() + (pb_h && options.proto_h ? ".pb.h" : "")); + + if (IsWellKnownMessage(file)) { + // For well-known messages we need third_party/protobuf and net/proto2 to + // have distinct include guards, because some source files include both and + // both need to be defined (the third_party copies will be in the + // google::protobuf_opensource namespace). + return MacroPrefix(options) + "_INCLUDED_" + filename_identifier; + } else { + // Ideally this case would use distinct include guards for opensource and + // google3 protos also. (The behavior of "first #included wins" is not + // ideal). But unfortunately some legacy code includes both and depends on + // the identical include guards to avoid compile errors. + // + // We should clean this up so that this case can be removed. + return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier; + } +} + +// Returns the OptimizeMode for this file, furthermore it updates a status +// bool if has_opt_codesize_extension is non-null. If this status bool is true +// it means this file contains an extension that itself is defined as +// optimized_for = CODE_SIZE. +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options, + bool* has_opt_codesize_extension); +inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options, nullptr); +} +inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file, + const Options& options) { + bool has_opt_codesize_extension; + if (GetOptimizeFor(file, options, &has_opt_codesize_extension) == + FileOptions::CODE_SIZE && + has_opt_codesize_extension) { + // If this filedescriptor contains an extension from another file which + // is optimized_for = CODE_SIZE. We need to be careful in the ordering so + // we eagerly build the descriptors in the dependencies before building + // the descriptors of this file. + return true; + } else { + // If we have a generated code based parser we never need eager + // initialization of descriptors of our deps. + return false; + } +} // This orders the messages in a .pb.cc as it's outputted by file.cc -void FlattenMessagesInFile(const FileDescriptor* file, - std::vector<const Descriptor*>* result); -inline std::vector<const Descriptor*> FlattenMessagesInFile( - const FileDescriptor* file) { - std::vector<const Descriptor*> result; - FlattenMessagesInFile(file, &result); - return result; -} - -bool HasWeakFields(const Descriptor* desc, const Options& options); -bool HasWeakFields(const FileDescriptor* desc, const Options& options); +void FlattenMessagesInFile(const FileDescriptor* file, + std::vector<const Descriptor*>* result); +inline std::vector<const Descriptor*> FlattenMessagesInFile( + const FileDescriptor* file) { + std::vector<const Descriptor*> result; + FlattenMessagesInFile(file, &result); + return result; +} + +bool HasWeakFields(const Descriptor* desc, const Options& options); +bool HasWeakFields(const FileDescriptor* desc, const Options& options); // Returns true if the "required" restriction check should be ignored for the // given field. -inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, - const Options& options) { - // Do not check "required" for lazily verified lazy fields. - return IsLazilyVerifiedLazy(field, options); +inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, + const Options& options) { + // Do not check "required" for lazily verified lazy fields. + return IsLazilyVerifiedLazy(field, options); } struct MessageAnalysis { @@ -549,16 +549,16 @@ struct MessageAnalysis { bool contains_cord; bool contains_extension; bool contains_required; - bool contains_weak; // Implicit weak as well. + bool contains_weak; // Implicit weak as well. }; // This class is used in FileGenerator, to ensure linear instead of // quadratic performance, if we do this per message we would get O(V*(V+E)). // Logically this is just only used in message.cc, but in the header for // FileGenerator to help share it. -class PROTOC_EXPORT MessageSCCAnalyzer { +class PROTOC_EXPORT MessageSCCAnalyzer { public: - explicit MessageSCCAnalyzer(const Options& options) : options_(options) {} + explicit MessageSCCAnalyzer(const Options& options) : options_(options) {} MessageAnalysis GetSCCAnalysis(const SCC* scc); @@ -566,331 +566,331 @@ class PROTOC_EXPORT MessageSCCAnalyzer { MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); return result.contains_required || result.contains_extension; } - bool HasWeakField(const Descriptor* descriptor) { - MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); - return result.contains_weak; - } - const SCC* GetSCC(const Descriptor* descriptor) { - return analyzer_.GetSCC(descriptor); - } + bool HasWeakField(const Descriptor* descriptor) { + MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); + return result.contains_weak; + } + const SCC* GetSCC(const Descriptor* descriptor) { + return analyzer_.GetSCC(descriptor); + } private: - struct DepsGenerator { - std::vector<const Descriptor*> operator()(const Descriptor* desc) const { - std::vector<const Descriptor*> deps; - for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->message_type()) { - deps.push_back(desc->field(i)->message_type()); - } - } - return deps; - } + struct DepsGenerator { + std::vector<const Descriptor*> operator()(const Descriptor* desc) const { + std::vector<const Descriptor*> deps; + for (int i = 0; i < desc->field_count(); i++) { + if (desc->field(i)->message_type()) { + deps.push_back(desc->field(i)->message_type()); + } + } + return deps; + } }; - SCCAnalyzer<DepsGenerator> analyzer_; + SCCAnalyzer<DepsGenerator> analyzer_; Options options_; std::map<const SCC*, MessageAnalysis> analysis_cache_; -}; - -void ListAllFields(const Descriptor* d, - std::vector<const FieldDescriptor*>* fields); -void ListAllFields(const FileDescriptor* d, - std::vector<const FieldDescriptor*>* fields); - -template <class T> -void ForEachField(const Descriptor* d, T&& func) { - for (int i = 0; i < d->nested_type_count(); i++) { - ForEachField(d->nested_type(i), std::forward<T&&>(func)); +}; + +void ListAllFields(const Descriptor* d, + std::vector<const FieldDescriptor*>* fields); +void ListAllFields(const FileDescriptor* d, + std::vector<const FieldDescriptor*>* fields); + +template <class T> +void ForEachField(const Descriptor* d, T&& func) { + for (int i = 0; i < d->nested_type_count(); i++) { + ForEachField(d->nested_type(i), std::forward<T&&>(func)); + } + for (int i = 0; i < d->extension_count(); i++) { + func(d->extension(i)); + } + for (int i = 0; i < d->field_count(); i++) { + func(d->field(i)); + } +} + +template <class T> +void ForEachField(const FileDescriptor* d, T&& func) { + for (int i = 0; i < d->message_type_count(); i++) { + ForEachField(d->message_type(i), std::forward<T&&>(func)); + } + for (int i = 0; i < d->extension_count(); i++) { + func(d->extension(i)); + } +} + +void ListAllTypesForServices(const FileDescriptor* fd, + std::vector<const Descriptor*>* types); + +// Indicates whether we should use implicit weak fields for this file. +bool UsingImplicitWeakFields(const FileDescriptor* file, + const Options& options); + +// Indicates whether to treat this field as implicitly weak. +bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + +// Formatter is a functor class which acts as a closure around printer and +// the variable map. It's much like printer->Print except it supports both named +// variables that are substituted using a key value map and direct arguments. In +// the format string $1$, $2$, etc... are substituted for the first, second, ... +// direct argument respectively in the format call, it accepts both strings and +// integers. The implementation verifies all arguments are used and are "first" +// used in order of appearance in the argument list. For example, +// +// Format("return array[$1$];", 3) -> "return array[3];" +// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order) +// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;" +// +// The arguments can be used more than once like +// +// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") -> +// "array[3] = Bla; // Index = 3" +// +// If you use more arguments use the following style to help the reader, +// +// Format("int $1$() {\n" +// " array[$2$] = $3$;\n" +// " return $4$;" +// "}\n", +// funname, // 1 +// idx, // 2 +// varname, // 3 +// retval); // 4 +// +// but consider using named variables. Named variables like $foo$, with some +// identifier foo, are looked up in the map. One additional feature is that +// spaces are accepted between the '$' delimiters, $ foo$ will +// substiture to " bar" if foo stands for "bar", but in case it's empty +// will substitute to "". Hence, for example, +// +// Format(vars, "$dllexport $void fun();") -> "void fun();" +// "__declspec(export) void fun();" +// +// which is convenient to prevent double, leading or trailing spaces. +class PROTOC_EXPORT Formatter { + public: + explicit Formatter(io::Printer* printer) : printer_(printer) {} + Formatter(io::Printer* printer, + const std::map<TProtoStringType, TProtoStringType>& vars) + : printer_(printer), vars_(vars) {} + + template <typename T> + void Set(const TProtoStringType& key, const T& value) { + vars_[key] = ToString(value); + } + + void AddMap(const std::map<TProtoStringType, TProtoStringType>& vars) { + for (const auto& keyval : vars) vars_[keyval.first] = keyval.second; } - for (int i = 0; i < d->extension_count(); i++) { - func(d->extension(i)); - } - for (int i = 0; i < d->field_count(); i++) { - func(d->field(i)); - } -} - -template <class T> -void ForEachField(const FileDescriptor* d, T&& func) { - for (int i = 0; i < d->message_type_count(); i++) { - ForEachField(d->message_type(i), std::forward<T&&>(func)); - } - for (int i = 0; i < d->extension_count(); i++) { - func(d->extension(i)); - } -} - -void ListAllTypesForServices(const FileDescriptor* fd, - std::vector<const Descriptor*>* types); - -// Indicates whether we should use implicit weak fields for this file. -bool UsingImplicitWeakFields(const FileDescriptor* file, - const Options& options); - -// Indicates whether to treat this field as implicitly weak. -bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - -// Formatter is a functor class which acts as a closure around printer and -// the variable map. It's much like printer->Print except it supports both named -// variables that are substituted using a key value map and direct arguments. In -// the format string $1$, $2$, etc... are substituted for the first, second, ... -// direct argument respectively in the format call, it accepts both strings and -// integers. The implementation verifies all arguments are used and are "first" -// used in order of appearance in the argument list. For example, -// -// Format("return array[$1$];", 3) -> "return array[3];" -// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order) -// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;" -// -// The arguments can be used more than once like -// -// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") -> -// "array[3] = Bla; // Index = 3" -// -// If you use more arguments use the following style to help the reader, -// -// Format("int $1$() {\n" -// " array[$2$] = $3$;\n" -// " return $4$;" -// "}\n", -// funname, // 1 -// idx, // 2 -// varname, // 3 -// retval); // 4 -// -// but consider using named variables. Named variables like $foo$, with some -// identifier foo, are looked up in the map. One additional feature is that -// spaces are accepted between the '$' delimiters, $ foo$ will -// substiture to " bar" if foo stands for "bar", but in case it's empty -// will substitute to "". Hence, for example, -// -// Format(vars, "$dllexport $void fun();") -> "void fun();" -// "__declspec(export) void fun();" -// -// which is convenient to prevent double, leading or trailing spaces. -class PROTOC_EXPORT Formatter { - public: - explicit Formatter(io::Printer* printer) : printer_(printer) {} - Formatter(io::Printer* printer, - const std::map<TProtoStringType, TProtoStringType>& vars) - : printer_(printer), vars_(vars) {} - - template <typename T> - void Set(const TProtoStringType& key, const T& value) { - vars_[key] = ToString(value); - } - - void AddMap(const std::map<TProtoStringType, TProtoStringType>& vars) { - for (const auto& keyval : vars) vars_[keyval.first] = keyval.second; - } - - template <typename... Args> - void operator()(const char* format, const Args&... args) const { - printer_->FormatInternal({ToString(args)...}, vars_, format); - } - - void Indent() const { printer_->Indent(); } - void Outdent() const { printer_->Outdent(); } - io::Printer* printer() const { return printer_; } - - class PROTOC_EXPORT SaveState { - public: - explicit SaveState(Formatter* format) - : format_(format), vars_(format->vars_) {} - ~SaveState() { format_->vars_.swap(vars_); } - - private: - Formatter* format_; - std::map<TProtoStringType, TProtoStringType> vars_; - }; - - private: - io::Printer* printer_; - std::map<TProtoStringType, TProtoStringType> vars_; - - // Convenience overloads to accept different types as arguments. - static TProtoStringType ToString(const TProtoStringType& s) { return s; } - template <typename I, typename = typename std::enable_if< - std::is_integral<I>::value>::type> - static TProtoStringType ToString(I x) { - return StrCat(x); - } - static TProtoStringType ToString(strings::Hex x) { return StrCat(x); } - static TProtoStringType ToString(const FieldDescriptor* d) { return Payload(d); } - static TProtoStringType ToString(const Descriptor* d) { return Payload(d); } - static TProtoStringType ToString(const EnumDescriptor* d) { return Payload(d); } - static TProtoStringType ToString(const EnumValueDescriptor* d) { - return Payload(d); - } - static TProtoStringType ToString(const OneofDescriptor* d) { return Payload(d); } - - template <typename Descriptor> - static TProtoStringType Payload(const Descriptor* descriptor) { - std::vector<int> path; - descriptor->GetLocationPath(&path); - GeneratedCodeInfo::Annotation annotation; - for (int index : path) { - annotation.add_path(index); - } - annotation.set_source_file(descriptor->file()->name()); - return annotation.SerializeAsString(); - } + + template <typename... Args> + void operator()(const char* format, const Args&... args) const { + printer_->FormatInternal({ToString(args)...}, vars_, format); + } + + void Indent() const { printer_->Indent(); } + void Outdent() const { printer_->Outdent(); } + io::Printer* printer() const { return printer_; } + + class PROTOC_EXPORT SaveState { + public: + explicit SaveState(Formatter* format) + : format_(format), vars_(format->vars_) {} + ~SaveState() { format_->vars_.swap(vars_); } + + private: + Formatter* format_; + std::map<TProtoStringType, TProtoStringType> vars_; + }; + + private: + io::Printer* printer_; + std::map<TProtoStringType, TProtoStringType> vars_; + + // Convenience overloads to accept different types as arguments. + static TProtoStringType ToString(const TProtoStringType& s) { return s; } + template <typename I, typename = typename std::enable_if< + std::is_integral<I>::value>::type> + static TProtoStringType ToString(I x) { + return StrCat(x); + } + static TProtoStringType ToString(strings::Hex x) { return StrCat(x); } + static TProtoStringType ToString(const FieldDescriptor* d) { return Payload(d); } + static TProtoStringType ToString(const Descriptor* d) { return Payload(d); } + static TProtoStringType ToString(const EnumDescriptor* d) { return Payload(d); } + static TProtoStringType ToString(const EnumValueDescriptor* d) { + return Payload(d); + } + static TProtoStringType ToString(const OneofDescriptor* d) { return Payload(d); } + + template <typename Descriptor> + static TProtoStringType Payload(const Descriptor* descriptor) { + std::vector<int> path; + descriptor->GetLocationPath(&path); + GeneratedCodeInfo::Annotation annotation; + for (int index : path) { + annotation.add_path(index); + } + annotation.set_source_file(descriptor->file()->name()); + return annotation.SerializeAsString(); + } +}; + +template <class T> +void PrintFieldComment(const Formatter& format, const T* field) { + // Print the field's (or oneof's) proto-syntax definition as a comment. + // We don't want to print group bodies so we cut off after the first + // line. + DebugStringOptions options; + options.elide_group_body = true; + options.elide_oneof_body = true; + TProtoStringType def = field->DebugStringWithOptions(options); + format("// $1$\n", def.substr(0, def.find_first_of('\n'))); +} + +class PROTOC_EXPORT NamespaceOpener { + public: + explicit NamespaceOpener(const Formatter& format) + : printer_(format.printer()) {} + NamespaceOpener(const TProtoStringType& name, const Formatter& format) + : NamespaceOpener(format) { + ChangeTo(name); + } + ~NamespaceOpener() { ChangeTo(""); } + + void ChangeTo(const TProtoStringType& name) { + std::vector<TProtoStringType> new_stack_ = + Split(name, "::", true); + size_t len = std::min(name_stack_.size(), new_stack_.size()); + size_t common_idx = 0; + while (common_idx < len) { + if (name_stack_[common_idx] != new_stack_[common_idx]) break; + common_idx++; + } + for (auto it = name_stack_.crbegin(); + it != name_stack_.crend() - common_idx; ++it) { + if (*it == "PROTOBUF_NAMESPACE_ID") { + printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n"); + } else { + printer_->Print("} // namespace $ns$\n", "ns", *it); + } + } + name_stack_.swap(new_stack_); + for (size_t i = common_idx; i < name_stack_.size(); ++i) { + if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") { + printer_->Print("PROTOBUF_NAMESPACE_OPEN\n"); + } else { + printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]); + } + } + } + + private: + io::Printer* printer_; + std::vector<TProtoStringType> name_stack_; }; -template <class T> -void PrintFieldComment(const Formatter& format, const T* field) { - // Print the field's (or oneof's) proto-syntax definition as a comment. - // We don't want to print group bodies so we cut off after the first - // line. - DebugStringOptions options; - options.elide_group_body = true; - options.elide_oneof_body = true; - TProtoStringType def = field->DebugStringWithOptions(options); - format("// $1$\n", def.substr(0, def.find_first_of('\n'))); -} - -class PROTOC_EXPORT NamespaceOpener { - public: - explicit NamespaceOpener(const Formatter& format) - : printer_(format.printer()) {} - NamespaceOpener(const TProtoStringType& name, const Formatter& format) - : NamespaceOpener(format) { - ChangeTo(name); - } - ~NamespaceOpener() { ChangeTo(""); } - - void ChangeTo(const TProtoStringType& name) { - std::vector<TProtoStringType> new_stack_ = - Split(name, "::", true); - size_t len = std::min(name_stack_.size(), new_stack_.size()); - size_t common_idx = 0; - while (common_idx < len) { - if (name_stack_[common_idx] != new_stack_[common_idx]) break; - common_idx++; - } - for (auto it = name_stack_.crbegin(); - it != name_stack_.crend() - common_idx; ++it) { - if (*it == "PROTOBUF_NAMESPACE_ID") { - printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n"); - } else { - printer_->Print("} // namespace $ns$\n", "ns", *it); - } - } - name_stack_.swap(new_stack_); - for (size_t i = common_idx; i < name_stack_.size(); ++i) { - if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") { - printer_->Print("PROTOBUF_NAMESPACE_OPEN\n"); - } else { - printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]); - } - } - } - - private: - io::Printer* printer_; - std::vector<TProtoStringType> name_stack_; -}; - -enum class Utf8CheckMode { - kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields. - kVerify = 1, // Only log an error but parsing will succeed. - kNone = 2, // No UTF-8 check. -}; - -Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, - const Options& options); - -void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, - const Options& options, bool for_parse, - const char* parameters, - const Formatter& format); - -void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, - const Options& options, bool for_parse, - const char* parameters, - const Formatter& format); - -template <typename T> -struct FieldRangeImpl { - struct Iterator { - using iterator_category = std::forward_iterator_tag; - using value_type = const FieldDescriptor*; - using difference_type = int; - - value_type operator*() { return descriptor->field(idx); } - - friend bool operator==(const Iterator& a, const Iterator& b) { - GOOGLE_DCHECK(a.descriptor == b.descriptor); - return a.idx == b.idx; - } - friend bool operator!=(const Iterator& a, const Iterator& b) { - return !(a == b); - } - - Iterator& operator++() { - idx++; - return *this; - } - - int idx; - const T* descriptor; - }; - - Iterator begin() const { return {0, descriptor}; } - Iterator end() const { return {descriptor->field_count(), descriptor}; } - - const T* descriptor; -}; - -template <typename T> -FieldRangeImpl<T> FieldRange(const T* desc) { - return {desc}; -} - -struct OneOfRangeImpl { - struct Iterator { - using iterator_category = std::forward_iterator_tag; - using value_type = const OneofDescriptor*; - using difference_type = int; - - value_type operator*() { return descriptor->oneof_decl(idx); } - - friend bool operator==(const Iterator& a, const Iterator& b) { - GOOGLE_DCHECK(a.descriptor == b.descriptor); - return a.idx == b.idx; - } - friend bool operator!=(const Iterator& a, const Iterator& b) { - return !(a == b); - } - - Iterator& operator++() { - idx++; - return *this; - } - - int idx; - const Descriptor* descriptor; - }; - - Iterator begin() const { return {0, descriptor}; } - Iterator end() const { - return {descriptor->real_oneof_decl_count(), descriptor}; - } - - const Descriptor* descriptor; -}; - -inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; } - -PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename); - -inline bool EnableMessageOwnedArena(const Descriptor* /* desc */ ) { return false; } - +enum class Utf8CheckMode { + kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields. + kVerify = 1, // Only log an error but parsing will succeed. + kNone = 2, // No UTF-8 check. +}; + +Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, + const Options& options); + +void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); + +void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); + +template <typename T> +struct FieldRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const FieldDescriptor*; + using difference_type = int; + + value_type operator*() { return descriptor->field(idx); } + + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + + Iterator& operator++() { + idx++; + return *this; + } + + int idx; + const T* descriptor; + }; + + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { return {descriptor->field_count(), descriptor}; } + + const T* descriptor; +}; + +template <typename T> +FieldRangeImpl<T> FieldRange(const T* desc) { + return {desc}; +} + +struct OneOfRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const OneofDescriptor*; + using difference_type = int; + + value_type operator*() { return descriptor->oneof_decl(idx); } + + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + + Iterator& operator++() { + idx++; + return *this; + } + + int idx; + const Descriptor* descriptor; + }; + + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { + return {descriptor->real_oneof_decl_count(), descriptor}; + } + + const Descriptor* descriptor; +}; + +inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; } + +PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename); + +inline bool EnableMessageOwnedArena(const Descriptor* /* desc */ ) { return false; } + } // namespace cpp } // namespace compiler } // namespace protobuf -} // namespace google +} // namespace google + +#include <google/protobuf/port_undef.inc> -#include <google/protobuf/port_undef.inc> - #endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ |