#pragma once #include #include #include #include class TMemoryMap; class IInputStream; class TFile; class TBuffer; enum class EMappingMode { /// Just mmap a file allowing lazy page loading at access Standard, /// Same as previous but warmup the buffer with sequential access to it's data Precharged, /// Try to lock file in memory so that it doesn't wash away. See mlock(2) Locked }; /// @addtogroup BLOBs /// @{ class TBlob { public: class TBase { public: inline TBase() noexcept = default; virtual ~TBase() = default; virtual void Ref() noexcept = 0; virtual void UnRef() noexcept = 0; }; private: struct TStorage { const void* Data; size_t Length; TBase* Base; inline TStorage(const void* data, size_t length, TBase* base) noexcept : Data(data) , Length(length) , Base(base) { } inline ~TStorage() = default; inline void Swap(TStorage& r) noexcept { DoSwap(Data, r.Data); DoSwap(Length, r.Length); DoSwap(Base, r.Base); } }; public: using value_type = ui8; using const_reference = const value_type&; using const_pointer = const value_type*; using const_iterator = const_pointer; /** * Constructs a null blob (data array points to nullptr). */ TBlob() noexcept : S_(nullptr, 0, nullptr) { } inline TBlob(const TBlob& r) noexcept : S_(r.S_) { Ref(); } TBlob(TBlob&& r) noexcept : TBlob() { this->Swap(r); } inline TBlob(const void* data, size_t length, TBase* base) noexcept : S_(data, length, base) { Ref(); } inline ~TBlob() { UnRef(); } inline TBlob& operator=(const TBlob& r) noexcept { TBlob(r).Swap(*this); return *this; } /// Swaps content of two data arrays. inline void Swap(TBlob& r) noexcept { S_.Swap(r.S_); } /// Returns a const reference to the data array. inline const void* Data() const noexcept { return S_.Data; } /// Returns the size of the data array in bytes. inline size_t Length() const noexcept { return S_.Length; } /// Checks if the object has an empty data array. Y_PURE_FUNCTION inline bool Empty() const noexcept { return !Length(); } /// Checks if the blob owns data Y_PURE_FUNCTION inline bool OwnsData() const noexcept { return S_.Base != nullptr; } /// Checks if the object has a data array. inline bool IsNull() const noexcept { return !Data(); } /// Returns a const pointer of char type to the data array. inline const char* AsCharPtr() const noexcept { return (const char*)Data(); } /// Returns a const pointer of unsigned char type to the data array. inline const unsigned char* AsUnsignedCharPtr() const noexcept { return (const unsigned char*)Data(); } inline TStringBuf AsStringBuf() const noexcept { return TStringBuf(AsCharPtr(), size()); } /// Drops the data array. inline void Drop() noexcept { TBlob().Swap(*this); } /* * Some stl-like methods */ /// Returns a const reference to the data array. /// result type is const ui8* which is not consistent with Data method above /// but it's consistent with operator[], Begin and End methods below /// Also it allows us to construct TArrayRef from TBlob inline const_pointer data() const noexcept { return static_cast(Data()); } /// Returns the size of the data array in bytes. inline size_t size() const noexcept { return Length(); } /// Returns the size of the data array in bytes. inline size_t Size() const noexcept { return Length(); } /// Standard iterator. inline const_iterator Begin() const noexcept { return AsUnsignedCharPtr(); } /// Standard iterator. inline const_iterator End() const noexcept { return Begin() + Size(); } inline value_type operator[](size_t n) const noexcept { return *(Begin() + n); } /// Shortcut to SubBlob(0, len) TBlob SubBlob(size_t len) const; /// Creates a new object from the provided range [begin, end) of internal data. No memory allocation and no copy. /// @details Increments the refcounter of the current object TBlob SubBlob(size_t begin, size_t end) const; /// Calls Copy() for the internal data. TBlob DeepCopy() const; /// Creates a new blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies the data content. static TBlob CopySingleThreaded(const void* data, size_t length); /// Creates a new blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies the data content. static TBlob Copy(const void* data, size_t length); /// Creates a blob which doesn't own data. No refcounter, no memory allocation, no data copy. static TBlob NoCopy(const void* data, size_t length); /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TString& path, EMappingMode); /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TString& path, EMappingMode); /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TFile& file, EMappingMode); /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TFile& file, EMappingMode); /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TString& path); /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TString& path); /// Creates a blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob FromFileSingleThreaded(const TFile& file); /// Creates a blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob FromFile(const TFile& file); // TODO: drop Precharged* functions. /// Creates a precharged blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob PrechargedFromFileSingleThreaded(const TString& path); /// Creates a precharged blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob PrechargedFromFile(const TString& path); /// Creates a precharged blob with a single-threaded (non atomic) refcounter. It maps the file content as data. static TBlob PrechargedFromFileSingleThreaded(const TFile& file); /// Creates a precharged blob with a multi-threaded (atomic) refcounter. It maps the file content as data. static TBlob PrechargedFromFile(const TFile& file); /// Creates a locked blob with a single-threaded (non atomic) refcounter. It maps the file on the path as data. static TBlob LockedFromFileSingleThreaded(const TString& path); /// Creates a locked blob with a multi-threaded (atomic) refcounter. It maps the file on the path as data. static TBlob LockedFromFile(const TString& path); /// Creates a locked blob with a single-threaded (non atomic) refcounter. It maps the file content as data. static TBlob LockedFromFileSingleThreaded(const TFile& file); /// Creates a locked blob with a multi-threaded (atomic) refcounter. It maps the file content as data. static TBlob LockedFromFile(const TFile& file); /// Creates a locked blob with a single-threaded (non atomic) refcounter from the mapped memory. static TBlob LockedFromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length); /// Creates a locked blob with a multi-threaded (atomic) refcounter from the mapped memory. static TBlob LockedFromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length); /// Creates a blob with a single-threaded (non atomic) refcounter from the mapped memory. static TBlob FromMemoryMapSingleThreaded(const TMemoryMap& map, ui64 offset, size_t length); /// Creates a blob with a multi-threaded (atomic) refcounter from the mapped memory. static TBlob FromMemoryMap(const TMemoryMap& map, ui64 offset, size_t length); /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the file on the path using pread(). static TBlob FromFileContentSingleThreaded(const TString& path); /// Creates a blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies data from the file on the path using pread(). static TBlob FromFileContent(const TString& path); /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the file using pread(). static TBlob FromFileContentSingleThreaded(const TFile& file); /// Creates a blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies data from the file using pread(). static TBlob FromFileContent(const TFile& file); /// Creates a blob with a single-threaded (non atomic) refcounter. Dynamically allocates memory and copies data from the provided range of the file content using pread(). static TBlob FromFileContentSingleThreaded(const TFile& file, ui64 offset, size_t length); /// Creates a blob with a multi-threaded (atomic) refcounter. Dynamically allocates memory and copies data from the provided range of the file content using pread(). static TBlob FromFileContent(const TFile& file, ui64 offset, size_t length); /// Creates a blob from the stream content with a single-threaded (non atomic) refcounter. static TBlob FromStreamSingleThreaded(IInputStream& in); /// Creates a blob from the stream content with a multi-threaded (atomic) refcounter. static TBlob FromStream(IInputStream& in); /// Creates a blob with a single-threaded (non atomic) refcounter. No memory allocation, no content copy. /// @details The input object becomes empty. static TBlob FromBufferSingleThreaded(TBuffer& in); /// Creates a blob with a multi-threaded (atomic) refcounter. No memory allocation, no content copy. /// @details The input object becomes empty. static TBlob FromBuffer(TBuffer& in); /// Creates a blob from TString with a single-threaded (non atomic) refcounter. static TBlob FromStringSingleThreaded(const TString& s); /// Creates a blob from TString with a single-threaded (non atomic) refcounter. Doesn't copy its content. static TBlob FromStringSingleThreaded(TString&& s); /// Creates a blob from TString with a multi-threaded (atomic) refcounter. static TBlob FromString(const TString& s); /// Creates a blob from TString with a multi-threaded (atomic) refcounter. Doesn't copy its content. static TBlob FromString(TString&& s); private: inline void Ref() noexcept { if (S_.Base) { S_.Base->Ref(); } } inline void UnRef() noexcept { if (S_.Base) { S_.Base->UnRef(); } } private: TStorage S_; }; /// @}