// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: [email protected] (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // This header is logically internal, but is made public because it is used // from protocol-compiler-generated code, which may reside in other components. #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__ #define GOOGLE_PROTOBUF_EXTENSION_SET_H__ #include <algorithm> #include <cassert> #include <map> #include <string> #include <utility> #include <vector> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/port.h> #include <google/protobuf/parse_context.h> #include <google/protobuf/repeated_field.h> #include <google/protobuf/wire_format_lite.h> // clang-format off #include <google/protobuf/port_def.inc> // Must be last // clang-format on #ifdef SWIG #error "You cannot SWIG proto headers" #endif namespace google { namespace protobuf { class Arena; class Descriptor; // descriptor.h class FieldDescriptor; // descriptor.h class DescriptorPool; // descriptor.h class MessageLite; // message_lite.h class Message; // message.h class MessageFactory; // message.h class Reflection; // message.h class UnknownFieldSet; // unknown_field_set.h namespace internal { class FieldSkipper; // wire_format_lite.h enum class LazyVerifyOption; } // namespace internal } // namespace protobuf } // namespace google namespace google { namespace protobuf { namespace internal { class InternalMetadata; // Used to store values of type WireFormatLite::FieldType without having to // #include wire_format_lite.h. Also, ensures that we use only one byte to // store these values, which is important to keep the layout of // ExtensionSet::Extension small. FieldType; // A function which, given an integer value, returns true if the number // matches one of the defined values for the corresponding enum type. This // is used with RegisterEnumExtension, below. EnumValidityFunc; // Version of the above which takes an argument. This is needed to deal with // extensions that are not compiled in. EnumValidityFuncWithArg; // Information about a registered extension. struct ExtensionInfo { … }; // An ExtensionFinder is an object which looks up extension definitions. It // must implement this method: // // bool Find(int number, ExtensionInfo* output); // GeneratedExtensionFinder is an ExtensionFinder which finds extensions // defined in .proto files which have been compiled into the binary. class PROTOBUF_EXPORT GeneratedExtensionFinder { … }; // Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for // finding extensions from a DescriptorPool. // This is an internal helper class intended for use within the protocol buffer // library and generated classes. Clients should not use it directly. Instead, // use the generated accessors such as GetExtension() of the class being // extended. // // This class manages extensions for a protocol message object. The // message's HasExtension(), GetExtension(), MutableExtension(), and // ClearExtension() methods are just thin wrappers around the embedded // ExtensionSet. When parsing, if a tag number is encountered which is // inside one of the message type's extension ranges, the tag is passed // off to the ExtensionSet for parsing. Etc. class PROTOBUF_EXPORT ExtensionSet { … }; constexpr ExtensionSet::ExtensionSet() : … { … } // These are just for convenience... inline void ExtensionSet::SetString(int number, FieldType type, std::string value, const FieldDescriptor* descriptor) { … } inline void ExtensionSet::SetRepeatedString(int number, int index, std::string value) { … } inline void ExtensionSet::AddString(int number, FieldType type, std::string value, const FieldDescriptor* descriptor) { … } // =================================================================== // Glue for generated extension accessors // ------------------------------------------------------------------- // Template magic // First we have a set of classes representing "type traits" for different // field types. A type traits class knows how to implement basic accessors // for extensions of a particular type given an ExtensionSet. The signature // for a type traits class looks like this: // // class TypeTraits { // public: // typedef ? ConstType; // typedef ? MutableType; // // TypeTraits for singular fields and repeated fields will define the // // symbol "Singular" or "Repeated" respectively. These two symbols will // // be used in extension accessors to distinguish between singular // // extensions and repeated extensions. If the TypeTraits for the passed // // in extension doesn't have the expected symbol defined, it means the // // user is passing a repeated extension to a singular accessor, or the // // opposite. In that case the C++ compiler will generate an error // // message "no matching member function" to inform the user. // typedef ? Singular // typedef ? Repeated // // static inline ConstType Get(int number, const ExtensionSet& set); // static inline void Set(int number, ConstType value, ExtensionSet* set); // static inline MutableType Mutable(int number, ExtensionSet* set); // // // Variants for repeated fields. // static inline ConstType Get(int number, const ExtensionSet& set, // int index); // static inline void Set(int number, int index, // ConstType value, ExtensionSet* set); // static inline MutableType Mutable(int number, int index, // ExtensionSet* set); // static inline void Add(int number, ConstType value, ExtensionSet* set); // static inline MutableType Add(int number, ExtensionSet* set); // This is used by the ExtensionIdentifier constructor to register // the extension at dynamic initialization. // template <typename ExtendeeT> // static void Register(int number, FieldType type, bool is_packed); // }; // // Not all of these methods make sense for all field types. For example, the // "Mutable" methods only make sense for strings and messages, and the // repeated methods only make sense for repeated types. So, each type // traits class implements only the set of methods from this signature that it // actually supports. This will cause a compiler error if the user tries to // access an extension using a method that doesn't make sense for its type. // For example, if "foo" is an extension of type "optional int32", then if you // try to write code like: // my_message.MutableExtension(foo) // you will get a compile error because PrimitiveTypeTraits<int32_t> does not // have a "Mutable()" method. // ------------------------------------------------------------------- // PrimitiveTypeTraits // Since the ExtensionSet has different methods for each primitive type, // we must explicitly define the methods of the type traits class for each // known type. template <typename Type> class PrimitiveTypeTraits { … }; template <typename Type> class RepeatedPrimitiveTypeTraits { … }; class PROTOBUF_EXPORT RepeatedPrimitiveDefaults { … }; #define PROTOBUF_DEFINE_PRIMITIVE_TYPE … PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE PROTOBUF_DEFINE_PRIMITIVE_TYPE #undef PROTOBUF_DEFINE_PRIMITIVE_TYPE // ------------------------------------------------------------------- // StringTypeTraits // Strings support both Set() and Mutable(). class PROTOBUF_EXPORT StringTypeTraits { … }; class PROTOBUF_EXPORT RepeatedStringTypeTraits { … }; // ------------------------------------------------------------------- // EnumTypeTraits // ExtensionSet represents enums using integers internally, so we have to // static_cast around. template <typename Type, bool IsValid(int)> class EnumTypeTraits { … }; template <typename Type, bool IsValid(int)> class RepeatedEnumTypeTraits { … }; // ------------------------------------------------------------------- // MessageTypeTraits // ExtensionSet guarantees that when manipulating extensions with message // types, the implementation used will be the compiled-in class representing // that type. So, we can static_cast down to the exact type we expect. template <typename Type> class MessageTypeTraits { … }; // Used by WireFormatVerify to extract the verify function from the registry. LazyEagerVerifyFnType FindExtensionLazyEagerVerifyFn( const MessageLite* extendee, int number); // forward declaration. class RepeatedMessageGenericTypeTraits; template <typename Type> class RepeatedMessageTypeTraits { … }; template <typename Type> inline const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType* RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() { … } // ------------------------------------------------------------------- // ExtensionIdentifier // This is the type of actual extension objects. E.g. if you have: // extend Foo { // optional int32 bar = 1234; // } // then "bar" will be defined in C++ as: // ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32_t>, 5, false> bar(1234); // // Note that we could, in theory, supply the field number as a template // parameter, and thus make an instance of ExtensionIdentifier have no // actual contents. However, if we did that, then using an extension // identifier would not necessarily cause the compiler to output any sort // of reference to any symbol defined in the extension's .pb.o file. Some // linkers will actually drop object files that are not explicitly referenced, // but that would be bad because it would cause this extension to not be // registered at static initialization, and therefore using it would crash. template <typename ExtendeeType, typename TypeTraitsType, FieldType field_type, bool is_packed> class ExtensionIdentifier { … }; // ------------------------------------------------------------------- // Generated accessors // Used to retrieve a lazy extension, may return nullptr in some environments. extern PROTOBUF_ATTRIBUTE_WEAK ExtensionSet::LazyMessageExtension* MaybeCreateLazyExtension(Arena* arena); } // namespace internal // Call this function to ensure that this extensions's reflection is linked into // the binary: // // google::protobuf::LinkExtensionReflection(Foo::my_extension); // // This will ensure that the following lookup will succeed: // // DescriptorPool::generated_pool()->FindExtensionByName("Foo.my_extension"); // // This is often relevant for parsing extensions in text mode. // // As a side-effect, it will also guarantee that anything else from the same // .proto file will also be available for lookup in the generated pool. // // This function does not actually register the extension, so it does not need // to be called before the lookup. However it does need to occur in a function // that cannot be stripped from the binary (ie. it must be reachable from main). // // Best practice is to call this function as close as possible to where the // reflection is actually needed. This function is very cheap to call, so you // should not need to worry about its runtime overhead except in tight loops (on // x86-64 it compiles into two "mov" instructions). template <typename ExtendeeType, typename TypeTraitsType, internal::FieldType field_type, bool is_packed> void LinkExtensionReflection( const google::protobuf::internal::ExtensionIdentifier< ExtendeeType, TypeTraitsType, field_type, is_packed>& extension) { … } } // namespace protobuf } // namespace google #include <google/protobuf/port_undef.inc> #endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__