aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/buffer.cpp
blob: dd60963873bbb656e1b58f0419e982956dda3f23 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "buffer.h"
#include "mem_copy.h"
#include "string.h"
#include "ymath.h"

#include <util/system/sys_alloc.h>
#include <util/system/sanitizers.h>

TBuffer::TBuffer(size_t len)
    : Data_(nullptr) 
    , Len_(0)
    , Pos_(0)
{
    Reserve(len);
}

TBuffer::TBuffer(TBuffer&& b) noexcept
    : Data_(nullptr)
    , Len_(0)
    , Pos_(0)
{
    Swap(b);
}

TBuffer::TBuffer(const char* buf, size_t len)
    : Data_(nullptr) 
    , Len_(0)
    , Pos_(0)
{
    Append(buf, len);
}

TBuffer& TBuffer::operator=(TBuffer&& b) noexcept {
    y_deallocate(Data_);

    Data_ = b.Data_;
    Len_ = b.Len_;
    Pos_ = b.Pos_;

    b.Data_ = nullptr;
    b.Len_ = 0;
    b.Pos_ = 0;

    return *this;
}

void TBuffer::Append(const char* buf, size_t len) {
    if (len > Avail()) {
        Reserve(Pos_ + len);
    }

    Y_ASSERT(len <= Avail());

    MemCopy(Data() + Pos_, buf, len);
    NSan::Unpoison(Data() + Pos_, len);
    Pos_ += len;

    Y_ASSERT(Pos_ <= Len_);
}

void TBuffer::Fill(char ch, size_t len) {
    if (len > Avail()) {
        Reserve(Pos_ + len);
    }

    Y_ASSERT(len <= Avail());

    memset(Data() + Pos_, ch, len);
    NSan::Unpoison(Data() + Pos_, len);
    Pos_ += len;

    Y_ASSERT(Pos_ <= Len_);
}

void TBuffer::DoReserve(size_t realLen) {
    // FastClp2<T>(x) returns 0 on x from [Max<T>/2 + 2, Max<T>]
    const size_t len = Max<size_t>(FastClp2(realLen), realLen);

    Y_ASSERT(realLen > Len_); 
    Y_ASSERT(len >= realLen); 

    Realloc(len);
}

void TBuffer::Realloc(size_t len) {
    Y_ASSERT(Pos_ <= len); 

    Data_ = (char*)y_reallocate(Data_, len);
    Len_ = len;
}

TBuffer::~TBuffer() {
    y_deallocate(Data_);
}

void TBuffer::AsString(TString& s) {
    s.assign(Data(), Size());
    Clear();
}