diff options
author | Adam Cozzette <acozzette@google.com> | 2017-09-12 10:32:01 -0700 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2017-09-14 10:03:57 -0700 |
commit | 13fd045dbb2b4dacea32be162a41d5a4b0d1802f (patch) | |
tree | c219e7eb18b82523e36c6748861c403a14ea66ae /src/google/protobuf/metadata_lite.h | |
parent | d1bc27caef8377a710370189675cb0958443e8f1 (diff) |
Integrated internal changes from Google
Diffstat (limited to 'src/google/protobuf/metadata_lite.h')
-rw-r--r-- | src/google/protobuf/metadata_lite.h | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h index 6022be92..10692e9b 100644 --- a/src/google/protobuf/metadata_lite.h +++ b/src/google/protobuf/metadata_lite.h @@ -34,6 +34,7 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/arena.h> #include <google/protobuf/generated_message_util.h> +#include <google/protobuf/stubs/port.h> namespace google { namespace protobuf { @@ -62,7 +63,7 @@ class InternalMetadataWithArenaBase { ptr_ = NULL; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { return PtrValue<Container>()->unknown_fields; } else { @@ -70,7 +71,7 @@ class InternalMetadataWithArenaBase { } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { return &PtrValue<Container>()->unknown_fields; } else { @@ -78,7 +79,7 @@ class InternalMetadataWithArenaBase { } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { return PtrValue<Container>()->arena; } else { @@ -86,11 +87,11 @@ class InternalMetadataWithArenaBase { } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { return PtrTag() == kTagContainer; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { // Semantics here are that we swap only the unknown fields, not the arena // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in @@ -102,19 +103,19 @@ class InternalMetadataWithArenaBase { } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { if (other.have_unknown_fields()) { static_cast<Derived*>(this)->DoMergeFrom(other.unknown_fields()); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Clear() { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Clear() { if (have_unknown_fields()) { static_cast<Derived*>(this)->DoClear(); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { return ptr_; } @@ -132,7 +133,7 @@ class InternalMetadataWithArenaBase { static const intptr_t kPtrValueMask = ~kPtrTagMask; // Accessors for pointer tag and pointer value. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask; } @@ -147,7 +148,7 @@ class InternalMetadataWithArenaBase { Arena* arena; }; - GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { + GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { Arena* my_arena = arena(); Container* container = Arena::Create<Container>(my_arena); // Two-step assignment works around a bug in clang's static analyzer: @@ -190,6 +191,32 @@ class InternalMetadataWithArenaLite } }; +// This helper RAII class is needed to efficiently parse unknown fields. We +// should only call mutable_unknown_fields if there are actual unknown fields. +// The obvious thing to just use a stack string and swap it at the end of the +// parse won't work, because the destructor of StringOutputStream needs to be +// called before we can modify the string (it check-fails). Using +// LiteUnknownFieldSetter setter(&_internal_metadata_); +// StringOutputStream stream(setter.buffer()); +// guarantees that the string is only swapped after stream is destroyed. +class LIBPROTOBUF_EXPORT LiteUnknownFieldSetter { + public: + explicit LiteUnknownFieldSetter(InternalMetadataWithArenaLite* metadata) + : metadata_(metadata) { + if (metadata->have_unknown_fields()) { + buffer_.swap(*metadata->mutable_unknown_fields()); + } + } + ~LiteUnknownFieldSetter() { + if (!buffer_.empty()) metadata_->mutable_unknown_fields()->swap(buffer_); + } + string* buffer() { return &buffer_; } + + private: + InternalMetadataWithArenaLite* metadata_; + string buffer_; +}; + } // namespace internal } // namespace protobuf |