Commit e5f504b6c5dc34337cc0b316b4a7b1fca7e614b1
1 parent
a89d8a06
Use SparseOHArray in QPDF_Array
Showing
3 changed files
with
29 additions
and
28 deletions
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<QPDFObjectHandle> const& 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 | ... | ... |