#pragma once #include "ref.h" #include "ref_counted.h" namespace NYT { //////////////////////////////////////////////////////////////////////////////// //! Default memory tag for TBlob. struct TDefaultBlobTag { }; //! A home-grown optimized replacement for |std::vector<char>| suitable for carrying //! large chunks of data. /*! * Compared to |std::vector<char>|, this class supports uninitialized allocations * when explicitly requested to. */ class TBlob { public: //! Constructs a blob with a given size. explicit TBlob( TRefCountedTypeCookie tagCookie = GetRefCountedTypeCookie<TDefaultBlobTag>(), size_t size = 0, bool initiailizeStorage = true, bool pageAligned = false); //! Copies a chunk of memory into a new instance. TBlob( TRefCountedTypeCookie tagCookie, TRef data, bool pageAligned = false); //! Copies the data. TBlob(const TBlob& other); //! Moves the data (takes the ownership). TBlob(TBlob&& other) noexcept; //! Reclaims the memory. ~TBlob(); //! Ensures that capacity is at least #capacity. void Reserve(size_t newCapacity); //! Changes the size to #newSize. /*! * If #size exceeds the current capacity, * we make sure the new capacity grows exponentially. * Hence calling #Resize N times to increase the size by N only * takes amortized O(1) time per call. */ void Resize(size_t newSize, bool initializeStorage = true); //! Returns the start pointer. Y_FORCE_INLINE const char* Begin() const { return Begin_; } //! Returns the start pointer. Y_FORCE_INLINE char* Begin() { return Begin_; } //! Returns the end pointer. Y_FORCE_INLINE const char* End() const { return Begin_ + Size_; } //! Returns the end pointer. Y_FORCE_INLINE char* End() { return Begin_ + Size_; } //! Returns the size. Y_FORCE_INLINE size_t size() const { return Size_; } //! Returns the size. Y_FORCE_INLINE size_t Size() const { return Size_; } //! Returns the capacity. Y_FORCE_INLINE size_t Capacity() const { return Capacity_; } //! Returns the TStringBuf instance for the occupied part of the blob. Y_FORCE_INLINE TStringBuf ToStringBuf() const { return TStringBuf(Begin_, Size_); } //! Returns the TRef instance for the occupied part of the blob. Y_FORCE_INLINE TRef ToRef() const { return TRef(Begin_, Size_); } //! Provides by-value access to the underlying storage. Y_FORCE_INLINE char operator [] (size_t index) const { return Begin_[index]; } //! Provides by-ref access to the underlying storage. Y_FORCE_INLINE char& operator [] (size_t index) { return Begin_[index]; } //! Clears the instance but does not reclaim the memory. Y_FORCE_INLINE void Clear() { Size_ = 0; } //! Returns |true| if size is zero. Y_FORCE_INLINE bool IsEmpty() const { return Size_ == 0; } //! Overwrites the current instance. TBlob& operator = (const TBlob& rhs); //! Takes the ownership. TBlob& operator = (TBlob&& rhs) noexcept; //! Appends a chunk of memory to the end. void Append(const void* data, size_t size); //! Appends a chunk of memory to the end. void Append(TRef ref); //! Appends a single char to the end. void Append(char ch); //! Swaps the current and other instances void Swap(TBlob& other); friend void swap(TBlob& left, TBlob& right); private: char* Begin_ = nullptr; size_t Size_ = 0; size_t Capacity_ = 0; bool PageAligned_ = false; #ifdef YT_ENABLE_REF_COUNTED_TRACKING TRefCountedTypeCookie TagCookie_ = NullRefCountedTypeCookie; #endif char* DoAllocate(size_t newCapacity); void Allocate(size_t newCapacity); void Reallocate(size_t newCapacity); void Free(); void Reset(); void SetTagCookie(TRefCountedTypeCookie tagCookie); void SetTagCookie(const TBlob& other); }; void swap(TBlob& left, TBlob& right); //////////////////////////////////////////////////////////////////////////////// } // namespace NYT