From 51d350c98c549ff59dd6423e98d993385f57fa9c Mon Sep 17 00:00:00 2001 From: m-holger Date: Fri, 24 Mar 2023 12:58:36 +0000 Subject: Inline QPDF_Array::getNItems and rename to size --- libqpdf/QPDFObjectHandle.cc | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index d474dcce..9fd8684b 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -789,9 +789,8 @@ QPDFObjectHandle::aitems() int QPDFObjectHandle::getArrayNItems() { - auto array = asArray(); - if (array) { - return array->getNItems(); + if (auto array = asArray()) { + return array->size(); } else { typeWarning("array", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); @@ -803,7 +802,7 @@ QPDFObjectHandle QPDFObjectHandle::getArrayItem(int n) { auto array = asArray(); - if (array && (n < array->getNItems()) && (n >= 0)) { + if (array && n < array->size() && n >= 0) { return array->getItem(n); } else { if (array) { @@ -823,7 +822,7 @@ bool QPDFObjectHandle::isRectangle() { auto array = asArray(); - if ((array == nullptr) || (array->getNItems() != 4)) { + if (array == nullptr || array->size() != 4) { return false; } for (int i = 0; i < 4; ++i) { @@ -838,7 +837,7 @@ bool QPDFObjectHandle::isMatrix() { auto array = asArray(); - if ((array == nullptr) || (array->getNItems() != 6)) { + if (array == nullptr || array->size() != 6) { return false; } for (int i = 0; i < 6; ++i) { @@ -975,7 +974,7 @@ void QPDFObjectHandle::eraseItem(int at) { auto array = asArray(); - if (array && (at < array->getNItems()) && (at >= 0)) { + if (array && at < array->size() && at >= 0) { array->eraseItem(at); } else { if (array) { @@ -991,11 +990,9 @@ QPDFObjectHandle::eraseItem(int at) QPDFObjectHandle QPDFObjectHandle::eraseItemAndGetOld(int at) { - auto result = QPDFObjectHandle::newNull(); auto array = asArray(); - if (array && (at < array->getNItems()) && (at >= 0)) { - result = array->getItem(at); - } + auto result = (array && at < array->size() && at >= 0) ? array->getItem(at) + : newNull(); eraseItem(at); return result; } @@ -1515,9 +1512,8 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( { all_description = description; std::vector result; - auto array = asArray(); - if (array) { - int n_items = array->getNItems(); + if (auto array = asArray()) { + int n_items = array->size(); for (int i = 0; i < n_items; ++i) { QPDFObjectHandle item = array->getItem(i); if (item.isStream()) { @@ -2217,7 +2213,7 @@ QPDFObjectHandle::makeDirect( } else if (isArray()) { std::vector items; auto array = asArray(); - int n = array->getNItems(); + int n = array->size(); for (int i = 0; i < n; ++i) { items.push_back(array->getItem(i)); items.back().makeDirect(visited, stop_at_streams); -- cgit v1.2.3-54-g00ecf From a1a8f35b63bcad7e0cac31a205e109d6a0d70622 Mon Sep 17 00:00:00 2001 From: m-holger Date: Fri, 24 Mar 2023 15:01:40 +0000 Subject: Refactor QPDF_Array::getItem and rename to at --- libqpdf/QPDFObjectHandle.cc | 114 +++++++++++++++++++++--------------------- libqpdf/QPDF_Array.cc | 30 +++++------ libqpdf/SparseOHArray.cc | 14 ++---- libqpdf/qpdf/QPDF_Array.hh | 2 +- libqpdf/qpdf/SparseOHArray.hh | 2 +- 5 files changed, 74 insertions(+), 88 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 9fd8684b..e08c675d 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -801,90 +801,88 @@ QPDFObjectHandle::getArrayNItems() QPDFObjectHandle QPDFObjectHandle::getArrayItem(int n) { - auto array = asArray(); - if (array && n < array->size() && n >= 0) { - return array->getItem(n); - } else { - if (array) { + if (auto array = asArray()) { + if (auto result = array->at(n); result.obj != nullptr) { + return result; + } else { objectWarning("returning null for out of bounds array access"); QTC::TC("qpdf", "QPDFObjectHandle array bounds"); - } else { - typeWarning("array", "returning null"); - QTC::TC("qpdf", "QPDFObjectHandle array null for non-array"); } - static auto constexpr msg = - " -> null returned from invalid array access"sv; - return QPDF_Null::create(obj, msg, ""); + } else { + typeWarning("array", "returning null"); + QTC::TC("qpdf", "QPDFObjectHandle array null for non-array"); } + static auto constexpr msg = " -> null returned from invalid array access"sv; + return QPDF_Null::create(obj, msg, ""); } bool QPDFObjectHandle::isRectangle() { - auto array = asArray(); - if (array == nullptr || array->size() != 4) { - return false; - } - for (int i = 0; i < 4; ++i) { - if (!array->getItem(i).isNumber()) { - return false; + if (auto array = asArray()) { + for (int i = 0; i < 4; ++i) { + if (auto item = array->at(i); !(item.obj && item.isNumber())) { + return false; + } } + return array->size() == 4; } - return true; + return false; } bool QPDFObjectHandle::isMatrix() { - auto array = asArray(); - if (array == nullptr || array->size() != 6) { - return false; - } - for (int i = 0; i < 6; ++i) { - if (!array->getItem(i).isNumber()) { - return false; + if (auto array = asArray()) { + for (int i = 0; i < 6; ++i) { + if (auto item = array->at(i); !(item.obj && item.isNumber())) { + return false; + } } + return array->size() == 6; } - return true; + return false; } QPDFObjectHandle::Rectangle QPDFObjectHandle::getArrayAsRectangle() { - Rectangle result; - if (isRectangle()) { - auto array = asArray(); - // Rectangle coordinates are always supposed to be llx, lly, - // urx, ury, but files have been found in the wild where - // llx > urx or lly > ury. - double i0 = array->getItem(0).getNumericValue(); - double i1 = array->getItem(1).getNumericValue(); - double i2 = array->getItem(2).getNumericValue(); - double i3 = array->getItem(3).getNumericValue(); - result = Rectangle( - std::min(i0, i2), - std::min(i1, i3), - std::max(i0, i2), - std::max(i1, i3)); + if (auto array = asArray()) { + if (array->size() != 4) { + return {}; + } + double items[4]; + for (int i = 0; i < 4; ++i) { + if (!array->at(i).getValueAsNumber(items[i])) { + return {}; + } + } + return Rectangle( + std::min(items[0], items[2]), + std::min(items[1], items[3]), + std::max(items[0], items[2]), + std::max(items[1], items[3])); } - return result; + return {}; } QPDFObjectHandle::Matrix QPDFObjectHandle::getArrayAsMatrix() { - Matrix result; - if (isMatrix()) { - auto array = asArray(); - result = Matrix( - array->getItem(0).getNumericValue(), - array->getItem(1).getNumericValue(), - array->getItem(2).getNumericValue(), - array->getItem(3).getNumericValue(), - array->getItem(4).getNumericValue(), - array->getItem(5).getNumericValue()); + if (auto array = asArray()) { + if (array->size() != 6) { + return {}; + } + double items[6]; + for (int i = 0; i < 6; ++i) { + if (!array->at(i).getValueAsNumber(items[i])) { + return {}; + } + } + return Matrix( + items[0], items[1], items[2], items[3], items[4], items[5]); } - return result; + return {}; } std::vector @@ -991,8 +989,8 @@ QPDFObjectHandle QPDFObjectHandle::eraseItemAndGetOld(int at) { auto array = asArray(); - auto result = (array && at < array->size() && at >= 0) ? array->getItem(at) - : newNull(); + auto result = + (array && at < array->size() && at >= 0) ? array->at(at) : newNull(); eraseItem(at); return result; } @@ -1515,7 +1513,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( if (auto array = asArray()) { int n_items = array->size(); for (int i = 0; i < n_items; ++i) { - QPDFObjectHandle item = array->getItem(i); + QPDFObjectHandle item = array->at(i); if (item.isStream()) { result.push_back(item); } else { @@ -2215,7 +2213,7 @@ QPDFObjectHandle::makeDirect( auto array = asArray(); int n = array->size(); for (int i = 0; i < n; ++i) { - items.push_back(array->getItem(i)); + items.push_back(array->at(i)); items.back().makeDirect(visited, stop_at_streams); } this->obj = QPDF_Array::create(items); diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 9368ca51..e9d216a5 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -105,7 +105,7 @@ QPDF_Array::unparse() std::string result = "[ "; int size = sp_elements.size(); for (int i = 0; i < size; ++i) { - result += sp_elements.at(i).unparse(); + result += at(i).unparse(); result += " "; } result += "]"; @@ -114,7 +114,7 @@ QPDF_Array::unparse() std::string result = "[ "; auto size = elements.size(); for (int i = 0; i < int(size); ++i) { - result += getItem(i).unparse(); + result += at(i).unparse(); result += " "; } result += "]"; @@ -129,35 +129,29 @@ QPDF_Array::getJSON(int json_version) JSON j = JSON::makeArray(); int size = sp_elements.size(); for (int i = 0; i < size; ++i) { - j.addArrayElement(sp_elements.at(i).getJSON(json_version)); + j.addArrayElement(at(i).getJSON(json_version)); } return j; } else { JSON j = JSON::makeArray(); size_t size = elements.size(); for (int i = 0; i < int(size); ++i) { - j.addArrayElement(getItem(i).getJSON(json_version)); + j.addArrayElement(at(i).getJSON(json_version)); } return j; } } QPDFObjectHandle -QPDF_Array::getItem(int n) const +QPDF_Array::at(int n) const noexcept { - if (sparse) { - if ((n < 0) || (n >= QIntC::to_int(sp_elements.size()))) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - return sp_elements.at(n); + if (n < 0 || n >= size()) { + return {}; + } else if (sparse) { + auto const& iter = sp_elements.elements.find(n); + return iter == sp_elements.elements.end() ? null_oh : (*iter).second; } else { - if ((n < 0) || (n >= QIntC::to_int(elements.size()))) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - auto const& obj = elements.at(size_t(n)); - return obj ? obj : null_oh; + return elements[size_t(n)]; } } @@ -167,7 +161,7 @@ QPDF_Array::getAsVector(std::vector& v) const if (sparse) { int size = sp_elements.size(); for (int i = 0; i < size; ++i) { - v.push_back(sp_elements.at(i)); + v.push_back(at(i)); } } else { v = std::vector(elements.cbegin(), elements.cend()); diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 3f6376a6..c82bf145 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -2,6 +2,8 @@ #include +static const QPDFObjectHandle null_oh = QPDFObjectHandle::newNull(); + void SparseOHArray::append(QPDFObjectHandle oh) { @@ -23,16 +25,8 @@ SparseOHArray::append(std::shared_ptr&& obj) QPDFObjectHandle SparseOHArray::at(int idx) const { - if (idx < 0 || idx >= this->n_elements) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing SparseOHArray element"); - } - auto const& iter = this->elements.find(idx); - if (iter == this->elements.end()) { - return QPDFObjectHandle::newNull(); - } else { - return (*iter).second; - } + auto const& iter = elements.find(idx); + return iter == elements.end() ? null_oh : (*iter).second; } void diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 558704c7..4947d09c 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -27,7 +27,7 @@ class QPDF_Array: public QPDFValue { return sparse ? sp_elements.size() : int(elements.size()); } - QPDFObjectHandle getItem(int n) const; + QPDFObjectHandle at(int n) const noexcept; void getAsVector(std::vector&) const; void setItem(int, QPDFObjectHandle const&); diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh index 468e3a39..80de95e5 100644 --- a/libqpdf/qpdf/SparseOHArray.hh +++ b/libqpdf/qpdf/SparseOHArray.hh @@ -12,7 +12,7 @@ class SparseOHArray public: SparseOHArray() = default; int - size() const + size() const noexcept { return n_elements; } -- cgit v1.2.3-54-g00ecf From cedb37caa153abfd92a91b2e39a6f32601be826c Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 10 Dec 2022 19:05:12 +0000 Subject: Refactor QPDF_Array::appendItem and rename to push_back --- libqpdf/QPDFObjectHandle.cc | 6 ++---- libqpdf/QPDF_Array.cc | 5 +++-- libqpdf/SparseOHArray.cc | 18 ------------------ libqpdf/qpdf/QPDF_Array.hh | 2 +- libqpdf/qpdf/SparseOHArray.hh | 12 ++++++++++-- 5 files changed, 16 insertions(+), 27 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index e08c675d..0c4d45ae 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -951,10 +951,8 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const& item) void QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) { - auto array = asArray(); - if (array) { - checkOwnership(item); - array->appendItem(item); + if (auto array = asArray()) { + array->push_back(item); } else { typeWarning("array", "ignoring attempt to append item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index def40e9b..5a80cdf5 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -264,10 +264,11 @@ QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) } void -QPDF_Array::appendItem(QPDFObjectHandle const& item) +QPDF_Array::push_back(QPDFObjectHandle const& item) { + checkOwnership(item); if (sparse) { - sp_elements.append(item); + sp_elements.elements[sp_elements.n_elements++] = item.getObj(); } else { elements.push_back(item.getObj()); } diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index c82bf145..48716deb 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -4,24 +4,6 @@ static const QPDFObjectHandle null_oh = QPDFObjectHandle::newNull(); -void -SparseOHArray::append(QPDFObjectHandle oh) -{ - if (!oh.isDirectNull()) { - this->elements[this->n_elements] = oh.getObj(); - } - ++this->n_elements; -} - -void -SparseOHArray::append(std::shared_ptr&& obj) -{ - if (obj->getTypeCode() != ::ot_null || !obj->getObjGen().isIndirect()) { - this->elements[this->n_elements] = std::move(obj); - } - ++this->n_elements; -} - QPDFObjectHandle SparseOHArray::at(int idx) const { diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index b27ce122..61f14d0f 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -34,7 +34,7 @@ class QPDF_Array: public QPDFValue void setFromVector(std::vector const& items); void setFromVector(std::vector>&& items); void insertItem(int at, QPDFObjectHandle const& item); - void appendItem(QPDFObjectHandle const& item); + void push_back(QPDFObjectHandle const& item); void eraseItem(int at); private: diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh index 80de95e5..f2872618 100644 --- a/libqpdf/qpdf/SparseOHArray.hh +++ b/libqpdf/qpdf/SparseOHArray.hh @@ -16,8 +16,16 @@ class SparseOHArray { return n_elements; } - void append(QPDFObjectHandle oh); - void append(std::shared_ptr&& obj); + void + append(QPDFObjectHandle oh) + { + elements[n_elements++] = oh.getObj(); + } + void + append(std::shared_ptr&& obj) + { + elements[n_elements++] = std::move(obj); + } QPDFObjectHandle at(int idx) const; void remove_last(); void setAt(int idx, QPDFObjectHandle oh); -- cgit v1.2.3-54-g00ecf From 1bb23d0545dfe2d651cb22b6135d99c1c9ef85d5 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 10 Dec 2022 19:48:07 +0000 Subject: Refactor QPDF_Array::insertItem and rename to insert --- libqpdf/QPDFObjectHandle.cc | 9 ++++++--- libqpdf/QPDF_Array.cc | 31 ++++++++++++------------------- libqpdf/SparseOHArray.cc | 22 +++++++++++----------- libqpdf/qpdf/QPDF_Array.hh | 2 +- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf/object-types-os.out | 1 + qpdf/qtest/qpdf/object-types.out | 1 + qpdf/test_driver.cc | 1 + 8 files changed, 34 insertions(+), 34 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 0c4d45ae..fa8b9136 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -932,9 +932,12 @@ QPDFObjectHandle::setArrayFromVector(std::vector const& items) void QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) { - auto array = asArray(); - if (array) { - array->insertItem(at, item); + if (auto array = asArray()) { + if (!array->insert(at, item)) { + objectWarning( + "ignoring attempt to insert out of bounds array item"); + QTC::TC("qpdf", "QPDFObjectHandle insert array bounds"); + } } else { typeWarning("array", "ignoring attempt to insert item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 5a80cdf5..7633266e 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -236,31 +236,24 @@ QPDF_Array::setFromVector(std::vector>&& v) } } -void -QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) +bool +QPDF_Array::insert(int at, QPDFObjectHandle const& item) { - if (sparse) { + int sz = size(); + if (at < 0 || at > sz) { // As special case, also allow insert beyond the end - if ((at < 0) || (at > sp_elements.size())) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - sp_elements.insert(at, item); + return false; + } else if (at == sz) { + push_back(item); } else { - // As special case, also allow insert beyond the end - size_t idx = QIntC::to_size(at); - if ((at < 0) || (at > QIntC::to_int(elements.size()))) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - if (idx == elements.size()) { - // Allow inserting to the last position - elements.push_back(item.getObj()); + checkOwnership(item); + if (sparse) { + sp_elements.insert(at, item); } else { - int n = int(idx); - elements.insert(elements.cbegin() + n, item.getObj()); + elements.insert(elements.cbegin() + at, item.getObj()); } } + return true; } void diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 48716deb..8f6c02d7 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -64,23 +64,23 @@ SparseOHArray::erase(int idx) void SparseOHArray::insert(int idx, QPDFObjectHandle oh) { - if (idx > this->n_elements) { - throw std::logic_error("bounds error inserting item to SparseOHArray"); - } else if (idx == this->n_elements) { + if (idx == n_elements) { // Allow inserting to the last position append(oh); } else { - decltype(this->elements) dest; - for (auto const& iter: this->elements) { - if (iter.first < idx) { - dest.insert(iter); + auto iter = elements.crbegin(); + while (iter != elements.crend()) { + auto key = (iter++)->first; + if (key >= idx) { + auto nh = elements.extract(key); + ++nh.key(); + elements.insert(std::move(nh)); } else { - dest[iter.first + 1] = iter.second; + break; } } - this->elements = dest; - this->elements[idx] = oh.getObj(); - ++this->n_elements; + elements[idx] = oh.getObj(); + ++n_elements; } } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 61f14d0f..8768c9ad 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -33,7 +33,7 @@ class QPDF_Array: public QPDFValue void setItem(int, QPDFObjectHandle const&); void setFromVector(std::vector const& items); void setFromVector(std::vector>&& items); - void insertItem(int at, QPDFObjectHandle const& item); + bool insert(int at, QPDFObjectHandle const& item); void push_back(QPDFObjectHandle const& item); void eraseItem(int at); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index cad67565..736c02b4 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -305,6 +305,7 @@ QPDFObjectHandle array treating as empty vector 0 QPDFObjectHandle array ignoring set item 0 QPDFObjectHandle array ignoring replace items 0 QPDFObjectHandle array ignoring insert item 0 +QPDFObjectHandle insert array bounds 0 QPDFObjectHandle array ignoring append item 0 QPDFObjectHandle array ignoring erase item 0 QPDFObjectHandle dictionary false for hasKey 0 diff --git a/qpdf/qtest/qpdf/object-types-os.out b/qpdf/qtest/qpdf/object-types-os.out index a95fa4d8..1ba84d50 100644 --- a/qpdf/qtest/qpdf/object-types-os.out +++ b/qpdf/qtest/qpdf/object-types-os.out @@ -5,6 +5,7 @@ WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operatio WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to append item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item +WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to insert out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/qtest/qpdf/object-types.out b/qpdf/qtest/qpdf/object-types.out index 718105db..bf41044e 100644 --- a/qpdf/qtest/qpdf/object-types.out +++ b/qpdf/qtest/qpdf/object-types.out @@ -5,6 +5,7 @@ WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempt WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to append item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item +WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to insert out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 5bae8b54..8c54ad01 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1506,6 +1506,7 @@ test_42(QPDF& pdf, char const* arg2) integer.appendItem(null); array.eraseItem(-1); array.eraseItem(16059); + array.insertItem(42, "/Dontpanic"_qpdf); integer.eraseItem(0); integer.insertItem(0, null); integer.setArrayFromVector(std::vector()); -- cgit v1.2.3-54-g00ecf From 4d37389befc705b671d8fa7a1da2b7117b50f454 Mon Sep 17 00:00:00 2001 From: m-holger Date: Mon, 12 Dec 2022 13:29:52 +0000 Subject: Refactor QPDF_Array::eraseItem and rename to erase --- libqpdf/QPDFObjectHandle.cc | 13 +++++-------- libqpdf/QPDF_Array.cc | 15 +++++++-------- libqpdf/SparseOHArray.cc | 25 +++++++++++++------------ libqpdf/qpdf/QPDF_Array.hh | 2 +- qpdf/qtest/qpdf/test88.out | 1 + qpdf/test_driver.cc | 1 + 6 files changed, 28 insertions(+), 29 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index fa8b9136..e113089a 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -972,17 +972,14 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) void QPDFObjectHandle::eraseItem(int at) { - auto array = asArray(); - if (array && at < array->size() && at >= 0) { - array->eraseItem(at); - } else { - if (array) { + if (auto array = asArray()) { + if (!array->erase(at)) { objectWarning("ignoring attempt to erase out of bounds array item"); QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); - } else { - typeWarning("array", "ignoring attempt to erase item"); - QTC::TC("qpdf", "QPDFObjectHandle array ignoring erase item"); } + } else { + typeWarning("array", "ignoring attempt to erase item"); + QTC::TC("qpdf", "QPDFObjectHandle array ignoring erase item"); } } diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 7633266e..e4e1668e 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -267,17 +267,16 @@ QPDF_Array::push_back(QPDFObjectHandle const& item) } } -void -QPDF_Array::eraseItem(int at) +bool +QPDF_Array::erase(int at) { + if (at < 0 || at >= size()) { + return false; + } if (sparse) { sp_elements.erase(at); } else { - size_t idx = QIntC::to_size(at); - if (idx >= elements.size()) { - throw std::logic_error("bounds error erasing item from OHArray"); - } - int n = int(idx); - elements.erase(elements.cbegin() + n); + elements.erase(elements.cbegin() + at); } + return true; } diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 8f6c02d7..773d7309 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -44,21 +44,22 @@ SparseOHArray::setAt(int idx, QPDFObjectHandle oh) } void -SparseOHArray::erase(int idx) +SparseOHArray::erase(int at) { - if (idx >= this->n_elements) { - throw std::logic_error("bounds error erasing item from SparseOHArray"); - } - decltype(this->elements) dest; - for (auto const& iter: this->elements) { - if (iter.first < idx) { - dest.insert(iter); - } else if (iter.first > idx) { - dest[iter.first - 1] = iter.second; + auto end = elements.end(); + if (auto iter = elements.lower_bound(at); iter != end) { + if (iter->first == at) { + iter++; + elements.erase(at); + } + + while (iter != end) { + auto nh = elements.extract(iter++); + --nh.key(); + elements.insert(std::move(nh)); } } - this->elements = dest; - --this->n_elements; + --n_elements; } void diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 8768c9ad..edda54ec 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -35,7 +35,7 @@ class QPDF_Array: public QPDFValue void setFromVector(std::vector>&& items); bool insert(int at, QPDFObjectHandle const& item); void push_back(QPDFObjectHandle const& item); - void eraseItem(int at); + bool erase(int at); private: QPDF_Array(std::vector const& items); diff --git a/qpdf/qtest/qpdf/test88.out b/qpdf/qtest/qpdf/test88.out index 327212b6..9d5cf504 100644 --- a/qpdf/qtest/qpdf/test88.out +++ b/qpdf/qtest/qpdf/test88.out @@ -1,2 +1,3 @@ WARNING: test array: ignoring attempt to erase out of bounds array item +WARNING: minimal.pdf, object 1 0 at offset 19: operation for array attempted on object of type dictionary: ignoring attempt to erase item test 88 done diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 8c54ad01..82361ba0 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3283,6 +3283,7 @@ test_88(QPDF& pdf, char const* arg2) auto arr2 = pdf.getRoot().replaceKeyAndGetNew("/QTest", "[1 2]"_qpdf); arr2.setObjectDescription(&pdf, "test array"); assert(arr2.eraseItemAndGetOld(50).isNull()); + assert(pdf.getRoot().eraseItemAndGetOld(0).isNull()); } static void -- cgit v1.2.3-54-g00ecf From 182c2480df3d2dee3e430e02afe6bbee3e45eadd Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 1 Jan 2023 12:47:03 +0000 Subject: Refactor QPDF_Array::setItem and rename to setAt --- libqpdf/QPDFObjectHandle.cc | 10 +++++----- libqpdf/QPDF_Array.cc | 20 +++++++++----------- libqpdf/SparseOHArray.cc | 13 ------------- libqpdf/qpdf/QPDF_Array.hh | 3 +-- libqpdf/qpdf/SparseOHArray.hh | 6 +++++- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf/object-types-os.out | 1 + qpdf/qtest/qpdf/object-types.out | 1 + qpdf/test_driver.cc | 1 + 9 files changed, 24 insertions(+), 32 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index e113089a..396e2063 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -904,16 +904,16 @@ QPDFObjectHandle::getArrayAsVector() void QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) { - auto array = asArray(); - if (array) { - checkOwnership(item); - array->setItem(n, item); + if (auto array = asArray()) { + if (!array->setAt(n, item)) { + objectWarning("ignoring attempt to set out of bounds array item"); + QTC::TC("qpdf", "QPDFObjectHandle set array bounds"); + } } else { typeWarning("array", "ignoring attempt to set item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); } } - void QPDFObjectHandle::setArrayFromVector(std::vector const& items) { diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index e4e1668e..d7505468 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -1,9 +1,6 @@ #include -#include #include -#include -#include static const QPDFObjectHandle null_oh = QPDFObjectHandle::newNull(); @@ -188,18 +185,19 @@ QPDF_Array::getAsVector(std::vector& v) const } } -void -QPDF_Array::setItem(int n, QPDFObjectHandle const& oh) +bool +QPDF_Array::setAt(int at, QPDFObjectHandle const& oh) { + if (at < 0 || at >= size()) { + return false; + } + checkOwnership(oh); if (sparse) { - sp_elements.setAt(n, oh); + sp_elements.setAt(at, oh); } else { - size_t idx = size_t(n); - if (n < 0 || idx >= elements.size()) { - throw std::logic_error("bounds error setting item in QPDF_Array"); - } - elements[idx] = oh.getObj(); + elements[size_t(at)] = oh.getObj(); } + return true; } void diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 773d7309..9904af1b 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -30,19 +30,6 @@ SparseOHArray::disconnect() } } -void -SparseOHArray::setAt(int idx, QPDFObjectHandle oh) -{ - if (idx >= this->n_elements) { - throw std::logic_error("bounds error setting item in SparseOHArray"); - } - if (oh.isDirectNull()) { - this->elements.erase(idx); - } else { - this->elements[idx] = oh.getObj(); - } -} - void SparseOHArray::erase(int at) { diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index edda54ec..f4d1fc3d 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -28,9 +28,8 @@ class QPDF_Array: public QPDFValue return sparse ? sp_elements.size() : int(elements.size()); } QPDFObjectHandle at(int n) const noexcept; + bool setAt(int n, QPDFObjectHandle const& oh); void getAsVector(std::vector&) const; - - void setItem(int, QPDFObjectHandle const&); void setFromVector(std::vector const& items); void setFromVector(std::vector>&& items); bool insert(int at, QPDFObjectHandle const& item); diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh index f2872618..19aa49f0 100644 --- a/libqpdf/qpdf/SparseOHArray.hh +++ b/libqpdf/qpdf/SparseOHArray.hh @@ -28,7 +28,11 @@ class SparseOHArray } QPDFObjectHandle at(int idx) const; void remove_last(); - void setAt(int idx, QPDFObjectHandle oh); + void + setAt(int idx, QPDFObjectHandle oh) + { + elements[idx] = oh.getObj(); + } void erase(int idx); void insert(int idx, QPDFObjectHandle oh); SparseOHArray copy(); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 736c02b4..014ea571 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -303,6 +303,7 @@ QPDFObjectHandle array treating as empty 0 QPDFObjectHandle array null for non-array 0 QPDFObjectHandle array treating as empty vector 0 QPDFObjectHandle array ignoring set item 0 +QPDFObjectHandle set array bounds 0 QPDFObjectHandle array ignoring replace items 0 QPDFObjectHandle array ignoring insert item 0 QPDFObjectHandle insert array bounds 0 diff --git a/qpdf/qtest/qpdf/object-types-os.out b/qpdf/qtest/qpdf/object-types-os.out index 1ba84d50..4b02d156 100644 --- a/qpdf/qtest/qpdf/object-types-os.out +++ b/qpdf/qtest/qpdf/object-types-os.out @@ -6,6 +6,7 @@ WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operatio WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to insert out of bounds array item +WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to set out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/qtest/qpdf/object-types.out b/qpdf/qtest/qpdf/object-types.out index bf41044e..b7089b6b 100644 --- a/qpdf/qtest/qpdf/object-types.out +++ b/qpdf/qtest/qpdf/object-types.out @@ -6,6 +6,7 @@ WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempt WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to insert out of bounds array item +WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to set out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 82361ba0..4a5d0ae8 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1507,6 +1507,7 @@ test_42(QPDF& pdf, char const* arg2) array.eraseItem(-1); array.eraseItem(16059); array.insertItem(42, "/Dontpanic"_qpdf); + array.setArrayItem(42, "/Dontpanic"_qpdf); integer.eraseItem(0); integer.insertItem(0, null); integer.setArrayFromVector(std::vector()); -- cgit v1.2.3-54-g00ecf From 5072238867f37f6c6ecd53dab06e42ea2763cf56 Mon Sep 17 00:00:00 2001 From: m-holger Date: Mon, 2 Jan 2023 19:49:42 +0000 Subject: Refactor QPDF_Array::getAsVector --- libqpdf/QPDFObjectHandle.cc | 5 ++--- libqpdf/QPDF_Array.cc | 16 ++++++++++------ libqpdf/qpdf/QPDF_Array.hh | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 396e2063..20be3f9d 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -888,15 +888,14 @@ QPDFObjectHandle::getArrayAsMatrix() std::vector QPDFObjectHandle::getArrayAsVector() { - std::vector result; auto array = asArray(); if (array) { - array->getAsVector(result); + return array->getAsVector(); } else { typeWarning("array", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); } - return result; + return {}; } // Array mutators diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 3ed18bf4..9593c31f 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -172,16 +172,20 @@ QPDF_Array::at(int n) const noexcept } } -void -QPDF_Array::getAsVector(std::vector& v) const +std::vector +QPDF_Array::getAsVector() const { if (sparse) { - int size = sp_elements.size(); - for (int i = 0; i < size; ++i) { - v.push_back(at(i)); + std::vector v; + v.reserve(size_t(size())); + for (auto const& item: sp_elements.elements) { + v.resize(size_t(item.first), null_oh); + v.push_back(item.second); } + v.resize(size_t(size()), null_oh); + return v; } else { - v = std::vector(elements.cbegin(), elements.cend()); + return {elements.cbegin(), elements.cend()}; } } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index f4d1fc3d..df814d74 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -29,7 +29,7 @@ class QPDF_Array: public QPDFValue } QPDFObjectHandle at(int n) const noexcept; bool setAt(int n, QPDFObjectHandle const& oh); - void getAsVector(std::vector&) const; + std::vector getAsVector() const; void setFromVector(std::vector const& items); void setFromVector(std::vector>&& items); bool insert(int at, QPDFObjectHandle const& item); -- cgit v1.2.3-54-g00ecf From 0aae54d3836107fdb9dc54faf0778bf262dd7e0a Mon Sep 17 00:00:00 2001 From: m-holger Date: Thu, 30 Mar 2023 14:16:07 +0100 Subject: Refactor QPDF_Array::setFromVector --- libqpdf/QPDFObjectHandle.cc | 6 +----- libqpdf/QPDF_Array.cc | 45 +++++++++++++++++---------------------------- libqpdf/qpdf/QPDF_Array.hh | 1 - 3 files changed, 18 insertions(+), 34 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 20be3f9d..c2bc30f0 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -916,11 +916,7 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) void QPDFObjectHandle::setArrayFromVector(std::vector const& items) { - auto array = asArray(); - if (array) { - for (auto const& item: items) { - checkOwnership(item); - } + if (auto array = asArray()) { array->setFromVector(items); } else { typeWarning("array", "ignoring attempt to replace items"); diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 9593c31f..afec05af 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -35,7 +35,18 @@ QPDF_Array::QPDF_Array( QPDFValue(::ot_array, "array"), sparse(sparse) { - setFromVector(std::move(v)); + if (sparse) { + sp_elements = SparseOHArray(); + for (auto&& item: v) { + if (item->getTypeCode() != ::ot_null || + item->getObjGen().isIndirect()) { + sp_elements.elements[sp_elements.n_elements] = std::move(item); + } + ++sp_elements.n_elements; + } + } else { + elements = std::move(v); + } } QPDF_Array::QPDF_Array(SparseOHArray const& items) : @@ -207,33 +218,11 @@ QPDF_Array::setAt(int at, QPDFObjectHandle const& oh) void QPDF_Array::setFromVector(std::vector const& v) { - if (sparse) { - sp_elements = SparseOHArray(); - for (auto const& iter: v) { - sp_elements.elements[sp_elements.n_elements++] = iter.getObj(); - } - } else { - elements.resize(0); - for (auto const& iter: v) { - elements.push_back(iter.getObj()); - } - } -} - -void -QPDF_Array::setFromVector(std::vector>&& v) -{ - if (sparse) { - sp_elements = SparseOHArray(); - for (auto&& item: v) { - if (item->getTypeCode() != ::ot_null || - item->getObjGen().isIndirect()) { - sp_elements.elements[sp_elements.n_elements] = std::move(item); - } - ++sp_elements.n_elements; - } - } else { - elements = std::move(v); + elements.resize(0); + elements.reserve(v.size()); + for (auto const& item: v) { + checkOwnership(item); + elements.push_back(item.getObj()); } } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index df814d74..d0138e5c 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -31,7 +31,6 @@ class QPDF_Array: public QPDFValue bool setAt(int n, QPDFObjectHandle const& oh); std::vector getAsVector() const; void setFromVector(std::vector const& items); - void setFromVector(std::vector>&& items); bool insert(int at, QPDFObjectHandle const& item); void push_back(QPDFObjectHandle const& item); bool erase(int at); -- cgit v1.2.3-54-g00ecf From a7b6975132eed94905eb784a0e267e575cade2cb Mon Sep 17 00:00:00 2001 From: m-holger Date: Wed, 29 Mar 2023 19:52:03 +0100 Subject: Remove SparseOHArray --- libqpdf/CMakeLists.txt | 1 - libqpdf/QPDFObjectHandle.cc | 1 - libqpdf/QPDF_Array.cc | 107 +++++++++++++++++------------------------- libqpdf/SparseOHArray.cc | 1 - libqpdf/qpdf/QPDF_Array.hh | 14 +++--- libqpdf/qpdf/SparseOHArray.hh | 26 ---------- libtests/sparse_array.cc | 1 + 7 files changed, 51 insertions(+), 100 deletions(-) delete mode 100644 libqpdf/SparseOHArray.cc delete mode 100644 libqpdf/qpdf/SparseOHArray.hh (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt index 5e3a628e..623e05d3 100644 --- a/libqpdf/CMakeLists.txt +++ b/libqpdf/CMakeLists.txt @@ -115,7 +115,6 @@ set(libqpdf_SOURCES ResourceFinder.cc SecureRandomDataProvider.cc SF_FlateLzwDecode.cc - SparseOHArray.cc qpdf-c.cc qpdfjob-c.cc qpdflogger-c.cc) diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index c2bc30f0..b3f208a5 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index d5cef946..36c5aaea 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -1,5 +1,6 @@ #include +#include #include static const QPDFObjectHandle null_oh = QPDFObjectHandle::newNull(); @@ -24,6 +25,20 @@ QPDF_Array::checkOwnership(QPDFObjectHandle const& item) const } } +QPDF_Array::QPDF_Array() : + QPDFValue(::ot_array, "array") +{ +} + +QPDF_Array::QPDF_Array(QPDF_Array const& other) : + QPDFValue(::ot_array, "array"), + sparse(other.sparse), + sp_size(other.sp_size), + sp_elements(other.sp_elements), + elements(other.elements) +{ +} + QPDF_Array::QPDF_Array(std::vector const& v) : QPDFValue(::ot_array, "array") { @@ -36,34 +51,18 @@ QPDF_Array::QPDF_Array( sparse(sparse) { if (sparse) { - sp_elements = SparseOHArray(); for (auto&& item: v) { if (item->getTypeCode() != ::ot_null || item->getObjGen().isIndirect()) { - sp_elements.elements[sp_elements.n_elements] = std::move(item); + sp_elements[sp_size] = std::move(item); } - ++sp_elements.n_elements; + ++sp_size; } } else { elements = std::move(v); } } -QPDF_Array::QPDF_Array(SparseOHArray const& items) : - QPDFValue(::ot_array, "array"), - sparse(true), - sp_elements(items) - -{ -} - -QPDF_Array::QPDF_Array(std::vector> const& items) : - QPDFValue(::ot_array, "array"), - sparse(false), - elements(items) -{ -} - std::shared_ptr QPDF_Array::create(std::vector const& items) { @@ -77,37 +76,21 @@ QPDF_Array::create( return do_create(new QPDF_Array(std::move(items), sparse)); } -std::shared_ptr -QPDF_Array::create(SparseOHArray const& items) -{ - return do_create(new QPDF_Array(items)); -} - -std::shared_ptr -QPDF_Array::create(std::vector> const& items) -{ - return do_create(new QPDF_Array(items)); -} - std::shared_ptr QPDF_Array::copy(bool shallow) { if (shallow) { - if (sparse) { - return create(sp_elements); - } else { - return create(elements); - } + return do_create(new QPDF_Array(*this)); } else { if (sparse) { - SparseOHArray result; - result.n_elements = sp_elements.n_elements; - for (auto const& element: sp_elements.elements) { + QPDF_Array* result = new QPDF_Array(); + result->sp_size = sp_size; + for (auto const& element: sp_elements) { auto const& obj = element.second; - result.elements[element.first] = + result->sp_elements[element.first] = obj->getObjGen().isIndirect() ? obj : obj->copy(); } - return create(std::move(result)); + return do_create(result); } else { std::vector> result; result.reserve(elements.size()); @@ -118,7 +101,7 @@ QPDF_Array::copy(bool shallow) : element->copy()) : element); } - return create(std::move(result)); + return create(std::move(result), false); } } } @@ -127,7 +110,7 @@ void QPDF_Array::disconnect() { if (sparse) { - for (auto& item: sp_elements.elements) { + for (auto& item: sp_elements) { auto& obj = item.second; if (!obj->getObjGen().isIndirect()) { obj->disconnect(); @@ -147,8 +130,7 @@ QPDF_Array::unparse() { if (sparse) { std::string result = "[ "; - int size = sp_elements.size(); - for (int i = 0; i < size; ++i) { + for (int i = 0; i < sp_size; ++i) { result += at(i).unparse(); result += " "; } @@ -171,8 +153,7 @@ QPDF_Array::getJSON(int json_version) { if (sparse) { JSON j = JSON::makeArray(); - int size = sp_elements.size(); - for (int i = 0; i < size; ++i) { + for (int i = 0; i < sp_size; ++i) { j.addArrayElement(at(i).getJSON(json_version)); } return j; @@ -192,8 +173,8 @@ QPDF_Array::at(int n) const noexcept if (n < 0 || n >= size()) { return {}; } else if (sparse) { - auto const& iter = sp_elements.elements.find(n); - return iter == sp_elements.elements.end() ? null_oh : (*iter).second; + auto const& iter = sp_elements.find(n); + return iter == sp_elements.end() ? null_oh : (*iter).second; } else { return elements[size_t(n)]; } @@ -205,7 +186,7 @@ QPDF_Array::getAsVector() const if (sparse) { std::vector v; v.reserve(size_t(size())); - for (auto const& item: sp_elements.elements) { + for (auto const& item: sp_elements) { v.resize(size_t(item.first), null_oh); v.push_back(item.second); } @@ -224,7 +205,7 @@ QPDF_Array::setAt(int at, QPDFObjectHandle const& oh) } checkOwnership(oh); if (sparse) { - sp_elements.elements[at] = oh.getObj(); + sp_elements[at] = oh.getObj(); } else { elements[size_t(at)] = oh.getObj(); } @@ -254,19 +235,19 @@ QPDF_Array::insert(int at, QPDFObjectHandle const& item) } else { checkOwnership(item); if (sparse) { - auto iter = sp_elements.elements.crbegin(); - while (iter != sp_elements.elements.crend()) { + auto iter = sp_elements.crbegin(); + while (iter != sp_elements.crend()) { auto key = (iter++)->first; if (key >= at) { - auto nh = sp_elements.elements.extract(key); + auto nh = sp_elements.extract(key); ++nh.key(); - sp_elements.elements.insert(std::move(nh)); + sp_elements.insert(std::move(nh)); } else { break; } } - sp_elements.elements[at] = item.getObj(); - ++sp_elements.n_elements; + sp_elements[at] = item.getObj(); + ++sp_size; } else { elements.insert(elements.cbegin() + at, item.getObj()); } @@ -279,7 +260,7 @@ QPDF_Array::push_back(QPDFObjectHandle const& item) { checkOwnership(item); if (sparse) { - sp_elements.elements[sp_elements.n_elements++] = item.getObj(); + sp_elements[sp_size++] = item.getObj(); } else { elements.push_back(item.getObj()); } @@ -292,20 +273,20 @@ QPDF_Array::erase(int at) return false; } if (sparse) { - auto end = sp_elements.elements.end(); - if (auto iter = sp_elements.elements.lower_bound(at); iter != end) { + auto end = sp_elements.end(); + if (auto iter = sp_elements.lower_bound(at); iter != end) { if (iter->first == at) { iter++; - sp_elements.elements.erase(at); + sp_elements.erase(at); } while (iter != end) { - auto nh = sp_elements.elements.extract(iter++); + auto nh = sp_elements.extract(iter++); --nh.key(); - sp_elements.elements.insert(std::move(nh)); + sp_elements.insert(std::move(nh)); } } - --sp_elements.n_elements; + --sp_size; } else { elements.erase(elements.cbegin() + at); } diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc deleted file mode 100644 index 8b137891..00000000 --- a/libqpdf/SparseOHArray.cc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index d0138e5c..4762bb6e 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -3,7 +3,7 @@ #include -#include +#include #include class QPDF_Array: public QPDFValue @@ -14,9 +14,6 @@ class QPDF_Array: public QPDFValue create(std::vector const& items); static std::shared_ptr create(std::vector>&& items, bool sparse); - static std::shared_ptr create(SparseOHArray const& items); - static std::shared_ptr - create(std::vector> const& items); virtual std::shared_ptr copy(bool shallow = false); virtual std::string unparse(); virtual JSON getJSON(int json_version); @@ -25,7 +22,7 @@ class QPDF_Array: public QPDFValue int size() const noexcept { - return sparse ? sp_elements.size() : int(elements.size()); + return sparse ? sp_size : int(elements.size()); } QPDFObjectHandle at(int n) const noexcept; bool setAt(int n, QPDFObjectHandle const& oh); @@ -36,15 +33,16 @@ class QPDF_Array: public QPDFValue bool erase(int at); private: + QPDF_Array(); + QPDF_Array(QPDF_Array const&); QPDF_Array(std::vector const& items); QPDF_Array(std::vector>&& items, bool sparse); - QPDF_Array(SparseOHArray const& items); - QPDF_Array(std::vector> const& items); void checkOwnership(QPDFObjectHandle const& item) const; bool sparse{false}; - SparseOHArray sp_elements; + int sp_size{0}; + std::map> sp_elements; std::vector> elements; }; diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh deleted file mode 100644 index 5760f174..00000000 --- a/libqpdf/qpdf/SparseOHArray.hh +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef QPDF_SPARSEOHARRAY_HH -#define QPDF_SPARSEOHARRAY_HH - -#include -#include -#include - -class QPDF_Array; - -class SparseOHArray -{ - public: - SparseOHArray() = default; - int - size() const noexcept - { - return n_elements; - } - - private: - friend class QPDF_Array; - std::map> elements; - int n_elements{0}; -}; - -#endif // QPDF_SPARSEOHARRAY_HH diff --git a/libtests/sparse_array.cc b/libtests/sparse_array.cc index a970b199..9f31c96f 100644 --- a/libtests/sparse_array.cc +++ b/libtests/sparse_array.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include -- cgit v1.2.3-54-g00ecf