diff options
Diffstat (limited to 'src/google/protobuf/message.h')
-rw-r--r-- | src/google/protobuf/message.h | 262 |
1 files changed, 209 insertions, 53 deletions
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index c0062f9..8bbf405 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -79,18 +79,19 @@ // // Same as the last block, but do it dynamically via the Message // // reflection interface. // Message* foo = new Foo; -// Descriptor* descriptor = foo->GetDescriptor(); +// const Descriptor* descriptor = foo->GetDescriptor(); // // // Get the descriptors for the fields we're interested in and verify // // their types. -// FieldDescriptor* text_field = descriptor->FindFieldByName("text"); +// const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); // assert(text_field != NULL); // assert(text_field->type() == FieldDescriptor::TYPE_STRING); -// assert(text_field->label() == FieldDescriptor::TYPE_OPTIONAL); -// FieldDescriptor* numbers_field = descriptor->FindFieldByName("numbers"); +// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); +// const FieldDescriptor* numbers_field = descriptor-> +// FindFieldByName("numbers"); // assert(numbers_field != NULL); // assert(numbers_field->type() == FieldDescriptor::TYPE_INT32); -// assert(numbers_field->label() == FieldDescriptor::TYPE_REPEATED); +// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED); // // // Parse the message. // foo->ParseFromString(data); @@ -109,38 +110,17 @@ #ifndef GOOGLE_PROTOBUF_MESSAGE_H__ #define GOOGLE_PROTOBUF_MESSAGE_H__ -#include <vector> -#include <string> - -#ifdef __DECCXX -// HP C++'s iosfwd doesn't work. -#include <iostream> -#else #include <iosfwd> -#endif +#include <string> +#include <vector> #include <google/protobuf/message_lite.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> -#if defined(_WIN32) && defined(GetMessage) -// windows.h defines GetMessage() as a macro. Let's re-define it as an inline -// function. This is necessary because Reflection has a method called -// GetMessage() which we don't want overridden. The inline function should be -// equivalent for C++ users. -inline BOOL GetMessage_Win32( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#undef GetMessage -inline BOOL GetMessage( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#endif +#define GOOGLE_PROTOBUF_HAS_ONEOF namespace google { namespace protobuf { @@ -151,17 +131,20 @@ class Reflection; class MessageFactory; // Defined in other files. -class Descriptor; // descriptor.h -class FieldDescriptor; // descriptor.h -class EnumDescriptor; // descriptor.h -class EnumValueDescriptor; // descriptor.h +class UnknownFieldSet; // unknown_field_set.h namespace io { class ZeroCopyInputStream; // zero_copy_stream.h class ZeroCopyOutputStream; // zero_copy_stream.h class CodedInputStream; // coded_stream.h class CodedOutputStream; // coded_stream.h } -class UnknownFieldSet; // unknown_field_set.h + + +template<typename T> +class RepeatedField; // repeated_field.h + +template<typename T> +class RepeatedPtrField; // repeated_field.h // A container to hold message metadata. struct Metadata { @@ -169,12 +152,6 @@ struct Metadata { const Reflection* reflection; }; -// Returns the EnumDescriptor for enum type E, which must be a -// proto-declared enum type. Code generated by the protocol compiler -// will include specializations of this template for each enum type declared. -template <typename E> -const EnumDescriptor* GetEnumDescriptor(); - // Abstract interface for protocol messages. // // See also MessageLite, which contains most every-day operations. Message @@ -203,9 +180,10 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { virtual void CopyFrom(const Message& from); // Merge the fields from the given message into this message. Singular - // fields will be overwritten, except for embedded messages which will - // be merged. Repeated fields will be concatenated. The given message - // must be of the same type as this message (i.e. the exact same class). + // fields will be overwritten, if specified in from, except for embedded + // messages which will be merged. Repeated fields will be concatenated. + // The given message must be of the same type as this message (i.e. the + // exact same class). virtual void MergeFrom(const Message& from); // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with @@ -216,7 +194,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // This is much, much slower than IsInitialized() as it is implemented // purely via reflection. Generally, you should not call this unless you // have already determined that an error exists by calling IsInitialized(). - void FindInitializationErrors(vector<string>* errors) const; + void FindInitializationErrors(std::vector<string>* errors) const; // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. @@ -378,7 +356,6 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // write fields from a Reflection without paying attention to the type. class LIBPROTOBUF_EXPORT Reflection { public: - // TODO(kenton): Remove parameter. inline Reflection() {} virtual ~Reflection(); @@ -408,7 +385,27 @@ class LIBPROTOBUF_EXPORT Reflection { virtual void ClearField(Message* message, const FieldDescriptor* field) const = 0; - // Remove the last element of a repeated field. + // Check if the oneof is set. Returns ture if any field in oneof + // is set, false otherwise. + // TODO(jieluo) - make it pure virtual after updating all + // the subclasses. + virtual bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return false; + } + + virtual void ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const {} + + // Returns the field descriptor if the oneof is set. NULL otherwise. + // TODO(jieluo) - make it pure virtual. + virtual const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return NULL; + } + + // Removes the last element of a repeated field. // We don't provide a way to remove any element other than the last // because it invites inefficient use, such as O(n^2) filtering loops // that should have been O(n). If you want to remove an element other @@ -417,15 +414,25 @@ class LIBPROTOBUF_EXPORT Reflection { // call RemoveLast(). virtual void RemoveLast(Message* message, const FieldDescriptor* field) const = 0; + // Removes the last element of a repeated message field, and returns the + // pointer to the caller. Caller takes ownership of the returned pointer. + virtual Message* ReleaseLast(Message* message, + const FieldDescriptor* field) const = 0; // Swap the complete contents of two messages. virtual void Swap(Message* message1, Message* message2) const = 0; + // Swap fields listed in fields vector of two messages. + virtual void SwapFields(Message* message1, + Message* message2, + const std::vector<const FieldDescriptor*>& fields) + const = 0; + // Swap two elements of a repeated field. virtual void SwapElements(Message* message, - const FieldDescriptor* field, - int index1, - int index2) const = 0; + const FieldDescriptor* field, + int index1, + int index2) const = 0; // List all fields of the message which are currently set. This includes // extensions. Singular fields will only be listed if HasField(field) would @@ -433,7 +440,7 @@ class LIBPROTOBUF_EXPORT Reflection { // would return non-zero. Fields (both normal fields and extension fields) // will be listed ordered by field number. virtual void ListFields(const Message& message, - vector<const FieldDescriptor*>* output) const = 0; + std::vector<const FieldDescriptor*>* output) const = 0; // Singular field getters ------------------------------------------ // These get the value of a non-repeated field. They return the default @@ -518,6 +525,23 @@ class LIBPROTOBUF_EXPORT Reflection { virtual Message* MutableMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const = 0; + // Replaces the message specified by 'field' with the already-allocated object + // sub_message, passing ownership to the message. If the field contained a + // message, that message is deleted. If sub_message is NULL, the field is + // cleared. + virtual void SetAllocatedMessage(Message* message, + Message* sub_message, + const FieldDescriptor* field) const = 0; + // Releases the message specified by 'field' and returns the pointer, + // ReleaseMessage() will return the message the message object if it exists. + // Otherwise, it may or may not return NULL. In any case, if the return value + // is non-NULL, the caller takes ownership of the pointer. + // If the field existed (HasField() is true), then the returned pointer will + // be the same as the pointer returned by MutableMessage(). + // This function has the same effect as ClearField(). + virtual Message* ReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; // Repeated field getters ------------------------------------------ @@ -625,7 +649,39 @@ class LIBPROTOBUF_EXPORT Reflection { MessageFactory* factory = NULL) const = 0; - // Extensions ------------------------------------------------------ + // Repeated field accessors ------------------------------------------------- + // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular + // access to the data in a RepeatedField. The methods below provide aggregate + // access by exposing the RepeatedField object itself with the Message. + // Applying these templates to inappropriate types will lead to an undefined + // reference at link time (e.g. GetRepeatedField<***double>), or possibly a + // template matching error at compile time (e.g. GetRepeatedPtrField<File>). + // + // Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd); + + // for T = Cord and all protobuf scalar types except enums. + template<typename T> + const RepeatedField<T>& GetRepeatedField( + const Message&, const FieldDescriptor*) const; + + // for T = Cord and all protobuf scalar types except enums. + template<typename T> + RepeatedField<T>* MutableRepeatedField( + Message*, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template<typename T> + const RepeatedPtrField<T>& GetRepeatedPtrField( + const Message&, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template<typename T> + RepeatedPtrField<T>* MutableRepeatedPtrField( + Message*, const FieldDescriptor*) const; + + // Extensions ---------------------------------------------------------------- // Try to find an extension of this message type by fully-qualified field // name. Returns NULL if no extension is known for this name or number. @@ -637,7 +693,26 @@ class LIBPROTOBUF_EXPORT Reflection { virtual const FieldDescriptor* FindKnownExtensionByNumber( int number) const = 0; + // --------------------------------------------------------------------------- + + protected: + // Obtain a pointer to a Repeated Field Structure and do some type checking: + // on field->cpp_type(), + // on field->field_option().ctype() (if ctype >= 0) + // of field->message_type() (if message_type != NULL). + // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer). + virtual void* MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, + int ctype, const Descriptor* message_type) const = 0; + private: + // Special version for specialized implementations of string. We can't call + // MutableRawRepeatedField directly here because we don't have access to + // FieldOptions::* which are defined in descriptor.pb.h. Including that + // file here is not possible because it would cause a circular include cycle. + void* MutableRawRepeatedString( + Message* message, const FieldDescriptor* field, bool is_string) const; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); }; @@ -654,7 +729,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // Calling this method twice with the same Descriptor returns the same // object. The returned object remains property of the factory. Also, any // objects created by calling the prototype's New() method share some data - // with the prototype, so these must be destoyed before the MessageFactory + // with the prototype, so these must be destroyed before the MessageFactory // is destroyed. // // The given descriptor must outlive the returned message, and hence must @@ -700,10 +775,91 @@ class LIBPROTOBUF_EXPORT MessageFactory { static void InternalRegisterGeneratedMessage(const Descriptor* descriptor, const Message* prototype); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory); }; +#define DECLARE_GET_REPEATED_FIELD(TYPE) \ +template<> \ +LIBPROTOBUF_EXPORT \ +const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \ + const Message& message, const FieldDescriptor* field) const; \ + \ +template<> \ +RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \ + Message* message, const FieldDescriptor* field) const; + +DECLARE_GET_REPEATED_FIELD(int32) +DECLARE_GET_REPEATED_FIELD(int64) +DECLARE_GET_REPEATED_FIELD(uint32) +DECLARE_GET_REPEATED_FIELD(uint64) +DECLARE_GET_REPEATED_FIELD(float) +DECLARE_GET_REPEATED_FIELD(double) +DECLARE_GET_REPEATED_FIELD(bool) + +#undef DECLARE_GET_REPEATED_FIELD + +// ============================================================================= +// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide +// specializations for <string>, <StringPieceField> and <Message> and handle +// everything else with the default template which will match any type having +// a method with signature "static const google::protobuf::Descriptor* descriptor()". +// Such a type presumably is a descendant of google::protobuf::Message. + +template<> +inline const RepeatedPtrField<string>& Reflection::GetRepeatedPtrField<string>( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<RepeatedPtrField<string>* >( + MutableRawRepeatedString(const_cast<Message*>(&message), field, true)); +} + +template<> +inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<string>* >( + MutableRawRepeatedString(message, field, true)); +} + + +// ----- + +template<> +inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<RepeatedPtrField<Message>* >( + MutableRawRepeatedField(const_cast<Message*>(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template<> +inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<Message>* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template<typename PB> +inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<RepeatedPtrField<PB>* >( + MutableRawRepeatedField(const_cast<Message*>(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + +template<typename PB> +inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<PB>* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + } // namespace protobuf } // namespace google |