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,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<QPDFObjectHandle> const& v) | @@ -8,6 +8,11 @@ QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& 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 |