Commit 4d37389befc705b671d8fa7a1da2b7117b50f454
1 parent
1bb23d05
Refactor QPDF_Array::eraseItem and rename to erase
Showing
6 changed files
with
28 additions
and
29 deletions
libqpdf/QPDFObjectHandle.cc
| @@ -972,17 +972,14 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) | @@ -972,17 +972,14 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) | ||
| 972 | void | 972 | void |
| 973 | QPDFObjectHandle::eraseItem(int at) | 973 | QPDFObjectHandle::eraseItem(int at) |
| 974 | { | 974 | { |
| 975 | - auto array = asArray(); | ||
| 976 | - if (array && at < array->size() && at >= 0) { | ||
| 977 | - array->eraseItem(at); | ||
| 978 | - } else { | ||
| 979 | - if (array) { | 975 | + if (auto array = asArray()) { |
| 976 | + if (!array->erase(at)) { | ||
| 980 | objectWarning("ignoring attempt to erase out of bounds array item"); | 977 | objectWarning("ignoring attempt to erase out of bounds array item"); |
| 981 | QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); | 978 | QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); |
| 982 | - } else { | ||
| 983 | - typeWarning("array", "ignoring attempt to erase item"); | ||
| 984 | - QTC::TC("qpdf", "QPDFObjectHandle array ignoring erase item"); | ||
| 985 | } | 979 | } |
| 980 | + } else { | ||
| 981 | + typeWarning("array", "ignoring attempt to erase item"); | ||
| 982 | + QTC::TC("qpdf", "QPDFObjectHandle array ignoring erase item"); | ||
| 986 | } | 983 | } |
| 987 | } | 984 | } |
| 988 | 985 |
libqpdf/QPDF_Array.cc
| @@ -267,17 +267,16 @@ QPDF_Array::push_back(QPDFObjectHandle const& item) | @@ -267,17 +267,16 @@ QPDF_Array::push_back(QPDFObjectHandle const& item) | ||
| 267 | } | 267 | } |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | -void | ||
| 271 | -QPDF_Array::eraseItem(int at) | 270 | +bool |
| 271 | +QPDF_Array::erase(int at) | ||
| 272 | { | 272 | { |
| 273 | + if (at < 0 || at >= size()) { | ||
| 274 | + return false; | ||
| 275 | + } | ||
| 273 | if (sparse) { | 276 | if (sparse) { |
| 274 | sp_elements.erase(at); | 277 | sp_elements.erase(at); |
| 275 | } else { | 278 | } else { |
| 276 | - size_t idx = QIntC::to_size(at); | ||
| 277 | - if (idx >= elements.size()) { | ||
| 278 | - throw std::logic_error("bounds error erasing item from OHArray"); | ||
| 279 | - } | ||
| 280 | - int n = int(idx); | ||
| 281 | - elements.erase(elements.cbegin() + n); | 279 | + elements.erase(elements.cbegin() + at); |
| 282 | } | 280 | } |
| 281 | + return true; | ||
| 283 | } | 282 | } |
libqpdf/SparseOHArray.cc
| @@ -44,21 +44,22 @@ SparseOHArray::setAt(int idx, QPDFObjectHandle oh) | @@ -44,21 +44,22 @@ SparseOHArray::setAt(int idx, QPDFObjectHandle oh) | ||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | void | 46 | void |
| 47 | -SparseOHArray::erase(int idx) | 47 | +SparseOHArray::erase(int at) |
| 48 | { | 48 | { |
| 49 | - if (idx >= this->n_elements) { | ||
| 50 | - throw std::logic_error("bounds error erasing item from SparseOHArray"); | ||
| 51 | - } | ||
| 52 | - decltype(this->elements) dest; | ||
| 53 | - for (auto const& iter: this->elements) { | ||
| 54 | - if (iter.first < idx) { | ||
| 55 | - dest.insert(iter); | ||
| 56 | - } else if (iter.first > idx) { | ||
| 57 | - dest[iter.first - 1] = iter.second; | 49 | + auto end = elements.end(); |
| 50 | + if (auto iter = elements.lower_bound(at); iter != end) { | ||
| 51 | + if (iter->first == at) { | ||
| 52 | + iter++; | ||
| 53 | + elements.erase(at); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + while (iter != end) { | ||
| 57 | + auto nh = elements.extract(iter++); | ||
| 58 | + --nh.key(); | ||
| 59 | + elements.insert(std::move(nh)); | ||
| 58 | } | 60 | } |
| 59 | } | 61 | } |
| 60 | - this->elements = dest; | ||
| 61 | - --this->n_elements; | 62 | + --n_elements; |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | void | 65 | void |
libqpdf/qpdf/QPDF_Array.hh
| @@ -35,7 +35,7 @@ class QPDF_Array: public QPDFValue | @@ -35,7 +35,7 @@ class QPDF_Array: public QPDFValue | ||
| 35 | void setFromVector(std::vector<std::shared_ptr<QPDFObject>>&& items); | 35 | void setFromVector(std::vector<std::shared_ptr<QPDFObject>>&& items); |
| 36 | bool insert(int at, QPDFObjectHandle const& item); | 36 | bool insert(int at, QPDFObjectHandle const& item); |
| 37 | void push_back(QPDFObjectHandle const& item); | 37 | void push_back(QPDFObjectHandle const& item); |
| 38 | - void eraseItem(int at); | 38 | + bool erase(int at); |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | QPDF_Array(std::vector<QPDFObjectHandle> const& items); | 41 | QPDF_Array(std::vector<QPDFObjectHandle> const& items); |
qpdf/qtest/qpdf/test88.out
| 1 | WARNING: test array: ignoring attempt to erase out of bounds array item | 1 | WARNING: test array: ignoring attempt to erase out of bounds array item |
| 2 | +WARNING: minimal.pdf, object 1 0 at offset 19: operation for array attempted on object of type dictionary: ignoring attempt to erase item | ||
| 2 | test 88 done | 3 | test 88 done |
qpdf/test_driver.cc
| @@ -3283,6 +3283,7 @@ test_88(QPDF& pdf, char const* arg2) | @@ -3283,6 +3283,7 @@ test_88(QPDF& pdf, char const* arg2) | ||
| 3283 | auto arr2 = pdf.getRoot().replaceKeyAndGetNew("/QTest", "[1 2]"_qpdf); | 3283 | auto arr2 = pdf.getRoot().replaceKeyAndGetNew("/QTest", "[1 2]"_qpdf); |
| 3284 | arr2.setObjectDescription(&pdf, "test array"); | 3284 | arr2.setObjectDescription(&pdf, "test array"); |
| 3285 | assert(arr2.eraseItemAndGetOld(50).isNull()); | 3285 | assert(arr2.eraseItemAndGetOld(50).isNull()); |
| 3286 | + assert(pdf.getRoot().eraseItemAndGetOld(0).isNull()); | ||
| 3286 | } | 3287 | } |
| 3287 | 3288 | ||
| 3288 | static void | 3289 | static void |