aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/extension_set.h
diff options
context:
space:
mode:
authorGravatar xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
committerGravatar xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
commitb55a20fa2c669b181f47ea9219b8e74d1263da19 (patch)
tree3936a0e7c22196587a6d8397372de41434fe2129 /src/google/protobuf/extension_set.h
parent9ced30caf94bb4e7e9629c199679ff44e8ca7389 (diff)
Down-integrate from internal branch
Diffstat (limited to 'src/google/protobuf/extension_set.h')
-rw-r--r--src/google/protobuf/extension_set.h227
1 files changed, 165 insertions, 62 deletions
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index ac1ada02..03af7eaf 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -89,8 +89,8 @@ typedef bool EnumValidityFuncWithArg(const void* arg, int number);
// Information about a registered extension.
struct ExtensionInfo {
inline ExtensionInfo() {}
- inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
- : type(type), is_repeated(is_repeated), is_packed(is_packed),
+ inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked)
+ : type(type_param), is_repeated(isrepeated), is_packed(ispacked),
descriptor(NULL) {}
FieldType type;
@@ -214,6 +214,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool Has(int number) const;
int ExtensionSize(int number) const; // Size of a repeated extension.
+ int NumExtensions() const; // The number of extensions
FieldType ExtensionType(int number) const;
void ClearExtension(int number);
@@ -251,10 +252,21 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& prototype, desc);
MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
MessageFactory* factory);
+ // Adds the given message to the ExtensionSet, taking ownership of the
+ // message object. Existing message with the same number will be deleted.
+ // If "message" is NULL, this is equivalent to "ClearExtension(number)".
+ void SetAllocatedMessage(int number, FieldType type,
+ const FieldDescriptor* descriptor,
+ MessageLite* message);
+ MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+ MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
+ MessageFactory* factory);
#undef desc
// repeated fields -------------------------------------------------
+ void* MutableRawRepeatedField(int number);
+
int32 GetRepeatedInt32 (int number, int index) const;
int64 GetRepeatedInt64 (int number, int index) const;
uint32 GetRepeatedUInt32(int number, int index) const;
@@ -296,6 +308,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
#undef desc
void RemoveLast(int number);
+ MessageLite* ReleaseLast(int number);
void SwapElements(int number, int index1, int index2);
// -----------------------------------------------------------------
@@ -312,18 +325,18 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void Swap(ExtensionSet* other);
bool IsInitialized() const;
- // Parses a single extension from the input. The input should start out
- // positioned immediately after the tag. |containing_type| is the default
- // instance for the containing message; it is used only to look up the
- // extension by number. See RegisterExtension(), above. Unlike the other
- // methods of ExtensionSet, this only works for generated message types --
- // it looks up extensions registered using RegisterExtension().
+ // Parses a single extension from the input. The input should start out
+ // positioned immediately after the tag.
bool ParseField(uint32 tag, io::CodedInputStream* input,
ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
- // FieldSkipper automatically).
+ // FieldSkipper automatically). |containing_type| is the default
+ // instance for the containing message; it is used only to look up the
+ // extension by number. See RegisterExtension(), above. Unlike the other
+ // methods of ExtensionSet, this only works for generated message types --
+ // it looks up extensions registered using RegisterExtension().
bool ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type);
bool ParseField(uint32 tag, io::CodedInputStream* input,
@@ -382,18 +395,49 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
private:
+ // Interface of a lazily parsed singular message extension.
+ class LIBPROTOBUF_EXPORT LazyMessageExtension {
+ public:
+ LazyMessageExtension() {}
+ virtual ~LazyMessageExtension() {}
+
+ virtual LazyMessageExtension* New() const = 0;
+ virtual const MessageLite& GetMessage(
+ const MessageLite& prototype) const = 0;
+ virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
+ virtual void SetAllocatedMessage(MessageLite *message) = 0;
+ virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+
+ virtual bool IsInitialized() const = 0;
+ virtual int ByteSize() const = 0;
+ virtual int SpaceUsed() const = 0;
+
+ virtual void MergeFrom(const LazyMessageExtension& other) = 0;
+ virtual void Clear() = 0;
+
+ virtual bool ReadMessage(const MessageLite& prototype,
+ io::CodedInputStream* input) = 0;
+ virtual void WriteMessage(int number,
+ io::CodedOutputStream* output) const = 0;
+ virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0;
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
+ };
struct Extension {
+ // The order of these fields packs Extension into 24 bytes when using 8
+ // byte alignment. Consider this when adding or removing fields here.
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;
- MessageLite* message_value;
+ 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;
+ MessageLite* message_value;
+ LazyMessageExtension* lazymessage_value;
RepeatedField <int32 >* repeated_int32_value;
RepeatedField <int64 >* repeated_int64_value;
@@ -416,21 +460,28 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// 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;
+ bool is_cleared : 4;
+
+ // For singular message types, indicates whether lazy parsing is enabled
+ // for this extension. This field is only valid when type == TYPE_MESSAGE
+ // and !is_repeated because we only support lazy parsing for singular
+ // message types currently. If is_lazy = true, the extension is stored in
+ // lazymessage_value. Otherwise, the extension will be message_value.
+ bool is_lazy : 4;
// For repeated types, this indicates if the [packed=true] option is set.
bool is_packed;
- // The descriptor for this extension, if one exists and is known. May be
- // NULL. Must not be NULL if the descriptor for the extension does not
- // live in the same pool as the descriptor for the containing type.
- const FieldDescriptor* descriptor;
-
// For packed fields, the size of the packed data is recorded here when
// ByteSize() is called then used during serialization.
// TODO(kenton): Use atomic<int> when C++ supports it.
mutable int cached_size;
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+
// Some helper methods for operations on a single Extension.
void SerializeFieldWithCachedSizes(
int number,
@@ -453,6 +504,25 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
};
+ // Returns true and fills field_number and extension if extension is found.
+ bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder,
+ int* field_number, ExtensionInfo* extension);
+
+ // Parses a single extension from the input. The input should start out
+ // positioned immediately after the wire tag. This method is called in
+ // ParseField() after field number is extracted from the wire tag and
+ // ExtensionInfo is found by the field number.
+ bool ParseFieldWithExtensionInfo(int field_number,
+ const ExtensionInfo& extension,
+ io::CodedInputStream* input,
+ FieldSkipper* field_skipper);
+
+ // Like ParseField(), but this method may parse singular message extensions
+ // lazily depending on the value of FLAGS_eagerly_parse_message_sets.
+ bool ParseFieldMaybeLazily(uint32 tag, io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper);
+
// Gets the extension with the given number, creating it if it does not
// already exist. Returns true if the extension did not already exist.
bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
@@ -720,6 +790,15 @@ class MessageTypeTraits {
return static_cast<Type*>(
set->MutableMessage(number, field_type, Type::default_instance(), NULL));
}
+ static inline void SetAllocated(int number, FieldType field_type,
+ MutableType message, ExtensionSet* set) {
+ set->SetAllocatedMessage(number, field_type, NULL, message);
+ }
+ static inline MutableType Release(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return static_cast<Type*>(set->ReleaseMessage(
+ number, Type::default_instance()));
+ }
};
template <typename Type>
@@ -787,113 +866,137 @@ class ExtensionIdentifier {
// causes problems if the class has a nested message or enum type with that
// name and "_TypeTraits" is technically reserved for the C++ library since
// it starts with an underscore followed by a capital letter.
+//
+// For similar reason, we use "_field_type" and "_is_packed" as parameter names
+// below, so that "field_type" and "is_packed" can be used as field names.
#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \
/* Has, Size, Clear */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline bool HasExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _extensions_.Has(id.number()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void ClearExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
_extensions_.ClearExtension(id.number()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline int ExtensionSize( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _extensions_.ExtensionSize(id.number()); \
} \
\
/* Singular accessors */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _proto_TypeTraits::Get(id.number(), _extensions_, \
id.default_value()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType MutableExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
- return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Mutable(id.number(), _field_type, \
+ &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
typename _proto_TypeTraits::ConstType value) { \
- _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \
+ _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ inline void SetAllocatedExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
+ typename _proto_TypeTraits::MutableType value) { \
+ _proto_TypeTraits::SetAllocated(id.number(), _field_type, \
+ value, &_extensions_); \
+ } \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ inline typename _proto_TypeTraits::MutableType ReleaseExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Release(id.number(), _field_type, \
+ &_extensions_); \
} \
\
/* Repeated accessors */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) const { \
return _proto_TypeTraits::Get(id.number(), _extensions_, index); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType MutableExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) { \
return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index, typename _proto_TypeTraits::ConstType value) { \
_proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType AddExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
- return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void AddExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
typename _proto_TypeTraits::ConstType value) { \
- _proto_TypeTraits::Add(id.number(), field_type, is_packed, \
+ _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \
value, &_extensions_); \
}