|  | @@ -37,7 +37,6 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <google/protobuf/stubs/logging.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/stubs/common.h>
 | 
	
		
			
				|  |  | -#include <google/protobuf/stubs/fastmem.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/arena.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/port.h>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -48,23 +47,57 @@
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// This is the implementation of arena string fields written for the open-source
 | 
	
		
			
				|  |  | -// release. The ArenaStringPtr struct below is an internal implementation class
 | 
	
		
			
				|  |  | -// and *should not be used* by user code. It is used to collect string
 | 
	
		
			
				|  |  | -// operations together into one place and abstract away the underlying
 | 
	
		
			
				|  |  | -// string-field pointer representation, so that (for example) an alternate
 | 
	
		
			
				|  |  | -// implementation that knew more about ::std::string's internals could integrate
 | 
	
		
			
				|  |  | -// more closely with the arena allocator.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  namespace google {
 | 
	
		
			
				|  |  |  namespace protobuf {
 | 
	
		
			
				|  |  |  namespace internal {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// Lazy string instance to support string fields with non-empty default.
 | 
	
		
			
				|  |  | +// These are initialized on the first call to .get().
 | 
	
		
			
				|  |  | +class PROTOBUF_EXPORT LazyString {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  // We explicitly make LazyString an aggregate so that MSVC can do constant
 | 
	
		
			
				|  |  | +  // initialization on it without marking it `constexpr`.
 | 
	
		
			
				|  |  | +  // We do not want to use `constexpr` because it makes it harder to have extern
 | 
	
		
			
				|  |  | +  // storage for it and causes library bloat.
 | 
	
		
			
				|  |  | +  struct InitValue {
 | 
	
		
			
				|  |  | +    const char* ptr;
 | 
	
		
			
				|  |  | +    size_t size;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  // We keep a union of the initialization value and the std::string to save on
 | 
	
		
			
				|  |  | +  // space. We don't need the string array after Init() is done.
 | 
	
		
			
				|  |  | +  union {
 | 
	
		
			
				|  |  | +    mutable InitValue init_value_;
 | 
	
		
			
				|  |  | +    alignas(std::string) mutable char string_buf_[sizeof(std::string)];
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  mutable std::atomic<const std::string*> inited_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  const std::string& get() const {
 | 
	
		
			
				|  |  | +    // This check generates less code than a call-once invocation.
 | 
	
		
			
				|  |  | +    auto* res = inited_.load(std::memory_order_acquire);
 | 
	
		
			
				|  |  | +    if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
 | 
	
		
			
				|  |  | +    return *res;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | + private:
 | 
	
		
			
				|  |  | +  // Initialize the string in `string_buf_`, update `inited_` and return it.
 | 
	
		
			
				|  |  | +  // We return it here to avoid having to read it again in the inlined code.
 | 
	
		
			
				|  |  | +  const std::string& Init() const;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  template <typename T>
 | 
	
		
			
				|  |  |  class TaggedPtr {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | +  void SetTagged(T* p) {
 | 
	
		
			
				|  |  | +    Set(p);
 | 
	
		
			
				|  |  | +    ptr_ |= 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); }
 | 
	
		
			
				|  |  | -  T* Get() const { return reinterpret_cast<T*>(ptr_); }
 | 
	
		
			
				|  |  | +  T* Get() const { return reinterpret_cast<T*>(ptr_ & -2); }
 | 
	
		
			
				|  |  | +  bool IsTagged() const { return ptr_ & 1; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Returned value is only safe to dereference if IsTagged() == false.
 | 
	
		
			
				|  |  | +  // It is safe to compare.
 | 
	
		
			
				|  |  | +  T* UnsafeGet() const { return reinterpret_cast<T*>(ptr_); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    bool IsNull() { return ptr_ == 0; }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -72,237 +105,266 @@ class TaggedPtr {
 | 
	
		
			
				|  |  |    uintptr_t ptr_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct PROTOBUF_EXPORT ArenaStringPtr {
 | 
	
		
			
				|  |  | -  inline void Set(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                  const ::std::string& value, Arena* arena) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      CreateInstance(arena, &value);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      *ptr_ = value;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
 | 
	
		
			
				|  |  | +              "TaggedPtr must be trivial");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  inline void SetLite(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                      const ::std::string& value, Arena* arena) {
 | 
	
		
			
				|  |  | -    Set(default_value, value, arena);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +// This class encapsulates a pointer to a std::string with or without a donated
 | 
	
		
			
				|  |  | +// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly
 | 
	
		
			
				|  |  | +// corresponds to the interface required by string fields in generated
 | 
	
		
			
				|  |  | +// code. It replaces the old std::string* pointer in such cases.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// The object has different but similar code paths for when the default value is
 | 
	
		
			
				|  |  | +// the empty string and when it is a non-empty string.
 | 
	
		
			
				|  |  | +// The empty string is handled different throughout the library and there is a
 | 
	
		
			
				|  |  | +// single global instance of it we can share.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// For fields with an empty string default value, there are three distinct
 | 
	
		
			
				|  |  | +// states:
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'String' tag (LSB is 0), equal to
 | 
	
		
			
				|  |  | +//   &GetEmptyStringAlreadyInited(): field is set to its default value. Points
 | 
	
		
			
				|  |  | +//   to a true std::string*, but we do not own that std::string* (it's a
 | 
	
		
			
				|  |  | +//   globally shared instance).
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty
 | 
	
		
			
				|  |  | +//   string: field points to a true std::string* instance that we own. This
 | 
	
		
			
				|  |  | +//   instance is either on the heap or on the arena (i.e. registered on
 | 
	
		
			
				|  |  | +//   free()/destructor-call list) as appropriate.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
 | 
	
		
			
				|  |  | +//   instance with a buffer on the arena (arena != NULL, always, in this case).
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// For fields with a non-empty string default value, there are three distinct
 | 
	
		
			
				|  |  | +// states:
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`:
 | 
	
		
			
				|  |  | +//   Field is in "default" mode and does not point to any actual instance.
 | 
	
		
			
				|  |  | +//   Methods that might need to create an instance of the object will pass a
 | 
	
		
			
				|  |  | +//   `const LazyString&` for it.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`:
 | 
	
		
			
				|  |  | +//   field points to a true std::string* instance that we own. This instance is
 | 
	
		
			
				|  |  | +//   either on the heap or on the arena (i.e. registered on
 | 
	
		
			
				|  |  | +//   free()/destructor-call list) as appropriate.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
 | 
	
		
			
				|  |  | +//   instance with a buffer on the arena (arena != NULL, always, in this case).
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// Generated code and reflection code both ensure that ptr_ is never null for
 | 
	
		
			
				|  |  | +// fields with an empty default.
 | 
	
		
			
				|  |  | +// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
 | 
	
		
			
				|  |  | +// so the field is always manually initialized via method calls.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// Side-note: why pass information about the default on every API call? Because
 | 
	
		
			
				|  |  | +// we don't want to hold it in a member variable, or else this would go into
 | 
	
		
			
				|  |  | +// every proto message instance. This would be a huge waste of space, since the
 | 
	
		
			
				|  |  | +// default instance pointer is typically a global (static class field). We want
 | 
	
		
			
				|  |  | +// the generated code to be as efficient as possible, and if we take
 | 
	
		
			
				|  |  | +// the default value information as a parameter that's in practice taken from a
 | 
	
		
			
				|  |  | +// static class field, and compare ptr_ to the default value, we end up with a
 | 
	
		
			
				|  |  | +// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also
 | 
	
		
			
				|  |  | +// requires the String tag to be 0 so we can avoid the mask before comparing.)
 | 
	
		
			
				|  |  | +struct PROTOBUF_EXPORT ArenaStringPtr {
 | 
	
		
			
				|  |  | +  // No default constructor or destructor -- we have to be POD because we go
 | 
	
		
			
				|  |  | +  // into a union when used in a oneof. Message code calls UnsafeReset() to zero
 | 
	
		
			
				|  |  | +  // the pointer when necessary instead.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Some methods below are overloaded on a `default_value` and on tags.
 | 
	
		
			
				|  |  | +  // The tagged overloads help reduce code size in the callers in generated
 | 
	
		
			
				|  |  | +  // code, while the `default_value` overloads are useful from reflection.
 | 
	
		
			
				|  |  | +  // By-value empty struct arguments are elided in the ABI.
 | 
	
		
			
				|  |  | +  struct EmptyDefault {};
 | 
	
		
			
				|  |  | +  struct NonEmptyDefault {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void Set(const std::string* default_value, ConstStringParam value,
 | 
	
		
			
				|  |  | +           ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Set(const std::string* default_value, std::string&& value,
 | 
	
		
			
				|  |  | +           ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Basic accessors.
 | 
	
		
			
				|  |  | -  inline const ::std::string& Get() const { return *ptr_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  inline ::std::string* Mutable(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                                Arena* arena) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      CreateInstance(arena, default_value);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return ptr_;
 | 
	
		
			
				|  |  | +  const std::string& Get() const PROTOBUF_ALWAYS_INLINE {
 | 
	
		
			
				|  |  | +    // Unconditionally mask away the tag.
 | 
	
		
			
				|  |  | +    return *tagged_ptr_.Get();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Release returns a ::std::string* instance that is heap-allocated and is not
 | 
	
		
			
				|  |  | -  // Own()'d by any arena. If the field was not set, it returns NULL. The caller
 | 
	
		
			
				|  |  | -  // retains ownership. Clears this field back to NULL state. Used to implement
 | 
	
		
			
				|  |  | -  // release_<field>() methods on generated classes.
 | 
	
		
			
				|  |  | -  inline ::std::string* Release(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                                Arena* arena) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return ReleaseNonDefault(default_value, arena);
 | 
	
		
			
				|  |  | +  const std::string* GetPointer() const PROTOBUF_ALWAYS_INLINE {
 | 
	
		
			
				|  |  | +    // Unconditionally mask away the tag.
 | 
	
		
			
				|  |  | +    return tagged_ptr_.Get();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Similar to Release, but ptr_ cannot be the default_value.
 | 
	
		
			
				|  |  | -  inline ::std::string* ReleaseNonDefault(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                                          Arena* arena) {
 | 
	
		
			
				|  |  | -    GOOGLE_DCHECK(!IsDefault(default_value));
 | 
	
		
			
				|  |  | -    ::std::string* released = NULL;
 | 
	
		
			
				|  |  | -    if (arena != NULL) {
 | 
	
		
			
				|  |  | -      // ptr_ is owned by the arena.
 | 
	
		
			
				|  |  | -      released = new ::std::string;
 | 
	
		
			
				|  |  | -      released->swap(*ptr_);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      released = ptr_;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ptr_ = const_cast< ::std::string*>(default_value);
 | 
	
		
			
				|  |  | -    return released;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned
 | 
	
		
			
				|  |  | -  // (i.e.  have its destructor already registered) if arena != NULL. If the
 | 
	
		
			
				|  |  | -  // field was not set, this returns NULL. This method clears this field back to
 | 
	
		
			
				|  |  | -  // NULL state. Used to implement unsafe_arena_release_<field>() methods on
 | 
	
		
			
				|  |  | -  // generated classes.
 | 
	
		
			
				|  |  | -  inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                                           Arena* /* arena */) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ::std::string* released = ptr_;
 | 
	
		
			
				|  |  | -    ptr_ = const_cast< ::std::string*>(default_value);
 | 
	
		
			
				|  |  | -    return released;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Takes a string that is heap-allocated, and takes ownership. The string's
 | 
	
		
			
				|  |  | -  // destructor is registered with the arena. Used to implement
 | 
	
		
			
				|  |  | +  // For fields with an empty default value.
 | 
	
		
			
				|  |  | +  std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  // For fields with a non-empty default value.
 | 
	
		
			
				|  |  | +  std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Release returns a std::string* instance that is heap-allocated and is not
 | 
	
		
			
				|  |  | +  // Own()'d by any arena. If the field is not set, this returns NULL. The
 | 
	
		
			
				|  |  | +  // caller retains ownership. Clears this field back to NULL state. Used to
 | 
	
		
			
				|  |  | +  // implement release_<field>() methods on generated classes.
 | 
	
		
			
				|  |  | +  std::string* Release(const std::string* default_value,
 | 
	
		
			
				|  |  | +                       ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  std::string* ReleaseNonDefault(const std::string* default_value,
 | 
	
		
			
				|  |  | +                                 ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Takes a std::string that is heap-allocated, and takes ownership. The
 | 
	
		
			
				|  |  | +  // std::string's destructor is registered with the arena. Used to implement
 | 
	
		
			
				|  |  |    // set_allocated_<field> in generated classes.
 | 
	
		
			
				|  |  | -  inline void SetAllocated(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                           ::std::string* value, Arena* arena) {
 | 
	
		
			
				|  |  | -    if (arena == NULL && ptr_ != default_value) {
 | 
	
		
			
				|  |  | -      Destroy(default_value, arena);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (value != NULL) {
 | 
	
		
			
				|  |  | -      ptr_ = value;
 | 
	
		
			
				|  |  | -      if (arena != NULL) {
 | 
	
		
			
				|  |  | -        arena->Own(value);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      ptr_ = const_cast< ::std::string*>(default_value);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Takes a string that has lifetime equal to the arena's lifetime. The arena
 | 
	
		
			
				|  |  | -  // must be non-null. It is safe only to pass this method a value returned by
 | 
	
		
			
				|  |  | -  // UnsafeArenaRelease() on another field of a message in the same arena. Used
 | 
	
		
			
				|  |  | -  // to implement unsafe_arena_set_allocated_<field> in generated classes.
 | 
	
		
			
				|  |  | -  inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                                      ::std::string* value,
 | 
	
		
			
				|  |  | -                                      Arena* /* arena */) {
 | 
	
		
			
				|  |  | -    if (value != NULL) {
 | 
	
		
			
				|  |  | -      ptr_ = value;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      ptr_ = const_cast< ::std::string*>(default_value);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  void SetAllocated(const std::string* default_value, std::string* value,
 | 
	
		
			
				|  |  | +                    ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // 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.
 | 
	
		
			
				|  |  | -  PROTOBUF_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
 | 
	
		
			
				|  |  | -    std::swap(ptr_, other->ptr_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  PROTOBUF_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_);
 | 
	
		
			
				|  |  | -    (void)default_value;
 | 
	
		
			
				|  |  | -    (void)arena;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  inline void Swap(ArenaStringPtr* other, const std::string* default_value,
 | 
	
		
			
				|  |  | +                   Arena* arena) PROTOBUF_ALWAYS_INLINE;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Frees storage (if not on an arena).
 | 
	
		
			
				|  |  | -  inline void Destroy(const ::std::string* default_value, Arena* arena) {
 | 
	
		
			
				|  |  | -    if (arena == NULL && ptr_ != default_value) {
 | 
	
		
			
				|  |  | -      delete ptr_;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Destroy(EmptyDefault, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  | +  void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // 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 the empty string. Assumes that |default_value|
 | 
	
		
			
				|  |  | -  // is an empty string.
 | 
	
		
			
				|  |  | -  inline void ClearToEmpty(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                           Arena* /* arena */) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      // Already set to default (which is empty) -- do nothing.
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      ptr_->clear();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  // Clears content, but keeps allocated std::string, to avoid the overhead of
 | 
	
		
			
				|  |  | +  // heap operations. After this returns, the content (as seen by the user) will
 | 
	
		
			
				|  |  | +  // always be the empty std::string. Assumes that |default_value| is an empty
 | 
	
		
			
				|  |  | +  // std::string.
 | 
	
		
			
				|  |  | +  void ClearToEmpty();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Clears content, assuming that the current value is not the empty string
 | 
	
		
			
				|  |  | -  // default.
 | 
	
		
			
				|  |  | -  inline void ClearNonDefaultToEmpty() { 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|.
 | 
	
		
			
				|  |  | -  inline void ClearToDefault(const ::std::string* default_value,
 | 
	
		
			
				|  |  | -                             Arena* /* arena */) {
 | 
	
		
			
				|  |  | -    if (ptr_ == default_value) {
 | 
	
		
			
				|  |  | -      // Already set to default -- do nothing.
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      // Have another allocated string -- rather than throwing this away and
 | 
	
		
			
				|  |  | -      // resetting ptr_ to the canonical default string instance, we just reuse
 | 
	
		
			
				|  |  | -      // this instance.
 | 
	
		
			
				|  |  | -      *ptr_ = *default_value;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  // Clears content, assuming that the current value is not the empty
 | 
	
		
			
				|  |  | +  // string default.
 | 
	
		
			
				|  |  | +  void ClearNonDefaultToEmpty();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Clears content, but keeps allocated std::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|.
 | 
	
		
			
				|  |  | +  void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Called from generated code / reflection runtime only. Resets value to point
 | 
	
		
			
				|  |  | -  // to a default string pointer, with the semantics that this ArenaStringPtr
 | 
	
		
			
				|  |  | -  // does not own the pointed-to memory. Disregards initial value of ptr_ (so
 | 
	
		
			
				|  |  | -  // this is the *ONLY* safe method to call after construction or when
 | 
	
		
			
				|  |  | -  // reinitializing after becoming the active field in a oneof union).
 | 
	
		
			
				|  |  | -  inline void UnsafeSetDefault(const ::std::string* default_value) {
 | 
	
		
			
				|  |  | -    // Casting away 'const' is safe here: accessors ensure that ptr_ is only
 | 
	
		
			
				|  |  | -    // returned as a const if it is equal to default_value.
 | 
	
		
			
				|  |  | -    ptr_ = const_cast< ::std::string*>(default_value);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  // to a default string pointer, with the semantics that this
 | 
	
		
			
				|  |  | +  // ArenaStringPtr does not own the pointed-to memory. Disregards initial value
 | 
	
		
			
				|  |  | +  // of ptr_ (so this is the *ONLY* safe method to call after construction or
 | 
	
		
			
				|  |  | +  // when reinitializing after becoming the active field in a oneof union).
 | 
	
		
			
				|  |  | +  inline void UnsafeSetDefault(const std::string* default_value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Returns a mutable pointer, but doesn't initialize the string to the
 | 
	
		
			
				|  |  | +  // default value.
 | 
	
		
			
				|  |  | +  std::string* MutableNoArenaNoDefault(const std::string* default_value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Get a mutable pointer with unspecified contents.
 | 
	
		
			
				|  |  | +  // Similar to `MutableNoArenaNoDefault`, but also handles the arena case.
 | 
	
		
			
				|  |  | +  // If the value was donated, the contents are discarded.
 | 
	
		
			
				|  |  | +  std::string* MutableNoCopy(const std::string* default_value,
 | 
	
		
			
				|  |  | +                             ::google::protobuf::Arena* arena);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Destroy the string. Assumes `arena == nullptr`.
 | 
	
		
			
				|  |  | -  inline void DestroyNoArena(const ::std::string* default_value) {
 | 
	
		
			
				|  |  | -    if (ptr_ != default_value) {
 | 
	
		
			
				|  |  | -      delete ptr_;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Internal accessor used only at parse time to provide direct access to the
 | 
	
		
			
				|  |  | -  // raw pointer from the shared parse routine (in the non-arenas case). The
 | 
	
		
			
				|  |  | -  // parse routine does the string allocation in order to save code size in the
 | 
	
		
			
				|  |  | -  // generated parsing code.
 | 
	
		
			
				|  |  | -  inline ::std::string** UnsafeRawStringPointer() { return &ptr_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  inline bool IsDefault(const ::std::string* default_value) const {
 | 
	
		
			
				|  |  | -    return ptr_ == default_value;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  void DestroyNoArena(const std::string* default_value);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Internal accessors!!!!
 | 
	
		
			
				|  |  | -  void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) {
 | 
	
		
			
				|  |  | -    ptr_ = value.Get();
 | 
	
		
			
				|  |  | +  // Internal setter used only at parse time to directly set a donated string
 | 
	
		
			
				|  |  | +  // value.
 | 
	
		
			
				|  |  | +  void UnsafeSetTaggedPointer(TaggedPtr<std::string> value) {
 | 
	
		
			
				|  |  | +    tagged_ptr_ = value;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // Generated code only! An optimization, in certain cases the generated
 | 
	
		
			
				|  |  | -  // code is certain we can obtain a string with no default checks and
 | 
	
		
			
				|  |  | +  // code is certain we can obtain a std::string with no default checks and
 | 
	
		
			
				|  |  |    // tag tests.
 | 
	
		
			
				|  |  | -  ::std::string* UnsafeMutablePointer() { return ptr_; }
 | 
	
		
			
				|  |  | +  std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  inline bool IsDefault(const std::string* default_value) const {
 | 
	
		
			
				|  |  | +    // Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the
 | 
	
		
			
				|  |  | +    // actual std::string pointer (and if !IsString(), ptr_ will never be equal
 | 
	
		
			
				|  |  | +    // to any aligned |default_value| pointer). The key is that we want to avoid
 | 
	
		
			
				|  |  | +    // masking in the fastpath const-pointer Get() case for non-arena code.
 | 
	
		
			
				|  |  | +    return tagged_ptr_.UnsafeGet() == default_value;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | -  ::std::string* ptr_;
 | 
	
		
			
				|  |  | +  TaggedPtr<std::string> tagged_ptr_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  bool IsDonatedString() const { return false; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Slow paths.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PROTOBUF_NOINLINE
 | 
	
		
			
				|  |  | -  void CreateInstance(Arena* arena, const ::std::string* initial_value) {
 | 
	
		
			
				|  |  | -    GOOGLE_DCHECK(initial_value != NULL);
 | 
	
		
			
				|  |  | -    // uses "new ::std::string" when arena is nullptr
 | 
	
		
			
				|  |  | -    ptr_ = Arena::Create< ::std::string>(arena, *initial_value);
 | 
	
		
			
				|  |  | +  // MutableSlow requires that !IsString() || IsDefault
 | 
	
		
			
				|  |  | +  // Variadic to support 0 args for EmptyDefault and 1 arg for LazyString.
 | 
	
		
			
				|  |  | +  template <typename... Lazy>
 | 
	
		
			
				|  |  | +  std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
 | 
	
		
			
				|  |  | +  tagged_ptr_.Set(const_cast<std::string*>(value));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline void ArenaStringPtr::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
 | 
	
		
			
				|  |  | +  // std::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 std::string, to
 | 
	
		
			
				|  |  | +  // ensure that we do not try to mutate default_value itself.
 | 
	
		
			
				|  |  | +  if (IsDefault(default_value) && other->IsDefault(default_value)) {
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  PROTOBUF_NOINLINE
 | 
	
		
			
				|  |  | -  void CreateInstanceNoArena(const ::std::string* initial_value) {
 | 
	
		
			
				|  |  | -    GOOGLE_DCHECK(initial_value != NULL);
 | 
	
		
			
				|  |  | -    ptr_ = new ::std::string(*initial_value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (default_value == nullptr) {
 | 
	
		
			
				|  |  | +    // If we have non-empty default, then `default_value` is null and we can't
 | 
	
		
			
				|  |  | +    // call Mutable the same way. Just do the regular swap.
 | 
	
		
			
				|  |  | +    std::swap(tagged_ptr_, other->tagged_ptr_);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    std::string* this_ptr = Mutable(EmptyDefault{}, arena);
 | 
	
		
			
				|  |  | +    std::string* other_ptr = other->Mutable(EmptyDefault{}, arena);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this_ptr->swap(*other_ptr);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +  std::swap(tagged_ptr_, other->tagged_ptr_);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
 | 
	
		
			
				|  |  | +  // Unconditionally mask away the tag.
 | 
	
		
			
				|  |  | +  tagged_ptr_.Get()->clear();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline std::string* ArenaStringPtr::MutableNoArenaNoDefault(
 | 
	
		
			
				|  |  | +    const std::string* default_value) {
 | 
	
		
			
				|  |  | +  // VERY IMPORTANT for performance and code size: this will reduce to a member
 | 
	
		
			
				|  |  | +  // variable load, a pointer check (against |default_value|, in practice a
 | 
	
		
			
				|  |  | +  // static global) and a branch to the slowpath (which calls operator new and
 | 
	
		
			
				|  |  | +  // the ctor). DO NOT add any tagged-pointer operations here.
 | 
	
		
			
				|  |  | +  if (IsDefault(default_value)) {
 | 
	
		
			
				|  |  | +    std::string* new_string = new std::string();
 | 
	
		
			
				|  |  | +    tagged_ptr_.Set(new_string);
 | 
	
		
			
				|  |  | +    return new_string;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return UnsafeMutablePointer();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
 | 
	
		
			
				|  |  | +  if (!IsDefault(default_value)) {
 | 
	
		
			
				|  |  | +    delete UnsafeMutablePointer();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
 | 
	
		
			
				|  |  | +  GOOGLE_DCHECK(!tagged_ptr_.IsTagged());
 | 
	
		
			
				|  |  | +  GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr);
 | 
	
		
			
				|  |  | +  return tagged_ptr_.UnsafeGet();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }  // namespace internal
 | 
	
		
			
				|  |  |  }  // namespace protobuf
 | 
	
		
			
				|  |  |  }  // namespace google
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  #include <google/protobuf/port_undef.inc>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #endif  // GOOGLE_PROTOBUF_ARENASTRING_H__
 |