aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/metadata_lite.h
diff options
context:
space:
mode:
authorGravatar Adam Cozzette <acozzette@google.com>2017-09-12 10:32:01 -0700
committerGravatar Adam Cozzette <acozzette@google.com>2017-09-14 10:03:57 -0700
commit13fd045dbb2b4dacea32be162a41d5a4b0d1802f (patch)
treec219e7eb18b82523e36c6748861c403a14ea66ae /src/google/protobuf/metadata_lite.h
parentd1bc27caef8377a710370189675cb0958443e8f1 (diff)
Integrated internal changes from Google
Diffstat (limited to 'src/google/protobuf/metadata_lite.h')
-rw-r--r--src/google/protobuf/metadata_lite.h47
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