Commit 18c1ffe0df335a46cddbeb96e2cb939d850df9fa

Authored by m-holger
1 parent 38cf7c16

Change underlying data structure of QPDF_Array in non-sparse mode to std::vector

libqpdf/OHArray.cc
... ... @@ -5,120 +5,82 @@
5 5  
6 6 #include <stdexcept>
7 7  
8   -OHArray::OHArray() :
9   - n_elements(0)
  8 +static const QPDFObjectHandle null_oh = QPDFObjectHandle::newNull();
  9 +
  10 +OHArray::OHArray()
10 11 {
11 12 }
12 13  
13 14 size_t
14 15 OHArray::size() const
15 16 {
16   - return this->n_elements;
  17 + return elements.size();
17 18 }
18 19  
19 20 void
20 21 OHArray::append(QPDFObjectHandle oh)
21 22 {
22   - if (!oh.isDirectNull()) {
23   - this->elements[this->n_elements] = oh;
24   - }
25   - ++this->n_elements;
  23 + elements.push_back(oh.getObj());
26 24 }
27 25  
28 26 void
29 27 OHArray::append(std::shared_ptr<QPDFObject>&& obj)
30 28 {
31   - if (obj->getTypeCode() != ::ot_null || !obj->getObjGen().isIndirect()) {
32   - this->elements[this->n_elements] = std::move(obj);
33   - }
34   - ++this->n_elements;
  29 + elements.push_back(std::move(obj));
35 30 }
36 31  
37 32 QPDFObjectHandle
38 33 OHArray::at(size_t idx) const
39 34 {
40   - if (idx >= this->n_elements) {
  35 + if (idx >= elements.size()) {
41 36 throw std::logic_error(
42 37 "INTERNAL ERROR: bounds error accessing OHArray element");
43 38 }
44   - auto const& iter = this->elements.find(idx);
45   - if (iter == this->elements.end()) {
46   - return QPDFObjectHandle::newNull();
47   - } else {
48   - return (*iter).second;
49   - }
50   -}
51   -
52   -void
53   -OHArray::remove_last()
54   -{
55   - if (this->n_elements == 0) {
56   - throw std::logic_error("INTERNAL ERROR: attempt to remove"
57   - " last item from empty OHArray");
58   - }
59   - --this->n_elements;
60   - this->elements.erase(this->n_elements);
  39 + auto const& obj = elements.at(idx);
  40 + return obj ? obj : null_oh;
61 41 }
62 42  
63 43 void
64 44 OHArray::disconnect()
65 45 {
66   - for (auto& iter: this->elements) {
67   - QPDFObjectHandle::DisconnectAccess::disconnect(iter.second);
  46 + for (auto const& iter: elements) {
  47 + if (iter) {
  48 + QPDFObjectHandle oh = iter;
  49 + QPDFObjectHandle::DisconnectAccess::disconnect(oh);
  50 + }
68 51 }
69 52 }
70 53  
71 54 void
72 55 OHArray::setAt(size_t idx, QPDFObjectHandle oh)
73 56 {
74   - if (idx >= this->n_elements) {
  57 + if (idx >= elements.size()) {
75 58 throw std::logic_error("bounds error setting item in OHArray");
76 59 }
77   - if (oh.isDirectNull()) {
78   - this->elements.erase(idx);
79   - } else {
80   - this->elements[idx] = oh;
81   - }
  60 + elements[idx] = oh.getObj();
82 61 }
83 62  
84 63 void
85 64 OHArray::erase(size_t idx)
86 65 {
87   - if (idx >= this->n_elements) {
  66 + if (idx >= elements.size()) {
88 67 throw std::logic_error("bounds error erasing item from OHArray");
89 68 }
90   - decltype(this->elements) dest;
91   - for (auto const& iter: this->elements) {
92   - if (iter.first < idx) {
93   - dest.insert(iter);
94   - } else if (iter.first > idx) {
95   - dest[iter.first - 1] = iter.second;
96   - }
97   - }
98   - this->elements = dest;
99   - --this->n_elements;
  69 + int n = int(idx);
  70 + elements.erase(elements.cbegin() + n);
100 71 }
101 72  
102 73 void
103 74 OHArray::insert(size_t idx, QPDFObjectHandle oh)
104 75 {
105   - if (idx > this->n_elements) {
  76 + if (idx > elements.size()) {
106 77 throw std::logic_error("bounds error inserting item to OHArray");
107   - } else if (idx == this->n_elements) {
  78 + } else if (idx == elements.size()) {
108 79 // Allow inserting to the last position
109   - append(oh);
  80 + append(oh.getObj());
110 81 } else {
111   - decltype(this->elements) dest;
112   - for (auto const& iter: this->elements) {
113   - if (iter.first < idx) {
114   - dest.insert(iter);
115   - } else {
116   - dest[iter.first + 1] = iter.second;
117   - }
118   - }
119   - this->elements = dest;
120   - this->elements[idx] = oh;
121   - ++this->n_elements;
  82 + int n = int(idx);
  83 + elements.insert(elements.cbegin() + n, oh.getObj());
122 84 }
123 85 }
124 86  
... ... @@ -126,23 +88,12 @@ OHArray
126 88 OHArray::copy()
127 89 {
128 90 OHArray result;
129   - result.n_elements = this->n_elements;
130   - for (auto const& element: this->elements) {
131   - auto value = element.second;
132   - result.elements[element.first] =
133   - value.isIndirect() ? value : value.shallowCopy();
  91 + result.elements.reserve(elements.size());
  92 + for (auto const& element: elements) {
  93 + result.elements.push_back(
  94 + element ? (element->getObjGen().isIndirect() ? element
  95 + : element->copy())
  96 + : element);
134 97 }
135 98 return result;
136 99 }
137   -
138   -OHArray::const_iterator
139   -OHArray::begin() const
140   -{
141   - return this->elements.begin();
142   -}
143   -
144   -OHArray::const_iterator
145   -OHArray::end() const
146   -{
147   - return this->elements.end();
148   -}
... ...
libqpdf/QPDF_Array.cc
... ... @@ -205,11 +205,7 @@ QPDF_Array::setFromVector(std::vector&lt;std::shared_ptr&lt;QPDFObject&gt;&gt;&amp;&amp; v)
205 205 } else {
206 206 elements = OHArray();
207 207 for (auto&& item: v) {
208   - if (item) {
209   - elements.append(item);
210   - } else {
211   - ++elements.n_elements;
212   - }
  208 + elements.append(std::move(item));
213 209 }
214 210 }
215 211 }
... ...
libqpdf/qpdf/OHArray.hh
... ... @@ -2,7 +2,9 @@
2 2 #define QPDF_OHARRAY_HH
3 3  
4 4 #include <qpdf/QPDFObjectHandle.hh>
5   -#include <unordered_map>
  5 +#include <qpdf/QPDFObject_private.hh>
  6 +
  7 +#include <vector>
6 8  
7 9 class QPDF_Array;
8 10  
... ... @@ -14,22 +16,15 @@ class OHArray
14 16 void append(QPDFObjectHandle oh);
15 17 void append(std::shared_ptr<QPDFObject>&& obj);
16 18 QPDFObjectHandle at(size_t idx) const;
17   - void remove_last();
18 19 void setAt(size_t idx, QPDFObjectHandle oh);
19 20 void erase(size_t idx);
20 21 void insert(size_t idx, QPDFObjectHandle oh);
21 22 OHArray copy();
22 23 void disconnect();
23 24  
24   - typedef std::unordered_map<size_t, QPDFObjectHandle>::const_iterator
25   - const_iterator;
26   - const_iterator begin() const;
27   - const_iterator end() const;
28   -
29 25 private:
30 26 friend class QPDF_Array;
31   - std::unordered_map<size_t, QPDFObjectHandle> elements;
32   - size_t n_elements;
  27 + std::vector<std::shared_ptr<QPDFObject>> elements;
33 28 };
34 29  
35 30 #endif // QPDF_OHARRAY_HH
... ...