Commit e5f504b6c5dc34337cc0b316b4a7b1fca7e614b1

Authored by Jay Berkenbilt
1 parent a89d8a06

Use SparseOHArray in QPDF_Array

include/qpdf/QPDFObjectHandle.hh
... ... @@ -544,6 +544,10 @@ class QPDFObjectHandle
544 544 int getArrayNItems();
545 545 QPDF_DLL
546 546 QPDFObjectHandle getArrayItem(int n);
  547 + // Note: QPDF arrays internally optimize memory for arrays
  548 + // containing lots of nulls. Calling getArrayAsVector may cause a
  549 + // lot of memory to be allocated for very large arrays with lots
  550 + // of nulls.
547 551 QPDF_DLL
548 552 std::vector<QPDFObjectHandle> getArrayAsVector();
549 553 QPDF_DLL
... ... @@ -932,7 +936,6 @@ class QPDFObjectHandle
932 936 class ReleaseResolver
933 937 {
934 938 friend class QPDF_Dictionary;
935   - friend class QPDF_Array;
936 939 friend class QPDF_Stream;
937 940 friend class SparseOHArray;
938 941 private:
... ...
libqpdf/QPDF_Array.cc
... ... @@ -8,6 +8,11 @@ QPDF_Array::QPDF_Array(std::vector&lt;QPDFObjectHandle&gt; const&amp; v)
8 8 setFromVector(v);
9 9 }
10 10  
  11 +QPDF_Array::QPDF_Array(SparseOHArray const& items) :
  12 + elements(items)
  13 +{
  14 +}
  15 +
11 16 QPDF_Array::~QPDF_Array()
12 17 {
13 18 }
... ... @@ -15,21 +20,17 @@ QPDF_Array::~QPDF_Array()
15 20 void
16 21 QPDF_Array::releaseResolved()
17 22 {
18   - for (std::vector<QPDFObjectHandle>::iterator iter = this->items.begin();
19   - iter != this->items.end(); ++iter)
20   - {
21   - QPDFObjectHandle::ReleaseResolver::releaseResolved(*iter);
22   - }
  23 + this->elements.releaseResolved();
23 24 }
24 25  
25 26 std::string
26 27 QPDF_Array::unparse()
27 28 {
28 29 std::string result = "[ ";
29   - size_t size = this->items.size();
  30 + size_t size = this->elements.size();
30 31 for (size_t i = 0; i < size; ++i)
31 32 {
32   - result += this->items.at(i).unparse();
  33 + result += this->elements.at(i).unparse();
33 34 result += " ";
34 35 }
35 36 result += "]";
... ... @@ -40,10 +41,10 @@ JSON
40 41 QPDF_Array::getJSON()
41 42 {
42 43 JSON j = JSON::makeArray();
43   - size_t size = this->items.size();
  44 + size_t size = this->elements.size();
44 45 for (size_t i = 0; i < size; ++i)
45 46 {
46   - j.addArrayElement(this->items.at(i).getJSON());
  47 + j.addArrayElement(this->elements.at(i).getJSON());
47 48 }
48 49 return j;
49 50 }
... ... @@ -71,46 +72,44 @@ QPDF_Array::getNItems() const
71 72 {
72 73 // This should really return a size_t, but changing it would break
73 74 // a lot of code.
74   - return QIntC::to_int(this->items.size());
  75 + return QIntC::to_int(this->elements.size());
75 76 }
76 77  
77 78 QPDFObjectHandle
78 79 QPDF_Array::getItem(int n) const
79 80 {
80   - if ((n < 0) || (n >= QIntC::to_int(this->items.size())))
  81 + if ((n < 0) || (n >= QIntC::to_int(elements.size())))
81 82 {
82 83 throw std::logic_error(
83 84 "INTERNAL ERROR: bounds error accessing QPDF_Array element");
84 85 }
85   - return this->items.at(QIntC::to_size(n));
  86 + return this->elements.at(QIntC::to_size(n));
86 87 }
87 88  
88 89 void
89 90 QPDF_Array::getAsVector(std::vector<QPDFObjectHandle>& v) const
90 91 {
91   - size_t size = this->items.size();
  92 + size_t size = this->elements.size();
92 93 for (size_t i = 0; i < size; ++i)
93 94 {
94   - v.push_back(this->items.at(i));
  95 + v.push_back(this->elements.at(i));
95 96 }
96 97 }
97 98  
98 99 void
99 100 QPDF_Array::setItem(int n, QPDFObjectHandle const& oh)
100 101 {
101   - // Call getItem for bounds checking
102   - (void) getItem(n);
103   - this->items.at(QIntC::to_size(n)) = oh;
  102 + this->elements.setAt(QIntC::to_size(n), oh);
104 103 }
105 104  
106 105 void
107 106 QPDF_Array::setFromVector(std::vector<QPDFObjectHandle> const& v)
108 107 {
109   - this->items.clear();
  108 + this->elements = SparseOHArray();
110 109 for (std::vector<QPDFObjectHandle>::const_iterator iter = v.begin();
111 110 iter != v.end(); ++iter)
112 111 {
113   - this->items.push_back(*iter);
  112 + this->elements.append(*iter);
114 113 }
115 114 }
116 115  
... ... @@ -118,24 +117,22 @@ void
118 117 QPDF_Array::insertItem(int at, QPDFObjectHandle const& item)
119 118 {
120 119 // As special case, also allow insert beyond the end
121   - if ((at < 0) || (at > QIntC::to_int(this->items.size())))
  120 + if ((at < 0) || (at > QIntC::to_int(this->elements.size())))
122 121 {
123 122 throw std::logic_error(
124 123 "INTERNAL ERROR: bounds error accessing QPDF_Array element");
125 124 }
126   - this->items.insert(this->items.begin() + at, item);
  125 + this->elements.insert(QIntC::to_size(at), item);
127 126 }
128 127  
129 128 void
130 129 QPDF_Array::appendItem(QPDFObjectHandle const& item)
131 130 {
132   - this->items.push_back(item);
  131 + this->elements.append(item);
133 132 }
134 133  
135 134 void
136 135 QPDF_Array::eraseItem(int at)
137 136 {
138   - // Call getItem for bounds checking
139   - (void) getItem(at);
140   - this->items.erase(this->items.begin() + at);
  137 + this->elements.erase(QIntC::to_size(at));
141 138 }
... ...
libqpdf/qpdf/QPDF_Array.hh
... ... @@ -4,12 +4,13 @@
4 4 #include <qpdf/QPDFObject.hh>
5 5  
6 6 #include <vector>
7   -#include <qpdf/QPDFObjectHandle.hh>
  7 +#include <qpdf/SparseOHArray.hh>
8 8  
9 9 class QPDF_Array: public QPDFObject
10 10 {
11 11 public:
12 12 QPDF_Array(std::vector<QPDFObjectHandle> const& items);
  13 + QPDF_Array(SparseOHArray const& items);
13 14 virtual ~QPDF_Array();
14 15 virtual std::string unparse();
15 16 virtual JSON getJSON();
... ... @@ -31,7 +32,7 @@ class QPDF_Array: public QPDFObject
31 32 virtual void releaseResolved();
32 33  
33 34 private:
34   - std::vector<QPDFObjectHandle> items;
  35 + SparseOHArray elements;
35 36 };
36 37  
37 38 #endif // QPDF_ARRAY_HH
... ...