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,120 +5,82 @@
5 5
6 #include <stdexcept> 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 size_t 14 size_t
14 OHArray::size() const 15 OHArray::size() const
15 { 16 {
16 - return this->n_elements; 17 + return elements.size();
17 } 18 }
18 19
19 void 20 void
20 OHArray::append(QPDFObjectHandle oh) 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 void 26 void
29 OHArray::append(std::shared_ptr<QPDFObject>&& obj) 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 QPDFObjectHandle 32 QPDFObjectHandle
38 OHArray::at(size_t idx) const 33 OHArray::at(size_t idx) const
39 { 34 {
40 - if (idx >= this->n_elements) { 35 + if (idx >= elements.size()) {
41 throw std::logic_error( 36 throw std::logic_error(
42 "INTERNAL ERROR: bounds error accessing OHArray element"); 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 void 43 void
64 OHArray::disconnect() 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 void 54 void
72 OHArray::setAt(size_t idx, QPDFObjectHandle oh) 55 OHArray::setAt(size_t idx, QPDFObjectHandle oh)
73 { 56 {
74 - if (idx >= this->n_elements) { 57 + if (idx >= elements.size()) {
75 throw std::logic_error("bounds error setting item in OHArray"); 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 void 63 void
85 OHArray::erase(size_t idx) 64 OHArray::erase(size_t idx)
86 { 65 {
87 - if (idx >= this->n_elements) { 66 + if (idx >= elements.size()) {
88 throw std::logic_error("bounds error erasing item from OHArray"); 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 void 73 void
103 OHArray::insert(size_t idx, QPDFObjectHandle oh) 74 OHArray::insert(size_t idx, QPDFObjectHandle oh)
104 { 75 {
105 - if (idx > this->n_elements) { 76 + if (idx > elements.size()) {
106 throw std::logic_error("bounds error inserting item to OHArray"); 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 // Allow inserting to the last position 79 // Allow inserting to the last position
109 - append(oh); 80 + append(oh.getObj());
110 } else { 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,23 +88,12 @@ OHArray
126 OHArray::copy() 88 OHArray::copy()
127 { 89 {
128 OHArray result; 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 return result; 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,11 +205,7 @@ QPDF_Array::setFromVector(std::vector&lt;std::shared_ptr&lt;QPDFObject&gt;&gt;&amp;&amp; v)
205 } else { 205 } else {
206 elements = OHArray(); 206 elements = OHArray();
207 for (auto&& item: v) { 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,7 +2,9 @@
2 #define QPDF_OHARRAY_HH 2 #define QPDF_OHARRAY_HH
3 3
4 #include <qpdf/QPDFObjectHandle.hh> 4 #include <qpdf/QPDFObjectHandle.hh>
5 -#include <unordered_map> 5 +#include <qpdf/QPDFObject_private.hh>
  6 +
  7 +#include <vector>
6 8
7 class QPDF_Array; 9 class QPDF_Array;
8 10
@@ -14,22 +16,15 @@ class OHArray @@ -14,22 +16,15 @@ class OHArray
14 void append(QPDFObjectHandle oh); 16 void append(QPDFObjectHandle oh);
15 void append(std::shared_ptr<QPDFObject>&& obj); 17 void append(std::shared_ptr<QPDFObject>&& obj);
16 QPDFObjectHandle at(size_t idx) const; 18 QPDFObjectHandle at(size_t idx) const;
17 - void remove_last();  
18 void setAt(size_t idx, QPDFObjectHandle oh); 19 void setAt(size_t idx, QPDFObjectHandle oh);
19 void erase(size_t idx); 20 void erase(size_t idx);
20 void insert(size_t idx, QPDFObjectHandle oh); 21 void insert(size_t idx, QPDFObjectHandle oh);
21 OHArray copy(); 22 OHArray copy();
22 void disconnect(); 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 private: 25 private:
30 friend class QPDF_Array; 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 #endif // QPDF_OHARRAY_HH 30 #endif // QPDF_OHARRAY_HH