Commit 1bb23d0545dfe2d651cb22b6135d99c1c9ef85d5
1 parent
cedb37ca
Refactor QPDF_Array::insertItem and rename to insert
Showing
8 changed files
with
34 additions
and
34 deletions
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -932,9 +932,12 @@ QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) |
| 932 | 932 | void |
| 933 | 933 | QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) |
| 934 | 934 | { |
| 935 | - auto array = asArray(); | |
| 936 | - if (array) { | |
| 937 | - array->insertItem(at, item); | |
| 935 | + if (auto array = asArray()) { | |
| 936 | + if (!array->insert(at, item)) { | |
| 937 | + objectWarning( | |
| 938 | + "ignoring attempt to insert out of bounds array item"); | |
| 939 | + QTC::TC("qpdf", "QPDFObjectHandle insert array bounds"); | |
| 940 | + } | |
| 938 | 941 | } else { |
| 939 | 942 | typeWarning("array", "ignoring attempt to insert item"); |
| 940 | 943 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); | ... | ... |
libqpdf/QPDF_Array.cc
| ... | ... | @@ -236,31 +236,24 @@ QPDF_Array::setFromVector(std::vector<std::shared_ptr<QPDFObject>>&& v) |
| 236 | 236 | } |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | -void | |
| 240 | -QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) | |
| 239 | +bool | |
| 240 | +QPDF_Array::insert(int at, QPDFObjectHandle const& item) | |
| 241 | 241 | { |
| 242 | - if (sparse) { | |
| 242 | + int sz = size(); | |
| 243 | + if (at < 0 || at > sz) { | |
| 243 | 244 | // As special case, also allow insert beyond the end |
| 244 | - if ((at < 0) || (at > sp_elements.size())) { | |
| 245 | - throw std::logic_error( | |
| 246 | - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); | |
| 247 | - } | |
| 248 | - sp_elements.insert(at, item); | |
| 245 | + return false; | |
| 246 | + } else if (at == sz) { | |
| 247 | + push_back(item); | |
| 249 | 248 | } else { |
| 250 | - // As special case, also allow insert beyond the end | |
| 251 | - size_t idx = QIntC::to_size(at); | |
| 252 | - if ((at < 0) || (at > QIntC::to_int(elements.size()))) { | |
| 253 | - throw std::logic_error( | |
| 254 | - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); | |
| 255 | - } | |
| 256 | - if (idx == elements.size()) { | |
| 257 | - // Allow inserting to the last position | |
| 258 | - elements.push_back(item.getObj()); | |
| 249 | + checkOwnership(item); | |
| 250 | + if (sparse) { | |
| 251 | + sp_elements.insert(at, item); | |
| 259 | 252 | } else { |
| 260 | - int n = int(idx); | |
| 261 | - elements.insert(elements.cbegin() + n, item.getObj()); | |
| 253 | + elements.insert(elements.cbegin() + at, item.getObj()); | |
| 262 | 254 | } |
| 263 | 255 | } |
| 256 | + return true; | |
| 264 | 257 | } |
| 265 | 258 | |
| 266 | 259 | void | ... | ... |
libqpdf/SparseOHArray.cc
| ... | ... | @@ -64,23 +64,23 @@ SparseOHArray::erase(int idx) |
| 64 | 64 | void |
| 65 | 65 | SparseOHArray::insert(int idx, QPDFObjectHandle oh) |
| 66 | 66 | { |
| 67 | - if (idx > this->n_elements) { | |
| 68 | - throw std::logic_error("bounds error inserting item to SparseOHArray"); | |
| 69 | - } else if (idx == this->n_elements) { | |
| 67 | + if (idx == n_elements) { | |
| 70 | 68 | // Allow inserting to the last position |
| 71 | 69 | append(oh); |
| 72 | 70 | } else { |
| 73 | - decltype(this->elements) dest; | |
| 74 | - for (auto const& iter: this->elements) { | |
| 75 | - if (iter.first < idx) { | |
| 76 | - dest.insert(iter); | |
| 71 | + auto iter = elements.crbegin(); | |
| 72 | + while (iter != elements.crend()) { | |
| 73 | + auto key = (iter++)->first; | |
| 74 | + if (key >= idx) { | |
| 75 | + auto nh = elements.extract(key); | |
| 76 | + ++nh.key(); | |
| 77 | + elements.insert(std::move(nh)); | |
| 77 | 78 | } else { |
| 78 | - dest[iter.first + 1] = iter.second; | |
| 79 | + break; | |
| 79 | 80 | } |
| 80 | 81 | } |
| 81 | - this->elements = dest; | |
| 82 | - this->elements[idx] = oh.getObj(); | |
| 83 | - ++this->n_elements; | |
| 82 | + elements[idx] = oh.getObj(); | |
| 83 | + ++n_elements; | |
| 84 | 84 | } |
| 85 | 85 | } |
| 86 | 86 | ... | ... |
libqpdf/qpdf/QPDF_Array.hh
| ... | ... | @@ -33,7 +33,7 @@ class QPDF_Array: public QPDFValue |
| 33 | 33 | void setItem(int, QPDFObjectHandle const&); |
| 34 | 34 | void setFromVector(std::vector<QPDFObjectHandle> const& items); |
| 35 | 35 | void setFromVector(std::vector<std::shared_ptr<QPDFObject>>&& items); |
| 36 | - void insertItem(int at, QPDFObjectHandle const& item); | |
| 36 | + bool insert(int at, QPDFObjectHandle const& item); | |
| 37 | 37 | void push_back(QPDFObjectHandle const& item); |
| 38 | 38 | void eraseItem(int at); |
| 39 | 39 | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -305,6 +305,7 @@ QPDFObjectHandle array treating as empty vector 0 |
| 305 | 305 | QPDFObjectHandle array ignoring set item 0 |
| 306 | 306 | QPDFObjectHandle array ignoring replace items 0 |
| 307 | 307 | QPDFObjectHandle array ignoring insert item 0 |
| 308 | +QPDFObjectHandle insert array bounds 0 | |
| 308 | 309 | QPDFObjectHandle array ignoring append item 0 |
| 309 | 310 | QPDFObjectHandle array ignoring erase item 0 |
| 310 | 311 | QPDFObjectHandle dictionary false for hasKey 0 | ... | ... |
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 |
| 5 | 5 | 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 |
| 6 | 6 | WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item |
| 7 | 7 | WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item |
| 8 | +WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to insert out of bounds array item | |
| 8 | 9 | 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 |
| 9 | 10 | 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 |
| 10 | 11 | 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 | ... | ... |
qpdf/qtest/qpdf/object-types.out
| ... | ... | @@ -5,6 +5,7 @@ WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempt |
| 5 | 5 | WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to append item |
| 6 | 6 | WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item |
| 7 | 7 | WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item |
| 8 | +WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to insert out of bounds array item | |
| 8 | 9 | WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to erase item |
| 9 | 10 | WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to insert item |
| 10 | 11 | WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to replace items | ... | ... |
qpdf/test_driver.cc
| ... | ... | @@ -1506,6 +1506,7 @@ test_42(QPDF& pdf, char const* arg2) |
| 1506 | 1506 | integer.appendItem(null); |
| 1507 | 1507 | array.eraseItem(-1); |
| 1508 | 1508 | array.eraseItem(16059); |
| 1509 | + array.insertItem(42, "/Dontpanic"_qpdf); | |
| 1509 | 1510 | integer.eraseItem(0); |
| 1510 | 1511 | integer.insertItem(0, null); |
| 1511 | 1512 | integer.setArrayFromVector(std::vector<QPDFObjectHandle>()); | ... | ... |