aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/Buffer.cc
blob: 20453a407c9d2cbaa9f405316724b8b139f2acf0 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <qpdf/assert_test.h>

#include <qpdf/Buffer.hh>

#include <cstring>

bool test_mode = false;

// During CI the Buffer copy constructor and copy assignment operator throw an assertion error to
// detect their accidental use. Call setTestMode to surpress the assertion errors for testing of
// copy construction and assignment.
void
Buffer::setTestMode() noexcept
{
    test_mode = true;
}

Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) :
    own_memory(own_memory),
    size(size),
    buf(nullptr)
{
    if (own_memory) {
        this->buf = (size ? new unsigned char[size] : nullptr);
    } else {
        this->buf = buf;
    }
}

Buffer::Members::Members(std::string&& content) :
    str(std::move(content)),
    own_memory(false),
    size(str.size()),
    buf(reinterpret_cast<unsigned char*>(str.data()))
{
}

Buffer::Members::~Members()
{
    if (this->own_memory) {
        delete[] this->buf;
    }
}

Buffer::Buffer() :
    m(new Members(0, nullptr, true))
{
}

Buffer::Buffer(size_t size) :
    m(new Members(size, nullptr, true))
{
}

Buffer::Buffer(std::string&& content) :
    m(new Members(std::move(content)))
{
}

Buffer::Buffer(unsigned char* buf, size_t size) :
    m(new Members(size, buf, false))
{
}

Buffer::Buffer(std::string& content) :
    m(new Members(content.size(), reinterpret_cast<unsigned char*>(content.data()), false))
{
}

Buffer::Buffer(Buffer const& rhs)
{
    assert(test_mode);
    copy(rhs);
}

Buffer&
Buffer::operator=(Buffer const& rhs)
{
    assert(test_mode);
    copy(rhs);
    return *this;
}

Buffer::Buffer(Buffer&& rhs) noexcept :
    m(std::move(rhs.m))
{
}

Buffer&
Buffer::operator=(Buffer&& rhs) noexcept
{
    std::swap(m, rhs.m);
    return *this;
}

void
Buffer::copy(Buffer const& rhs)
{
    if (this != &rhs) {
        m = std::unique_ptr<Members>(new Members(rhs.m->size, nullptr, true));
        if (m->size) {
            memcpy(m->buf, rhs.m->buf, m->size);
        }
    }
}

size_t
Buffer::getSize() const
{
    return m->size;
}

unsigned char const*
Buffer::getBuffer() const
{
    return m->buf;
}

unsigned char*
Buffer::getBuffer()
{
    return m->buf;
}

Buffer
Buffer::copy() const
{
    auto result = Buffer(m->size);
    if (m->size) {
        memcpy(result.m->buf, m->buf, m->size);
    }
    return result;
}