aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/OHArray.cc
blob: 436fa4f2d71124c8b039334a94b4a97bbcebee2e (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
137
138
139
140
141
142
143
144
145
146
147
148
#include <qpdf/OHArray.hh>

#include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDFObject_private.hh>

#include <stdexcept>

OHArray::OHArray() :
    n_elements(0)
{
}

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

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

void
OHArray::append(std::shared_ptr<QPDFObject>&& obj)
{
    if (obj->getTypeCode() != ::ot_null || !obj->getObjGen().isIndirect()) {
        this->elements[this->n_elements] = std::move(obj);
    }
    ++this->n_elements;
}

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

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

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

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

void
OHArray::erase(size_t idx)
{
    if (idx >= this->n_elements) {
        throw std::logic_error("bounds error erasing item from OHArray");
    }
    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
OHArray::insert(size_t idx, QPDFObjectHandle oh)
{
    if (idx > this->n_elements) {
        throw std::logic_error("bounds error inserting item to OHArray");
    } 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;
    }
}

OHArray
OHArray::copy()
{
    OHArray 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;
}

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

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