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,6 +544,10 @@ class QPDFObjectHandle
544 int getArrayNItems(); 544 int getArrayNItems();
545 QPDF_DLL 545 QPDF_DLL
546 QPDFObjectHandle getArrayItem(int n); 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 QPDF_DLL 551 QPDF_DLL
548 std::vector<QPDFObjectHandle> getArrayAsVector(); 552 std::vector<QPDFObjectHandle> getArrayAsVector();
549 QPDF_DLL 553 QPDF_DLL
@@ -932,7 +936,6 @@ class QPDFObjectHandle @@ -932,7 +936,6 @@ class QPDFObjectHandle
932 class ReleaseResolver 936 class ReleaseResolver
933 { 937 {
934 friend class QPDF_Dictionary; 938 friend class QPDF_Dictionary;
935 - friend class QPDF_Array;  
936 friend class QPDF_Stream; 939 friend class QPDF_Stream;
937 friend class SparseOHArray; 940 friend class SparseOHArray;
938 private: 941 private:
libqpdf/QPDF_Array.cc
@@ -8,6 +8,11 @@ QPDF_Array::QPDF_Array(std::vector&lt;QPDFObjectHandle&gt; const&amp; v) @@ -8,6 +8,11 @@ QPDF_Array::QPDF_Array(std::vector&lt;QPDFObjectHandle&gt; const&amp; v)
8 setFromVector(v); 8 setFromVector(v);
9 } 9 }
10 10
  11 +QPDF_Array::QPDF_Array(SparseOHArray const& items) :
  12 + elements(items)
  13 +{
  14 +}
  15 +
11 QPDF_Array::~QPDF_Array() 16 QPDF_Array::~QPDF_Array()
12 { 17 {
13 } 18 }
@@ -15,21 +20,17 @@ QPDF_Array::~QPDF_Array() @@ -15,21 +20,17 @@ QPDF_Array::~QPDF_Array()
15 void 20 void
16 QPDF_Array::releaseResolved() 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 std::string 26 std::string
26 QPDF_Array::unparse() 27 QPDF_Array::unparse()
27 { 28 {
28 std::string result = "[ "; 29 std::string result = "[ ";
29 - size_t size = this->items.size(); 30 + size_t size = this->elements.size();
30 for (size_t i = 0; i < size; ++i) 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 result += " "; 34 result += " ";
34 } 35 }
35 result += "]"; 36 result += "]";
@@ -40,10 +41,10 @@ JSON @@ -40,10 +41,10 @@ JSON
40 QPDF_Array::getJSON() 41 QPDF_Array::getJSON()
41 { 42 {
42 JSON j = JSON::makeArray(); 43 JSON j = JSON::makeArray();
43 - size_t size = this->items.size(); 44 + size_t size = this->elements.size();
44 for (size_t i = 0; i < size; ++i) 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 return j; 49 return j;
49 } 50 }
@@ -71,46 +72,44 @@ QPDF_Array::getNItems() const @@ -71,46 +72,44 @@ QPDF_Array::getNItems() const
71 { 72 {
72 // This should really return a size_t, but changing it would break 73 // This should really return a size_t, but changing it would break
73 // a lot of code. 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 QPDFObjectHandle 78 QPDFObjectHandle
78 QPDF_Array::getItem(int n) const 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 throw std::logic_error( 83 throw std::logic_error(
83 "INTERNAL ERROR: bounds error accessing QPDF_Array element"); 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 void 89 void
89 QPDF_Array::getAsVector(std::vector<QPDFObjectHandle>& v) const 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 for (size_t i = 0; i < size; ++i) 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 void 99 void
99 QPDF_Array::setItem(int n, QPDFObjectHandle const& oh) 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 void 105 void
107 QPDF_Array::setFromVector(std::vector<QPDFObjectHandle> const& v) 106 QPDF_Array::setFromVector(std::vector<QPDFObjectHandle> const& v)
108 { 107 {
109 - this->items.clear(); 108 + this->elements = SparseOHArray();
110 for (std::vector<QPDFObjectHandle>::const_iterator iter = v.begin(); 109 for (std::vector<QPDFObjectHandle>::const_iterator iter = v.begin();
111 iter != v.end(); ++iter) 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,24 +117,22 @@ void
118 QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) 117 QPDF_Array::insertItem(int at, QPDFObjectHandle const& item)
119 { 118 {
120 // As special case, also allow insert beyond the end 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 throw std::logic_error( 122 throw std::logic_error(
124 "INTERNAL ERROR: bounds error accessing QPDF_Array element"); 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 void 128 void
130 QPDF_Array::appendItem(QPDFObjectHandle const& item) 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 void 134 void
136 QPDF_Array::eraseItem(int at) 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,12 +4,13 @@
4 #include <qpdf/QPDFObject.hh> 4 #include <qpdf/QPDFObject.hh>
5 5
6 #include <vector> 6 #include <vector>
7 -#include <qpdf/QPDFObjectHandle.hh> 7 +#include <qpdf/SparseOHArray.hh>
8 8
9 class QPDF_Array: public QPDFObject 9 class QPDF_Array: public QPDFObject
10 { 10 {
11 public: 11 public:
12 QPDF_Array(std::vector<QPDFObjectHandle> const& items); 12 QPDF_Array(std::vector<QPDFObjectHandle> const& items);
  13 + QPDF_Array(SparseOHArray const& items);
13 virtual ~QPDF_Array(); 14 virtual ~QPDF_Array();
14 virtual std::string unparse(); 15 virtual std::string unparse();
15 virtual JSON getJSON(); 16 virtual JSON getJSON();
@@ -31,7 +32,7 @@ class QPDF_Array: public QPDFObject @@ -31,7 +32,7 @@ class QPDF_Array: public QPDFObject
31 virtual void releaseResolved(); 32 virtual void releaseResolved();
32 33
33 private: 34 private:
34 - std::vector<QPDFObjectHandle> items; 35 + SparseOHArray elements;
35 }; 36 };
36 37
37 #endif // QPDF_ARRAY_HH 38 #endif // QPDF_ARRAY_HH