From e5f504b6c5dc34337cc0b316b4a7b1fca7e614b1 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 17 Aug 2019 22:13:37 -0400 Subject: [PATCH] Use SparseOHArray in QPDF_Array --- include/qpdf/QPDFObjectHandle.hh | 5 +++- libqpdf/QPDF_Array.cc | 47 +++++++++++++++----------------- libqpdf/qpdf/QPDF_Array.hh | 5 ++-- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index ad542c09..4f18cbda 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -544,6 +544,10 @@ class QPDFObjectHandle int getArrayNItems(); QPDF_DLL QPDFObjectHandle getArrayItem(int n); + // Note: QPDF arrays internally optimize memory for arrays + // containing lots of nulls. Calling getArrayAsVector may cause a + // lot of memory to be allocated for very large arrays with lots + // of nulls. QPDF_DLL std::vector getArrayAsVector(); QPDF_DLL @@ -932,7 +936,6 @@ class QPDFObjectHandle class ReleaseResolver { friend class QPDF_Dictionary; - friend class QPDF_Array; friend class QPDF_Stream; friend class SparseOHArray; private: diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index a912b2bd..45635f8a 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -8,6 +8,11 @@ QPDF_Array::QPDF_Array(std::vector const& v) setFromVector(v); } +QPDF_Array::QPDF_Array(SparseOHArray const& items) : + elements(items) +{ +} + QPDF_Array::~QPDF_Array() { } @@ -15,21 +20,17 @@ QPDF_Array::~QPDF_Array() void QPDF_Array::releaseResolved() { - for (std::vector::iterator iter = this->items.begin(); - iter != this->items.end(); ++iter) - { - QPDFObjectHandle::ReleaseResolver::releaseResolved(*iter); - } + this->elements.releaseResolved(); } std::string QPDF_Array::unparse() { std::string result = "[ "; - size_t size = this->items.size(); + size_t size = this->elements.size(); for (size_t i = 0; i < size; ++i) { - result += this->items.at(i).unparse(); + result += this->elements.at(i).unparse(); result += " "; } result += "]"; @@ -40,10 +41,10 @@ JSON QPDF_Array::getJSON() { JSON j = JSON::makeArray(); - size_t size = this->items.size(); + size_t size = this->elements.size(); for (size_t i = 0; i < size; ++i) { - j.addArrayElement(this->items.at(i).getJSON()); + j.addArrayElement(this->elements.at(i).getJSON()); } return j; } @@ -71,46 +72,44 @@ QPDF_Array::getNItems() const { // This should really return a size_t, but changing it would break // a lot of code. - return QIntC::to_int(this->items.size()); + return QIntC::to_int(this->elements.size()); } QPDFObjectHandle QPDF_Array::getItem(int n) const { - if ((n < 0) || (n >= QIntC::to_int(this->items.size()))) + if ((n < 0) || (n >= QIntC::to_int(elements.size()))) { throw std::logic_error( "INTERNAL ERROR: bounds error accessing QPDF_Array element"); } - return this->items.at(QIntC::to_size(n)); + return this->elements.at(QIntC::to_size(n)); } void QPDF_Array::getAsVector(std::vector& v) const { - size_t size = this->items.size(); + size_t size = this->elements.size(); for (size_t i = 0; i < size; ++i) { - v.push_back(this->items.at(i)); + v.push_back(this->elements.at(i)); } } void QPDF_Array::setItem(int n, QPDFObjectHandle const& oh) { - // Call getItem for bounds checking - (void) getItem(n); - this->items.at(QIntC::to_size(n)) = oh; + this->elements.setAt(QIntC::to_size(n), oh); } void QPDF_Array::setFromVector(std::vector const& v) { - this->items.clear(); + this->elements = SparseOHArray(); for (std::vector::const_iterator iter = v.begin(); iter != v.end(); ++iter) { - this->items.push_back(*iter); + this->elements.append(*iter); } } @@ -118,24 +117,22 @@ void QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) { // As special case, also allow insert beyond the end - if ((at < 0) || (at > QIntC::to_int(this->items.size()))) + if ((at < 0) || (at > QIntC::to_int(this->elements.size()))) { throw std::logic_error( "INTERNAL ERROR: bounds error accessing QPDF_Array element"); } - this->items.insert(this->items.begin() + at, item); + this->elements.insert(QIntC::to_size(at), item); } void QPDF_Array::appendItem(QPDFObjectHandle const& item) { - this->items.push_back(item); + this->elements.append(item); } void QPDF_Array::eraseItem(int at) { - // Call getItem for bounds checking - (void) getItem(at); - this->items.erase(this->items.begin() + at); + this->elements.erase(QIntC::to_size(at)); } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 4d2cb005..08a5a608 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -4,12 +4,13 @@ #include #include -#include +#include class QPDF_Array: public QPDFObject { public: QPDF_Array(std::vector const& items); + QPDF_Array(SparseOHArray const& items); virtual ~QPDF_Array(); virtual std::string unparse(); virtual JSON getJSON(); @@ -31,7 +32,7 @@ class QPDF_Array: public QPDFObject virtual void releaseResolved(); private: - std::vector items; + SparseOHArray elements; }; #endif // QPDF_ARRAY_HH