aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/SparseOHArray.cc
blob: 567f9d0bf90a671c91a7f0da9023900d48921f82 (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
134
135
136
#include <qpdf/SparseOHArray.hh>

#include <stdexcept>

SparseOHArray::SparseOHArray() :
    n_elements(0)
{
}

size_t
SparseOHArray::size() const
{
    return this->n_elements;
}

void
SparseOHArray::append(QPDFObjectHandle oh)
{
    if (!oh.isDirectNull()) {
        this->elements[this->n_elements] = oh;
    }
    ++this->n_elements;
}

QPDFObjectHandle
SparseOHArray::at(size_t idx) const
{
    if (idx >= this->n_elements) {
        throw std::logic_error(
            "INTERNAL ERROR: bounds error accessing SparseOHArray element");
    }
    auto const& iter = this->elements.find(idx);
    if (iter == this->elements.end()) {
        return QPDFObjectHandle::newNull();
    } else {
        return (*iter).second;
    }
}

void
SparseOHArray::remove_last()
{
    if (this->n_elements == 0) {
        throw std::logic_error("INTERNAL ERROR: attempt to remove"
                               " last item from empty SparseOHArray");
    }
    --this->n_elements;
    this->elements.erase(this->n_elements);
}

void
SparseOHArray::disconnect()
{
    for (auto& iter: this->elements) {
        QPDFObjectHandle::DisconnectAccess::disconnect(iter.second);
    }
}

void
SparseOHArray::setAt(size_t idx, QPDFObjectHandle oh)
{
    if (idx >= this->n_elements) {
        throw std::logic_error("bounds error setting item in SparseOHArray");
    }
    if (oh.isDirectNull()) {
        this->elements.erase(idx);
    } else {
        this->elements[idx] = oh;
    }
}

void
SparseOHArray::erase(size_t idx)
{
    if (idx >= this->n_elements) {
        throw std::logic_error("bounds error erasing item from SparseOHArray");
    }
    decltype(this->elements) dest;
    for (auto const& iter: this->elements) {
        if (iter.first < idx) {
            dest.insert(iter);
        } else if (iter.first > idx) {
            dest[iter.first - 1] = iter.second;
        }
    }
    this->elements = dest;
    --this->n_elements;
}

void
SparseOHArray::insert(size_t idx, QPDFObjectHandle oh)
{
    if (idx > this->n_elements) {
        throw std::logic_error("bounds error inserting item to SparseOHArray");
    } else if (idx == this->n_elements) {
        // Allow inserting to the last position
        append(oh);
    } else {
        decltype(this->elements) dest;
        for (auto const& iter: this->elements) {
            if (iter.first < idx) {
                dest.insert(iter);
            } else {
                dest[iter.first + 1] = iter.second;
            }
        }
        this->elements = dest;
        this->elements[idx] = oh;
        ++this->n_elements;
    }
}

SparseOHArray
SparseOHArray::copy()
{
    SparseOHArray result;
    result.n_elements = this->n_elements;
    for (auto const& element: this->elements) {
        auto value = element.second;
        result.elements[element.first] =
            value.isIndirect() ? value : value.shallowCopy();
    }
    return result;
}

SparseOHArray::const_iterator
SparseOHArray::begin() const
{
    return this->elements.begin();
}

SparseOHArray::const_iterator
SparseOHArray::end() const
{
    return this->elements.end();
}