diff options
author | Adam Cozzette <acozzette@google.com> | 2017-04-27 14:55:53 -0700 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2017-04-27 14:55:53 -0700 |
commit | 9053033a5076f82cf18b823c31f352e95e5bfd8d (patch) | |
tree | 1d2a2611f56e786d7c3e40b8fd1b2e3d9aff9025 /src/google/protobuf/descriptor.h | |
parent | 067b1eec3bf852abaad0844999461baff8a5fdc8 (diff) | |
parent | a6189acd18b00611c1dc7042299ad75486f08a1a (diff) | |
download | protobuf-9053033a5076f82cf18b823c31f352e95e5bfd8d.tar.gz protobuf-9053033a5076f82cf18b823c31f352e95e5bfd8d.tar.bz2 protobuf-9053033a5076f82cf18b823c31f352e95e5bfd8d.zip |
Merge remote-tracking branch 'remotes/google/3.3.x' into merge-3.3-to-master
Diffstat (limited to 'src/google/protobuf/descriptor.h')
-rw-r--r-- | src/google/protobuf/descriptor.h | 153 |
1 files changed, 129 insertions, 24 deletions
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index cc099693..7aea7344 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -63,6 +63,7 @@ #include <vector> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/stubs/once.h> // TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. #ifdef TYPE_BOOL @@ -110,6 +111,7 @@ class Message; // Defined in descriptor.cc class DescriptorBuilder; class FileDescriptorTables; +struct Symbol; // Defined in unknown_field_set.h. class UnknownField; @@ -165,6 +167,55 @@ struct DebugStringOptions { elide_oneof_body(false) {} }; +// A class to handle the simplest cases of a lazily linked descriptor +// for a message type that isn't built at the time of cross linking, +// which is needed when a pool has lazily_build_dependencies_ set. +// Must be instantiated as mutable in a descriptor. +namespace internal { +class LIBPROTOBUF_EXPORT LazyDescriptor { + public: + // Init function to be called at init time of a descriptor containing + // a LazyDescriptor. + void Init() { + descriptor_ = NULL; + name_ = NULL; + once_ = NULL; + file_ = NULL; + } + + // Sets the value of the descriptor if it is known during the descriptor + // building process. Not thread safe, should only be called during the + // descriptor build process. Should not be called after SetLazy has been + // called. + void Set(const Descriptor* descriptor); + + // Sets the information needed to lazily cross link the descriptor at a later + // time, SetLazy is not thread safe, should be called only once at descriptor + // build time if the symbol wasn't found and building of the file containing + // that type is delayed because lazily_build_dependencies_ is set on the pool. + // Should not be called after Set() has been called. + void SetLazy(const string& name, const FileDescriptor* file); + + // Returns the current value of the descriptor, thread-safe. If SetLazy(...) + // has been called, will do a one-time cross link of the type specified, + // building the descriptor file that contains the type if necessary. + inline const Descriptor* Get() { + Once(); + return descriptor_; + } + + private: + static void OnceStatic(LazyDescriptor* lazy); + void OnceInternal(); + void Once(); + + const Descriptor* descriptor_; + const string* name_; + GoogleOnceDynamic* once_; + const FileDescriptor* file_; +}; +} // namespace internal + // Describes a type of protocol message, or a particular group within a // message. To obtain the Descriptor for a given message object, call // Message::GetDescriptor(). Generated message classes also have a @@ -417,6 +468,7 @@ class LIBPROTOBUF_EXPORT Descriptor { // Must be constructed using DescriptorPool. Descriptor() {} friend class DescriptorBuilder; + friend class DescriptorPool; friend class EnumDescriptor; friend class FieldDescriptor; friend class OneofDescriptor; @@ -692,16 +744,21 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { const string* json_name_; const FileDescriptor* file_; int number_; - Type type_; + GoogleOnceDynamic* type_once_; + static void TypeOnceInit(const FieldDescriptor* to_init); + void InternalTypeOnceInit() const; + mutable Type type_; Label label_; bool is_extension_; int index_in_oneof_; const Descriptor* containing_type_; const OneofDescriptor* containing_oneof_; const Descriptor* extension_scope_; - const Descriptor* message_type_; - const EnumDescriptor* enum_type_; + mutable const Descriptor* message_type_; + mutable const EnumDescriptor* enum_type_; const FieldOptions* options_; + const string* type_name_; + const string* default_value_enum_name_; // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in // descriptor.cc and update them to initialize the field. @@ -716,7 +773,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { double default_value_double_; bool default_value_bool_; - const EnumValueDescriptor* default_value_enum_; + mutable const EnumValueDescriptor* default_value_enum_; const string* default_value_string_; }; @@ -918,6 +975,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { friend class FieldDescriptor; friend class EnumValueDescriptor; friend class FileDescriptor; + friend class DescriptorPool; friend class internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor); }; @@ -994,6 +1052,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { EnumValueDescriptor() {} friend class DescriptorBuilder; friend class EnumDescriptor; + friend class DescriptorPool; friend class FileDescriptorTables; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor); }; @@ -1144,8 +1203,8 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { const string* name_; const string* full_name_; const ServiceDescriptor* service_; - const Descriptor* input_type_; - const Descriptor* output_type_; + mutable internal::LazyDescriptor input_type_; + mutable internal::LazyDescriptor output_type_; const MethodOptions* options_; bool client_streaming_; bool server_streaming_; @@ -1302,7 +1361,11 @@ class LIBPROTOBUF_EXPORT FileDescriptor { const string* package_; const DescriptorPool* pool_; int dependency_count_; - const FileDescriptor** dependencies_; + mutable const FileDescriptor** dependencies_; + const string** dependencies_names_; + GoogleOnceDynamic* dependencies_once_; + static void DependenciesOnceInit(const FileDescriptor* to_init); + void InternalDependenciesOnceInit() const; int public_dependency_count_; int* public_dependencies_; int weak_dependency_count_; @@ -1321,14 +1384,22 @@ class LIBPROTOBUF_EXPORT FileDescriptor { const FileDescriptorTables* tables_; const SourceCodeInfo* source_code_info_; + + // Indicates the FileDescriptor is completed building. Used to verify + // that type accessor functions that can possibly build a dependent file + // aren't called during the process of building the file. + bool finished_building_; + // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in // descriptor.cc and update them to initialize the field. FileDescriptor() {} friend class DescriptorBuilder; + friend class DescriptorPool; friend class Descriptor; friend class FieldDescriptor; + friend class internal::LazyDescriptor; friend class OneofDescriptor; friend class EnumDescriptor; friend class EnumValueDescriptor; @@ -1559,6 +1630,9 @@ class LIBPROTOBUF_EXPORT DescriptorPool { static void InternalAddGeneratedFile( const void* encoded_file_descriptor, int size); + // Disallow [enforce_utf8 = false] in .proto files. + void DisallowEnforceUtf8() { disallow_enforce_utf8_ = true; } + // For internal use only: Gets a non-const pointer to the generated pool. // This is called at static-initialization time only, so thread-safety is @@ -1571,6 +1645,21 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // which it did not officially declare as dependencies. void InternalDontEnforceDependencies(); + // For internal use only: Enables lazy building of dependencies of a file. + // Delay the building of dependencies of a file descriptor until absolutely + // necessary, like when message_type() is called on a field that is defined + // in that dependency's file. This will cause functional issues if a proto + // or one of it's dependencies has errors. Should only be enabled for the + // generated_pool_ (because no descriptor build errors are guaranteed by + // the compilation generation process), testing, or if a lack of descriptor + // build errors can be guaranteed for a pool. + void InternalSetLazilyBuildDependencies() { + lazily_build_dependencies_ = true; + // This needs to be set when lazily building dependencies, as it breaks + // dependency checking. + InternalDontEnforceDependencies(); + } + // For internal use only. void internal_set_underlay(const DescriptorPool* underlay) { underlay_ = underlay; @@ -1589,10 +1678,13 @@ class LIBPROTOBUF_EXPORT DescriptorPool { private: friend class Descriptor; + friend class internal::LazyDescriptor; friend class FieldDescriptor; friend class EnumDescriptor; friend class ServiceDescriptor; + friend class MethodDescriptor; friend class FileDescriptor; + friend class StreamDescriptor; friend class DescriptorBuilder; friend class FileDescriptorTables; @@ -1616,6 +1708,28 @@ class LIBPROTOBUF_EXPORT DescriptorPool { const FileDescriptor* BuildFileFromDatabase( const FileDescriptorProto& proto) const; + // Helper for when lazily_build_dependencies_ is set, can look up a symbol + // after the file's descriptor is built, and can build the file where that + // symbol is defined if necessary. Will create a placeholder if the type + // doesn't exist in the fallback database, or the file doesn't build + // successfully. + Symbol CrossLinkOnDemandHelper(const string& name, bool expecting_enum) const; + + // Create a placeholder FileDescriptor of the specified name + FileDescriptor* NewPlaceholderFile(const string& name) const; + FileDescriptor* NewPlaceholderFileWithMutexHeld(const string& name) const; + + enum PlaceholderType { + PLACEHOLDER_MESSAGE, + PLACEHOLDER_ENUM, + PLACEHOLDER_EXTENDABLE_MESSAGE + }; + // Create a placeholder Descriptor of the specified name + Symbol NewPlaceholder(const string& name, + PlaceholderType placeholder_type) const; + Symbol NewPlaceholderWithMutexHeld(const string& name, + PlaceholderType placeholder_type) const; + // If fallback_database_ is NULL, this is NULL. Otherwise, this is a mutex // which must be locked while accessing tables_. Mutex* mutex_; @@ -1631,9 +1745,11 @@ class LIBPROTOBUF_EXPORT DescriptorPool { google::protobuf::scoped_ptr<Tables> tables_; bool enforce_dependencies_; + bool lazily_build_dependencies_; bool allow_unknown_; bool enforce_weak_; std::set<string> unused_import_track_files_; + bool disallow_enforce_utf8_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); }; @@ -1693,15 +1809,12 @@ PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, number, int) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, type, FieldDescriptor::Type) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, label, FieldDescriptor::Label) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_oneof, const OneofDescriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, index_in_oneof, int) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_json_name, bool) @@ -1712,8 +1825,6 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint64, uint64) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float , float ) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_double, double) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool , bool ) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_enum, - const EnumValueDescriptor*) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, name) @@ -1749,8 +1860,6 @@ PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions) PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*) -PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*) -PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, client_streaming, bool) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, server_streaming, bool) @@ -1824,7 +1933,7 @@ inline bool FieldDescriptor::is_packable() const { // in the parent's array of children. inline int FieldDescriptor::index() const { if (!is_extension_) { - return static_cast<int>(this - containing_type_->fields_); + return static_cast<int>(this - containing_type()->fields_); } else if (extension_scope_ != NULL) { return static_cast<int>(this - extension_scope_->extensions_); } else { @@ -1865,15 +1974,15 @@ inline int MethodDescriptor::index() const { } inline const char* FieldDescriptor::type_name() const { - return kTypeToName[type_]; + return kTypeToName[type()]; } inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const { - return kTypeToCppTypeMap[type_]; + return kTypeToCppTypeMap[type()]; } inline const char* FieldDescriptor::cpp_type_name() const { - return kCppTypeToName[kTypeToCppTypeMap[type_]]; + return kCppTypeToName[kTypeToCppTypeMap[type()]]; } inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) { @@ -1895,18 +2004,14 @@ inline bool FieldDescriptor::IsTypePackable(Type field_type) { field_type != FieldDescriptor::TYPE_BYTES); } -inline const FileDescriptor* FileDescriptor::dependency(int index) const { - return dependencies_[index]; -} - inline const FileDescriptor* FileDescriptor::public_dependency( int index) const { - return dependencies_[public_dependencies_[index]]; + return dependency(public_dependencies_[index]); } inline const FileDescriptor* FileDescriptor::weak_dependency( int index) const { - return dependencies_[weak_dependencies_[index]]; + return dependency(weak_dependencies_[index]); } inline FileDescriptor::Syntax FileDescriptor::syntax() const { |