123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- #pragma once
- #include "iterator.h"
- #include "utility.h"
- #include <util/generic/fwd.h>
- #include <util/system/align.h>
- #include <util/system/compiler.h>
- #include <util/system/yassert.h>
- #include <cstring>
- class TBuffer {
- public:
- using TIterator = char*;
- using TConstIterator = const char*;
- TBuffer(size_t len = 0);
- TBuffer(const char* buf, size_t len);
- TBuffer(const TBuffer& b)
- : Data_(nullptr)
- , Len_(0)
- , Pos_(0)
- {
- *this = b;
- }
- TBuffer(TBuffer&& b) noexcept;
- TBuffer& operator=(TBuffer&& b) noexcept;
- TBuffer& operator=(const TBuffer& b) {
- if (this != &b) {
- Assign(b.Data(), b.Size());
- }
- return *this;
- }
- ~TBuffer();
- inline void Clear() noexcept {
- Pos_ = 0;
- }
- inline void EraseBack(size_t n) noexcept {
- Y_ASSERT(n <= Pos_);
- Pos_ -= n;
- }
- Y_REINITIALIZES_OBJECT inline void Reset() noexcept {
- TBuffer().Swap(*this);
- }
- inline void Assign(const char* data, size_t len) {
- Clear();
- Append(data, len);
- }
- inline void Assign(const char* b, const char* e) {
- Assign(b, NonNegativeDistance(b, e));
- }
- inline char* Data() noexcept {
- return Data_;
- }
- inline const char* Data() const noexcept {
- return Data_;
- }
- inline char* Pos() noexcept {
- return Data_ + Pos_;
- }
- inline const char* Pos() const noexcept {
- return Data_ + Pos_;
- }
- /// Used space in bytes (do not mix with Capacity!)
- inline size_t Size() const noexcept {
- return Pos_;
- }
- Y_PURE_FUNCTION inline bool Empty() const noexcept {
- return !Size();
- }
- inline explicit operator bool() const noexcept {
- return Size();
- }
- inline size_t Avail() const noexcept {
- return Len_ - Pos_;
- }
- void Append(const char* buf, size_t len);
- inline void Append(const char* b, const char* e) {
- Append(b, NonNegativeDistance(b, e));
- }
- inline void Append(char ch) {
- if (Len_ == Pos_) {
- Reserve(Len_ + 1);
- }
- *(Data() + Pos_++) = ch;
- }
- void Fill(char ch, size_t len);
- // Method is useful when first messages from buffer are processed, and
- // the last message in buffer is incomplete, so we need to move partial
- // message to the begin of the buffer and continue filling the buffer
- // from the network.
- inline void Chop(size_t pos, size_t count) {
- const auto end = pos + count;
- Y_ASSERT(end <= Pos_);
- if (count == 0) {
- return;
- } else if (count == Pos_) {
- Pos_ = 0;
- } else {
- memmove(Data_ + pos, Data_ + end, Pos_ - end);
- Pos_ -= count;
- }
- }
- inline void ChopHead(size_t count) {
- Chop(0U, count);
- }
- inline void Proceed(size_t pos) {
- // Y_ASSERT(pos <= Len_); // see discussion in REVIEW:29021
- Resize(pos);
- }
- inline void Advance(size_t len) {
- Resize(Pos_ + len);
- }
- inline void Reserve(size_t len) {
- if (len > Len_) {
- DoReserve(len);
- }
- }
- inline void ReserveExactNeverCallMeInSaneCode(size_t len) {
- if (len > Len_) {
- Realloc(len);
- }
- }
- inline void ShrinkToFit() {
- if (Pos_ < Len_) {
- Realloc(Pos_);
- }
- }
- inline void Resize(size_t len) {
- Reserve(len);
- Pos_ = len;
- }
- // Method works like Resize, but allocates exact specified number of bytes
- // rather than rounded up to next power of 2
- // Use with care
- inline void ResizeExactNeverCallMeInSaneCode(size_t len) {
- ReserveExactNeverCallMeInSaneCode(len);
- Pos_ = len;
- }
- inline size_t Capacity() const noexcept {
- return Len_;
- }
- inline void AlignUp(size_t align, char fillChar = '\0') {
- size_t diff = ::AlignUp(Pos_, align) - Pos_;
- while (diff-- > 0) {
- Append(fillChar);
- }
- }
- inline char* data() noexcept {
- return Data();
- }
- inline const char* data() const noexcept {
- return Data();
- }
- inline size_t size() const noexcept {
- return Size();
- }
- inline void Swap(TBuffer& r) noexcept {
- DoSwap(Data_, r.Data_);
- DoSwap(Len_, r.Len_);
- DoSwap(Pos_, r.Pos_);
- }
- /*
- * after this call buffer becomes empty
- */
- void AsString(TString& s);
- /*
- * iterator-like interface
- */
- inline TIterator Begin() noexcept {
- return Data();
- }
- inline TIterator End() noexcept {
- return Begin() + Size();
- }
- inline TConstIterator Begin() const noexcept {
- return Data();
- }
- inline TConstIterator End() const noexcept {
- return Begin() + Size();
- }
- bool operator==(const TBuffer& other) const noexcept {
- if (Empty()) {
- return other.Empty();
- }
- return Size() == other.Size() && 0 == std::memcmp(Data(), other.Data(), Size());
- }
- bool operator!=(const TBuffer& other) const noexcept {
- return !(*this == other);
- }
- private:
- void DoReserve(size_t len);
- void Realloc(size_t len);
- private:
- char* Data_;
- size_t Len_;
- size_t Pos_;
- };
|