diff options
Diffstat (limited to 'src/google/protobuf/arenastring.h')
-rwxr-xr-x | src/google/protobuf/arenastring.h | 123 |
1 files changed, 106 insertions, 17 deletions
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index a7efb752..168fc972 100755 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -33,12 +33,11 @@ #include <string> -#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/arena.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/fastmem.h> -#include <google/protobuf/arena.h> - - +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/port.h> // This is the implementation of arena string fields written for the open-source // release. The ArenaStringPtr struct below is an internal implementation class @@ -52,6 +51,18 @@ namespace google { namespace protobuf { namespace internal { +template <typename T> +class TaggedPtr { + public: + void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); } + T* Get() const { return reinterpret_cast<T*>(ptr_); } + + bool IsNull() { return ptr_ == 0; } + + private: + uintptr_t ptr_; +}; + struct LIBPROTOBUF_EXPORT ArenaStringPtr { inline void Set(const ::std::string* default_value, const ::std::string& value, ::google::protobuf::Arena* arena) { @@ -62,6 +73,12 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { } } + inline void SetLite(const ::std::string* default_value, + const ::std::string& value, + ::google::protobuf::Arena* arena) { + Set(default_value, value, arena); + } + // Basic accessors. inline const ::std::string& Get() const { return *ptr_; } @@ -82,10 +99,18 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { if (ptr_ == default_value) { return NULL; } + return ReleaseNonDefault(default_value, arena); + } + + // Similar to Release, but ptr_ cannot be the default_value. + inline ::std::string* ReleaseNonDefault( + const ::std::string* default_value, ::google::protobuf::Arena* arena) { + GOOGLE_DCHECK(!IsDefault(default_value)); ::std::string* released = NULL; if (arena != NULL) { - // ptr_ is owned by the arena -- we need to return a copy. - released = new ::std::string(*ptr_); + // ptr_ is owned by the arena. + released = new ::std::string; + released->swap(*ptr_); } else { released = ptr_; } @@ -143,9 +168,32 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { // Swaps internal pointers. Arena-safety semantics: this is guarded by the // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is // 'unsafe' if called directly. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { std::swap(ptr_, other->ptr_); } + GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap( + ArenaStringPtr* other, const ::std::string* default_value, Arena* arena) { +#ifndef NDEBUG + // For debug builds, we swap the contents of the string, rather than the + // string instances themselves. This invalidates previously taken const + // references that are (per our documentation) invalidated by calling Swap() + // on the message. + // + // If both strings are the default_value, swapping is uninteresting. + // Otherwise, we use ArenaStringPtr::Mutable() to access the string, to + // ensure that we do not try to mutate default_value itself. + if (IsDefault(default_value) && other->IsDefault(default_value)) { + return; + } + + ::std::string* this_ptr = Mutable(default_value, arena); + ::std::string* other_ptr = other->Mutable(default_value, arena); + + this_ptr->swap(*other_ptr); +#else + std::swap(ptr_, other->ptr_); +#endif + } // Frees storage (if not on an arena). inline void Destroy(const ::std::string* default_value, @@ -168,6 +216,15 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { } } + // Clears content, assuming that the current value is not the empty string + // default. + inline void ClearNonDefaultToEmpty() { + ptr_->clear(); + } + inline void ClearNonDefaultToEmptyNoArena() { + ptr_->clear(); + } + // Clears content, but keeps allocated string if arena != NULL, to avoid the // overhead of heap operations. After this returns, the content (as seen by // the user) will always be equal to |default_value|. @@ -235,12 +292,19 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { if (ptr_ == default_value) { return NULL; } else { - ::std::string* released = ptr_; - ptr_ = const_cast< ::std::string* >(default_value); - return released; + return ReleaseNonDefaultNoArena(default_value); } } + inline ::std::string* ReleaseNonDefaultNoArena( + const ::std::string* default_value) { + GOOGLE_DCHECK(!IsDefault(default_value)); + ::std::string* released = ptr_; + ptr_ = const_cast< ::std::string* >(default_value); + return released; + } + + inline void SetAllocatedNoArena(const ::std::string* default_value, ::std::string* value) { if (ptr_ != default_value) { @@ -288,18 +352,27 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { return ptr_ == default_value; } + // Internal accessors!!!! + void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) { + ptr_ = value.Get(); + } + // Generated code only! An optimization, in certain cases the generated + // code is certain we can obtain a string with no default checks and + // tag tests. + ::std::string* UnsafeMutablePointer() { return ptr_; } + private: ::std::string* ptr_; - GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena, - const ::std::string* initial_value) { + GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + void CreateInstance(::google::protobuf::Arena* arena, + const ::std::string* initial_value) { GOOGLE_DCHECK(initial_value != NULL); - ptr_ = new ::std::string(*initial_value); - if (arena != NULL) { - arena->Own(ptr_); - } + // uses "new ::std::string" when arena is nullptr + ptr_ = Arena::Create< ::std::string >(arena, *initial_value); } - GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) { + GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + void CreateInstanceNoArena(const ::std::string* initial_value) { GOOGLE_DCHECK(initial_value != NULL); ptr_ = new ::std::string(*initial_value); } @@ -310,5 +383,21 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { +namespace protobuf { +namespace internal { + +inline void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value, + ArenaStringPtr value) { + const ::std::string* me = *UnsafeRawStringPointer(); + const ::std::string* other = *value.UnsafeRawStringPointer(); + // If the pointers are the same then do nothing. + if (me != other) { + SetNoArena(default_value, value.GetNoArena()); + } +} + +} // namespace internal +} // namespace protobuf + } // namespace google #endif // GOOGLE_PROTOBUF_ARENASTRING_H__ |