| // Protocol Buffers - Google's data interchange format |
| // Copyright 2008 Google Inc. |
| // http://code.google.com/p/protobuf/ |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Author: kenton@google.com (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 <vector> |
| #include <stack> |
| #include <map> |
| #include <utility> |
| #include <string> |
| |
| #include <google/protobuf/message.h> |
| |
| namespace google { |
| namespace protobuf { |
| class Descriptor; // descriptor.h |
| class FieldDescriptor; // descriptor.h |
| class DescriptorPool; // descriptor.h |
| class Message; // message.h |
| class MessageFactory; // message.h |
| namespace io { |
| class CodedInputStream; // coded_stream.h |
| class CodedOutputStream; // coded_stream.h |
| } |
| template <typename Element> class RepeatedField; // repeated_field.h |
| template <typename Element> class RepeatedPtrField; // repeated_field.h |
| } |
| |
| namespace protobuf { |
| namespace internal { |
| |
| // 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 LIBPROTOBUF_EXPORT ExtensionSet { |
| public: |
| // Construct an ExtensionSet. |
| // extendee: Descriptor for the type being extended. |
| // pool: DescriptorPool to search for extension definitions. |
| // factory: MessageFactory used to construct implementations of messages |
| // for extensions with message type. This factory must be able |
| // to construct any message type found in "pool". |
| // All three objects remain property of the caller and must outlive the |
| // ExtensionSet. |
| ExtensionSet(const Descriptor* extendee, |
| const DescriptorPool* pool, |
| MessageFactory* factory); |
| |
| ~ExtensionSet(); |
| |
| // Search for a known (compiled-in) extension of this type by name or number. |
| // Returns NULL if no extension is known. |
| const FieldDescriptor* FindKnownExtensionByName(const string& name) const; |
| const FieldDescriptor* FindKnownExtensionByNumber(int number) const; |
| |
| // Add all fields which are currently present to the given vector. This |
| // is useful to implement Message::Reflection::ListFields(). |
| void AppendToList(vector<const FieldDescriptor*>* output) const; |
| |
| // ================================================================= |
| // Accessors |
| // |
| // Generated message classes include type-safe templated wrappers around |
| // these methods. Generally you should use those rather than call these |
| // directly, unless you are doing low-level memory management. |
| // |
| // When calling any of these accessors, the extension number requested |
| // MUST exist in the DescriptorPool provided to the constructor. Otheriwse, |
| // the method will fail an assert. Normally, though, you would not call |
| // these directly; you would either call the generated accessors of your |
| // message class (e.g. GetExtension()) or you would call the accessors |
| // of the reflection interface. In both cases, it is impossible to |
| // trigger this assert failure: the generated accessors only accept |
| // linked-in extension types as parameters, while the Reflection interface |
| // requires you to provide the FieldDescriptor describing the extension. |
| // |
| // When calling any of these accessors, a protocol-compiler-generated |
| // implementation of the extension corresponding to the number MUST |
| // be linked in, and the FieldDescriptor used to refer to it MUST be |
| // the one generated by that linked-in code. Otherwise, the method will |
| // die on an assert failure. The message objects returned by the message |
| // accessors are guaranteed to be of the correct linked-in type. |
| // |
| // These methods pretty much match Message::Reflection except that: |
| // - They're not virtual. |
| // - They identify fields by number rather than FieldDescriptors. |
| // - They identify enum values using integers rather than descriptors. |
| // - Strings provide Mutable() in addition to Set() accessors. |
| |
| bool Has(int number) const; |
| int ExtensionSize(int number) const; // Size of a repeated extension. |
| void ClearExtension(int number); |
| |
| // singular fields ------------------------------------------------- |
| |
| int32 GetInt32 (int number) const; |
| int64 GetInt64 (int number) const; |
| uint32 GetUInt32(int number) const; |
| uint64 GetUInt64(int number) const; |
| float GetFloat (int number) const; |
| double GetDouble(int number) const; |
| bool GetBool (int number) const; |
| int GetEnum (int number) const; |
| const string & GetString (int number) const; |
| const Message& GetMessage(int number) const; |
| |
| void SetInt32 (int number, int32 value); |
| void SetInt64 (int number, int64 value); |
| void SetUInt32(int number, uint32 value); |
| void SetUInt64(int number, uint64 value); |
| void SetFloat (int number, float value); |
| void SetDouble(int number, double value); |
| void SetBool (int number, bool value); |
| void SetEnum (int number, int value); |
| void SetString(int number, const string& value); |
| string * MutableString (int number); |
| Message* MutableMessage(int number); |
| |
| // repeated fields ------------------------------------------------- |
| |
| int32 GetRepeatedInt32 (int number, int index) const; |
| int64 GetRepeatedInt64 (int number, int index) const; |
| uint32 GetRepeatedUInt32(int number, int index) const; |
| uint64 GetRepeatedUInt64(int number, int index) const; |
| float GetRepeatedFloat (int number, int index) const; |
| double GetRepeatedDouble(int number, int index) const; |
| bool GetRepeatedBool (int number, int index) const; |
| int GetRepeatedEnum (int number, int index) const; |
| const string & GetRepeatedString (int number, int index) const; |
| const Message& GetRepeatedMessage(int number, int index) const; |
| |
| void SetRepeatedInt32 (int number, int index, int32 value); |
| void SetRepeatedInt64 (int number, int index, int64 value); |
| void SetRepeatedUInt32(int number, int index, uint32 value); |
| void SetRepeatedUInt64(int number, int index, uint64 value); |
| void SetRepeatedFloat (int number, int index, float value); |
| void SetRepeatedDouble(int number, int index, double value); |
| void SetRepeatedBool (int number, int index, bool value); |
| void SetRepeatedEnum (int number, int index, int value); |
| void SetRepeatedString(int number, int index, const string& value); |
| string * MutableRepeatedString (int number, int index); |
| Message* MutableRepeatedMessage(int number, int index); |
| |
| void AddInt32 (int number, int32 value); |
| void AddInt64 (int number, int64 value); |
| void AddUInt32(int number, uint32 value); |
| void AddUInt64(int number, uint64 value); |
| void AddFloat (int number, float value); |
| void AddDouble(int number, double value); |
| void AddBool (int number, bool value); |
| void AddEnum (int number, int value); |
| void AddString(int number, const string& value); |
| string * AddString (int number); |
| Message* AddMessage(int number); |
| |
| // ----------------------------------------------------------------- |
| // TODO(kenton): Hardcore memory management accessors |
| |
| // ================================================================= |
| // convenience methods for implementing methods of Message |
| // |
| // These could all be implemented in terms of the other methods of this |
| // class, but providing them here helps keep the generated code size down. |
| |
| void Clear(); |
| void MergeFrom(const ExtensionSet& other); |
| bool IsInitialized() const; |
| |
| // These parsing and serialization functions all want a pointer to the |
| // reflection interface because they hand off the actual work to WireFormat, |
| // which works in terms of a reflection interface. Yes, this means there |
| // are some redundant virtual function calls that end up being made, but |
| // it probably doesn't matter much in practice, and the alternative would |
| // involve reproducing a lot of WireFormat's functionality. |
| |
| // Parses a single extension from the input. The input should start out |
| // positioned immediately after the tag. |
| bool ParseField(uint32 tag, io::CodedInputStream* input, |
| Message::Reflection* reflection); |
| |
| // Write all extension fields with field numbers in the range |
| // [start_field_number, end_field_number) |
| // to the output stream, using the cached sizes computed when ByteSize() was |
| // last called. Note that the range bounds are inclusive-exclusive. |
| bool SerializeWithCachedSizes(int start_field_number, |
| int end_field_number, |
| const Message::Reflection* reflection, |
| io::CodedOutputStream* output) const; |
| |
| // Returns the total serialized size of all the extensions. |
| int ByteSize(const Message::Reflection* reflection) const; |
| |
| private: |
| // Like FindKnownExtension(), but GOOGLE_CHECK-fail if not found. |
| const FieldDescriptor* FindKnownExtensionOrDie(int number) const; |
| |
| // Get the prototype for the message. |
| const Message* GetPrototype(const Descriptor* message_type) const; |
| |
| struct Extension { |
| union { |
| int32 int32_value; |
| int64 int64_value; |
| uint32 uint32_value; |
| uint64 uint64_value; |
| float float_value; |
| double double_value; |
| bool bool_value; |
| int enum_value; |
| string* string_value; |
| Message* message_value; |
| |
| RepeatedField <int32 >* repeated_int32_value; |
| RepeatedField <int64 >* repeated_int64_value; |
| RepeatedField <uint32 >* repeated_uint32_value; |
| RepeatedField <uint64 >* repeated_uint64_value; |
| RepeatedField <float >* repeated_float_value; |
| RepeatedField <double >* repeated_double_value; |
| RepeatedField <bool >* repeated_bool_value; |
| RepeatedField <int >* repeated_enum_value; |
| RepeatedPtrField<string >* repeated_string_value; |
| RepeatedPtrField<Message>* repeated_message_value; |
| }; |
| |
| const FieldDescriptor* descriptor; |
| |
| // For singular types, indicates if the extension is "cleared". This |
| // happens when an extension is set and then later cleared by the caller. |
| // We want to keep the Extension object around for reuse, so instead of |
| // removing it from the map, we just set is_cleared = true. This has no |
| // meaning for repeated types; for those, the size of the RepeatedField |
| // simply becomes zero when cleared. |
| bool is_cleared; |
| |
| Extension(): descriptor(NULL), is_cleared(false) {} |
| |
| // Some helper methods for operations on a single Extension. |
| bool SerializeFieldWithCachedSizes( |
| const Message::Reflection* reflection, |
| io::CodedOutputStream* output) const; |
| int64 ByteSize(const Message::Reflection* reflection) const; |
| void Clear(); |
| int GetSize() const; |
| void Free(); |
| }; |
| |
| // The Extension struct is small enough to be passed by value, so we use it |
| // directly as the value type in the map rather than use pointers. We use |
| // a map rather than hash_map here because we expect most ExtensionSets will |
| // only contain a small number of extensions whereas hash_map is optimized |
| // for 100 elements or more. Also, we want AppendToList() to order fields |
| // by field number. |
| map<int, Extension> extensions_; |
| const Descriptor* extendee_; |
| const DescriptorPool* descriptor_pool_; |
| MessageFactory* message_factory_; |
| |
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); |
| }; |
| |
| // These are just for convenience... |
| inline void ExtensionSet::SetString(int number, const string& value) { |
| MutableString(number)->assign(value); |
| } |
| inline void ExtensionSet::SetRepeatedString(int number, int index, |
| const string& value) { |
| MutableRepeatedString(number, index)->assign(value); |
| } |
| inline void ExtensionSet::AddString(int number, const string& value) { |
| AddString(number)->assign(value); |
| } |
| |
| // =================================================================== |
| // Implementation details |
| // |
| // DO NOT DEPEND ON ANYTHING BELOW THIS POINT. This is for use from |
| // generated code only. |
| |
| // ------------------------------------------------------------------- |
| // 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; |
| // |
| // 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); |
| // }; |
| // |
| // 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> 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 { |
| public: |
| typedef Type ConstType; |
| |
| static inline ConstType Get(int number, const ExtensionSet& set); |
| static inline void Set(int number, ConstType value, ExtensionSet* set); |
| }; |
| |
| template <typename Type> |
| class RepeatedPrimitiveTypeTraits { |
| public: |
| typedef Type ConstType; |
| |
| static inline Type Get(int number, const ExtensionSet& set, int index); |
| static inline void Set(int number, int index, Type value, ExtensionSet* set); |
| static inline void Add(int number, Type value, ExtensionSet* set); |
| }; |
| |
| #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ |
| template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \ |
| int number, const ExtensionSet& set) { \ |
| return set.Get##METHOD(number); \ |
| } \ |
| template<> inline void PrimitiveTypeTraits<TYPE>::Set( \ |
| int number, ConstType value, ExtensionSet* set) { \ |
| set->Set##METHOD(number, value); \ |
| } \ |
| \ |
| template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \ |
| int number, const ExtensionSet& set, int index) { \ |
| return set.GetRepeated##METHOD(number, index); \ |
| } \ |
| template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \ |
| int number, int index, ConstType value, ExtensionSet* set) { \ |
| set->SetRepeated##METHOD(number, index, value); \ |
| } \ |
| template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \ |
| int number, ConstType value, ExtensionSet* set) { \ |
| set->Add##METHOD(number, value); \ |
| } |
| |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double) |
| PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool) |
| |
| #undef PROTOBUF_DEFINE_PRIMITIVE_TYPE |
| |
| // ------------------------------------------------------------------- |
| // StringTypeTraits |
| |
| // Strings support both Set() and Mutable(). |
| class LIBPROTOBUF_EXPORT StringTypeTraits { |
| public: |
| typedef const string& ConstType; |
| typedef string* MutableType; |
| |
| static inline const string& Get(int number, const ExtensionSet& set) { |
| return set.GetString(number); |
| } |
| static inline void Set(int number, const string& value, ExtensionSet* set) { |
| set->SetString(number, value); |
| } |
| static inline string* Mutable(int number, ExtensionSet* set) { |
| return set->MutableString(number); |
| } |
| }; |
| |
| class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { |
| public: |
| typedef const string& ConstType; |
| typedef string* MutableType; |
| |
| static inline const string& Get(int number, const ExtensionSet& set, |
| int index) { |
| return set.GetRepeatedString(number, index); |
| } |
| static inline void Set(int number, int index, |
| const string& value, ExtensionSet* set) { |
| set->SetRepeatedString(number, index, value); |
| } |
| static inline string* Mutable(int number, int index, ExtensionSet* set) { |
| return set->MutableRepeatedString(number, index); |
| } |
| static inline void Add(int number, const string& value, ExtensionSet* set) { |
| set->AddString(number, value); |
| } |
| static inline string* Add(int number, ExtensionSet* set) { |
| return set->AddString(number); |
| } |
| }; |
| |
| // ------------------------------------------------------------------- |
| // EnumTypeTraits |
| |
| // ExtensionSet represents enums using integers internally, so we have to |
| // static_cast around. |
| template <typename Type> |
| class EnumTypeTraits { |
| public: |
| typedef Type ConstType; |
| |
| static inline ConstType Get(int number, const ExtensionSet& set) { |
| return static_cast<Type>(set.GetEnum(number)); |
| } |
| static inline void Set(int number, ConstType value, ExtensionSet* set) { |
| set->SetEnum(number, value); |
| } |
| }; |
| |
| template <typename Type> |
| class RepeatedEnumTypeTraits { |
| public: |
| typedef Type ConstType; |
| |
| static inline ConstType Get(int number, const ExtensionSet& set, int index) { |
| return static_cast<Type>(set.GetRepeatedEnum(number, index)); |
| } |
| static inline void Set(int number, int index, |
| ConstType value, ExtensionSet* set) { |
| set->SetRepeatedEnum(number, index, value); |
| } |
| static inline void Add(int number, ConstType value, ExtensionSet* set) { |
| set->AddEnum(number, value); |
| } |
| }; |
| |
| // ------------------------------------------------------------------- |
| // 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 { |
| public: |
| typedef const Type& ConstType; |
| typedef Type* MutableType; |
| |
| static inline ConstType Get(int number, const ExtensionSet& set) { |
| return static_cast<const Type&>(set.GetMessage(number)); |
| } |
| static inline MutableType Mutable(int number, ExtensionSet* set) { |
| return static_cast<Type*>(set->MutableMessage(number)); |
| } |
| }; |
| |
| template <typename Type> |
| class RepeatedMessageTypeTraits { |
| public: |
| typedef const Type& ConstType; |
| typedef Type* MutableType; |
| |
| static inline ConstType Get(int number, const ExtensionSet& set, int index) { |
| return static_cast<const Type&>(set.GetRepeatedMessage(number, index)); |
| } |
| static inline MutableType Mutable(int number, int index, ExtensionSet* set) { |
| return static_cast<Type*>(set->MutableRepeatedMessage(number, index)); |
| } |
| static inline MutableType Add(int number, ExtensionSet* set) { |
| return static_cast<Type*>(set->AddMessage(number)); |
| } |
| }; |
| |
| // ------------------------------------------------------------------- |
| // ExtensionIdentifier |
| |
| // This is the type of actual extension objects. E.g. if you have: |
| // extends Foo with optional int32 bar = 1234; |
| // then "bar" will be defined in C++ as: |
| // ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>> 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 at extension |
| // identifier would not necessarily cause the compiler to output any sort |
| // of reference to any simple 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> |
| class ExtensionIdentifier { |
| public: |
| typedef TypeTraitsType TypeTraits; |
| typedef ExtendeeType Extendee; |
| |
| ExtensionIdentifier(int number): number_(number) {} |
| inline int number() const { return number_; } |
| private: |
| const int number_; |
| }; |
| |
| } // namespace internal |
| } // namespace protobuf |
| |
| } // namespace google |
| #endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__ |