Commit e3ce9e173c1a70ed02a5d749b262ebae4e0fd663
1 parent
14f445b1
Refactor `NNTree` and `NNTreeImpl` to use `Array` API, simplify logic, and remove redundant traces.
Showing
2 changed files
with
65 additions
and
70 deletions
libqpdf/NNTree.cc
| @@ -11,6 +11,8 @@ | @@ -11,6 +11,8 @@ | ||
| 11 | #include <exception> | 11 | #include <exception> |
| 12 | #include <utility> | 12 | #include <utility> |
| 13 | 13 | ||
| 14 | +using namespace qpdf; | ||
| 15 | + | ||
| 14 | static std::string | 16 | static std::string |
| 15 | get_description(QPDFObjectHandle const& node) | 17 | get_description(QPDFObjectHandle const& node) |
| 16 | { | 18 | { |
| @@ -66,7 +68,7 @@ NNTreeIterator::updateIValue(bool allow_invalid) | @@ -66,7 +68,7 @@ NNTreeIterator::updateIValue(bool allow_invalid) | ||
| 66 | ivalue.second = QPDFObjectHandle(); | 68 | ivalue.second = QPDFObjectHandle(); |
| 67 | return; | 69 | return; |
| 68 | } | 70 | } |
| 69 | - auto items = node.getKey(impl.details.itemsKey()); | 71 | + Array items = node.getKey(impl.details.itemsKey()); |
| 70 | if (!std::cmp_less(item_number + 1, items.size())) { | 72 | if (!std::cmp_less(item_number + 1, items.size())) { |
| 71 | impl.error(node, "update ivalue: items array is too short"); | 73 | impl.error(node, "update ivalue: items array is too short"); |
| 72 | } | 74 | } |
| @@ -85,7 +87,7 @@ NNTreeIterator::getNextKid(PathElement& pe, bool backward) | @@ -85,7 +87,7 @@ NNTreeIterator::getNextKid(PathElement& pe, bool backward) | ||
| 85 | { | 87 | { |
| 86 | while (true) { | 88 | while (true) { |
| 87 | pe.kid_number += backward ? -1 : 1; | 89 | pe.kid_number += backward ? -1 : 1; |
| 88 | - auto kids = pe.node.getKey("/Kids"); | 90 | + Array kids = pe.node.getKey("/Kids"); |
| 89 | if (pe.kid_number >= 0 && std::cmp_less(pe.kid_number, kids.size())) { | 91 | if (pe.kid_number >= 0 && std::cmp_less(pe.kid_number, kids.size())) { |
| 90 | auto result = kids[pe.kid_number]; | 92 | auto result = kids[pe.kid_number]; |
| 91 | if (result.isDictionary() && | 93 | if (result.isDictionary() && |
| @@ -117,7 +119,7 @@ NNTreeIterator::increment(bool backward) | @@ -117,7 +119,7 @@ NNTreeIterator::increment(bool backward) | ||
| 117 | 119 | ||
| 118 | while (valid()) { | 120 | while (valid()) { |
| 119 | item_number += backward ? -2 : 2; | 121 | item_number += backward ? -2 : 2; |
| 120 | - auto items = node.getKey(impl.details.itemsKey()); | 122 | + Array items = node.getKey(impl.details.itemsKey()); |
| 121 | if (item_number < 0 || std::cmp_greater_equal(item_number, items.size())) { | 123 | if (item_number < 0 || std::cmp_greater_equal(item_number, items.size())) { |
| 122 | bool found = false; | 124 | bool found = false; |
| 123 | setItemNumber(QPDFObjectHandle(), -1); | 125 | setItemNumber(QPDFObjectHandle(), -1); |
| @@ -152,9 +154,9 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | @@ -152,9 +154,9 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | ||
| 152 | a_node.removeKey("/Limits"); | 154 | a_node.removeKey("/Limits"); |
| 153 | break; | 155 | break; |
| 154 | } | 156 | } |
| 155 | - auto kids = a_node.getKey("/Kids"); | ||
| 156 | - size_t nkids = kids.isArray() ? kids.size() : 0; | ||
| 157 | - auto items = a_node.getKey(impl.details.itemsKey()); | 157 | + Array kids = a_node.getKey("/Kids"); |
| 158 | + size_t nkids = kids.size(); | ||
| 159 | + Array items = a_node.getKey(impl.details.itemsKey()); | ||
| 158 | size_t nitems = items.size(); | 160 | size_t nitems = items.size(); |
| 159 | 161 | ||
| 160 | bool changed = true; | 162 | bool changed = true; |
| @@ -167,8 +169,8 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | @@ -167,8 +169,8 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | ||
| 167 | auto first_kid = kids[0]; | 169 | auto first_kid = kids[0]; |
| 168 | auto last_kid = kids[nkids - 1u]; | 170 | auto last_kid = kids[nkids - 1u]; |
| 169 | if (first_kid.isDictionary() && last_kid.isDictionary()) { | 171 | if (first_kid.isDictionary() && last_kid.isDictionary()) { |
| 170 | - auto first_limits = first_kid.getKey("/Limits"); | ||
| 171 | - auto last_limits = last_kid.getKey("/Limits"); | 172 | + Array first_limits = first_kid.getKey("/Limits"); |
| 173 | + Array last_limits = last_kid.getKey("/Limits"); | ||
| 172 | if (first_limits.size() >= 2 && last_limits.size() >= 2) { | 174 | if (first_limits.size() >= 2 && last_limits.size() >= 2) { |
| 173 | first = first_limits[0]; | 175 | first = first_limits[0]; |
| 174 | last = last_limits[1]; | 176 | last = last_limits[1]; |
| @@ -176,16 +178,14 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | @@ -176,16 +178,14 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite | ||
| 176 | } | 178 | } |
| 177 | } | 179 | } |
| 178 | if (first && last) { | 180 | if (first && last) { |
| 179 | - auto limits = QPDFObjectHandle::newArray(); | ||
| 180 | - limits.appendItem(first); | ||
| 181 | - limits.appendItem(last); | ||
| 182 | - auto olimits = a_node.getKey("/Limits"); | 181 | + Array limits({first, last}); |
| 182 | + Array olimits = a_node.getKey("/Limits"); | ||
| 183 | if (olimits.size() == 2) { | 183 | if (olimits.size() == 2) { |
| 184 | auto ofirst = olimits[0]; | 184 | auto ofirst = olimits[0]; |
| 185 | auto olast = olimits[1]; | 185 | auto olast = olimits[1]; |
| 186 | if (impl.details.keyValid(ofirst) && impl.details.keyValid(olast) && | 186 | if (impl.details.keyValid(ofirst) && impl.details.keyValid(olast) && |
| 187 | - (impl.details.compareKeys(first, ofirst) == 0) && | ||
| 188 | - (impl.details.compareKeys(last, olast) == 0)) { | 187 | + impl.details.compareKeys(first, ofirst) == 0 && |
| 188 | + impl.details.compareKeys(last, olast) == 0) { | ||
| 189 | changed = false; | 189 | changed = false; |
| 190 | } | 190 | } |
| 191 | } | 191 | } |
| @@ -240,24 +240,23 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | @@ -240,24 +240,23 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | ||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | // Find the array we actually need to split, which is either this node's kids or items. | 242 | // Find the array we actually need to split, which is either this node's kids or items. |
| 243 | - auto kids = to_split.getKey("/Kids"); | ||
| 244 | - int nkids = kids.isArray() ? static_cast<int>(kids.size()) : 0; | ||
| 245 | - auto items = to_split.getKey(impl.details.itemsKey()); | ||
| 246 | - int nitems = items.isArray() ? static_cast<int>(items.size()) : 0; | 243 | + Array kids = to_split.getKey("/Kids"); |
| 244 | + size_t nkids = kids.size(); | ||
| 245 | + Array items = to_split.getKey(impl.details.itemsKey()); | ||
| 246 | + size_t nitems = items.size(); | ||
| 247 | 247 | ||
| 248 | - QPDFObjectHandle first_half; | ||
| 249 | - int n = 0; | 248 | + Array first_half; |
| 249 | + size_t n = 0; | ||
| 250 | std::string key; | 250 | std::string key; |
| 251 | - int threshold = 0; | 251 | + size_t threshold = static_cast<size_t>(impl.split_threshold); |
| 252 | if (nkids > 0) { | 252 | if (nkids > 0) { |
| 253 | first_half = kids; | 253 | first_half = kids; |
| 254 | n = nkids; | 254 | n = nkids; |
| 255 | - threshold = impl.split_threshold; | ||
| 256 | key = "/Kids"; | 255 | key = "/Kids"; |
| 257 | } else if (nitems > 0) { | 256 | } else if (nitems > 0) { |
| 258 | first_half = items; | 257 | first_half = items; |
| 259 | n = nitems; | 258 | n = nitems; |
| 260 | - threshold = 2 * impl.split_threshold; | 259 | + threshold *= 2; |
| 261 | key = impl.details.itemsKey(); | 260 | key = impl.details.itemsKey(); |
| 262 | } else { | 261 | } else { |
| 263 | throw std::logic_error("NNTreeIterator::split called on invalid node"); | 262 | throw std::logic_error("NNTreeIterator::split called on invalid node"); |
| @@ -289,8 +288,8 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | @@ -289,8 +288,8 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | ||
| 289 | 288 | ||
| 290 | auto first_node = impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); | 289 | auto first_node = impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); |
| 291 | first_node.replaceKey(key, first_half); | 290 | first_node.replaceKey(key, first_half); |
| 292 | - QPDFObjectHandle new_kids = QPDFObjectHandle::newArray(); | ||
| 293 | - new_kids.appendItem(first_node); | 291 | + Array new_kids; |
| 292 | + new_kids.push_back(first_node); | ||
| 294 | to_split.removeKey("/Limits"); // already shouldn't be there for root | 293 | to_split.removeKey("/Limits"); // already shouldn't be there for root |
| 295 | to_split.removeKey(impl.details.itemsKey()); | 294 | to_split.removeKey(impl.details.itemsKey()); |
| 296 | to_split.replaceKey("/Kids", new_kids); | 295 | to_split.replaceKey("/Kids", new_kids); |
| @@ -310,11 +309,11 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | @@ -310,11 +309,11 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | ||
| 310 | 309 | ||
| 311 | // Create a second half array, and transfer the second half of the items into the second half | 310 | // Create a second half array, and transfer the second half of the items into the second half |
| 312 | // array. | 311 | // array. |
| 313 | - QPDFObjectHandle second_half = QPDFObjectHandle::newArray(); | ||
| 314 | - int start_idx = ((n / 2) & ~1); | 312 | + Array second_half; |
| 313 | + auto start_idx = static_cast<int>((n / 2) & ~1u); | ||
| 315 | while (std::cmp_greater(first_half.size(), start_idx)) { | 314 | while (std::cmp_greater(first_half.size(), start_idx)) { |
| 316 | - second_half.appendItem(first_half[start_idx]); | ||
| 317 | - first_half.eraseItem(start_idx); | 315 | + second_half.push_back(first_half[start_idx]); |
| 316 | + first_half.erase(start_idx); | ||
| 318 | } | 317 | } |
| 319 | resetLimits(to_split, parent); | 318 | resetLimits(to_split, parent); |
| 320 | 319 | ||
| @@ -331,8 +330,8 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | @@ -331,8 +330,8 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato | ||
| 331 | // kid_number to traverse through it. We need to update to_split's path element, or the node if | 330 | // kid_number to traverse through it. We need to update to_split's path element, or the node if |
| 332 | // this is a leaf, so that the kid/item number points to the right place. | 331 | // this is a leaf, so that the kid/item number points to the right place. |
| 333 | 332 | ||
| 334 | - auto parent_kids = parent->node.getKey("/Kids"); | ||
| 335 | - parent_kids.insertItem(parent->kid_number + 1, second_node); | 333 | + Array parent_kids = parent->node.getKey("/Kids"); |
| 334 | + parent_kids.insert(parent->kid_number + 1, second_node); | ||
| 336 | auto cur_elem = parent; | 335 | auto cur_elem = parent; |
| 337 | ++cur_elem; // points to end() for leaf nodes | 336 | ++cur_elem; // points to end() for leaf nodes |
| 338 | int old_idx = (is_leaf ? item_number : cur_elem->kid_number); | 337 | int old_idx = (is_leaf ? item_number : cur_elem->kid_number); |
| @@ -367,22 +366,21 @@ void | @@ -367,22 +366,21 @@ void | ||
| 367 | NNTreeIterator::insertAfter(QPDFObjectHandle const& key, QPDFObjectHandle const& value) | 366 | NNTreeIterator::insertAfter(QPDFObjectHandle const& key, QPDFObjectHandle const& value) |
| 368 | { | 367 | { |
| 369 | if (!valid()) { | 368 | if (!valid()) { |
| 370 | - QTC::TC("qpdf", "NNTree insertAfter inserts first"); | ||
| 371 | impl.insertFirst(key, value); | 369 | impl.insertFirst(key, value); |
| 372 | deepen(impl.oh, true, false); | 370 | deepen(impl.oh, true, false); |
| 373 | return; | 371 | return; |
| 374 | } | 372 | } |
| 375 | 373 | ||
| 376 | - auto items = node.getKey(impl.details.itemsKey()); | 374 | + Array items = node.getKey(impl.details.itemsKey()); |
| 375 | + if (!items) { | ||
| 376 | + impl.error(node, "node contains no items array"); | ||
| 377 | + } | ||
| 377 | 378 | ||
| 378 | if (std::cmp_less(items.size(), item_number + 2)) { | 379 | if (std::cmp_less(items.size(), item_number + 2)) { |
| 379 | - if (!items.isArray()) { | ||
| 380 | - impl.error(node, "node contains no items array"); | ||
| 381 | - } | ||
| 382 | impl.error(node, "insert: items array is too short"); | 380 | impl.error(node, "insert: items array is too short"); |
| 383 | } | 381 | } |
| 384 | - items.insertItem(item_number + 2, key); | ||
| 385 | - items.insertItem(item_number + 3, value); | 382 | + items.insert(item_number + 2, key); |
| 383 | + items.insert(item_number + 3, value); | ||
| 386 | resetLimits(node, lastPathElement()); | 384 | resetLimits(node, lastPathElement()); |
| 387 | split(node, lastPathElement()); | 385 | split(node, lastPathElement()); |
| 388 | increment(false); | 386 | increment(false); |
| @@ -396,14 +394,14 @@ NNTreeIterator::remove() | @@ -396,14 +394,14 @@ NNTreeIterator::remove() | ||
| 396 | if (!valid()) { | 394 | if (!valid()) { |
| 397 | throw std::logic_error("attempt made to remove an invalid iterator"); | 395 | throw std::logic_error("attempt made to remove an invalid iterator"); |
| 398 | } | 396 | } |
| 399 | - auto items = node.getKey(impl.details.itemsKey()); | 397 | + Array items = node.getKey(impl.details.itemsKey()); |
| 400 | int nitems = static_cast<int>(items.size()); | 398 | int nitems = static_cast<int>(items.size()); |
| 401 | if (std::cmp_greater(item_number + 2, nitems)) { | 399 | if (std::cmp_greater(item_number + 2, nitems)) { |
| 402 | impl.error(node, "found short items array while removing an item"); | 400 | impl.error(node, "found short items array while removing an item"); |
| 403 | } | 401 | } |
| 404 | 402 | ||
| 405 | - items.eraseItem(item_number); | ||
| 406 | - items.eraseItem(item_number); | 403 | + items.erase(item_number); |
| 404 | + items.erase(item_number); | ||
| 407 | nitems -= 2; | 405 | nitems -= 2; |
| 408 | 406 | ||
| 409 | if (nitems > 0) { | 407 | if (nitems > 0) { |
| @@ -443,8 +441,8 @@ NNTreeIterator::remove() | @@ -443,8 +441,8 @@ NNTreeIterator::remove() | ||
| 443 | auto element = lastPathElement(); | 441 | auto element = lastPathElement(); |
| 444 | auto parent = element; | 442 | auto parent = element; |
| 445 | --parent; | 443 | --parent; |
| 446 | - auto kids = element->node.getKey("/Kids"); | ||
| 447 | - kids.eraseItem(element->kid_number); | 444 | + Array kids = element->node.getKey("/Kids"); |
| 445 | + kids.erase(element->kid_number); | ||
| 448 | auto nkids = kids.size(); | 446 | auto nkids = kids.size(); |
| 449 | if (nkids > 0) { | 447 | if (nkids > 0) { |
| 450 | // The logic here is similar to the items case. | 448 | // The logic here is similar to the items case. |
| @@ -462,7 +460,7 @@ NNTreeIterator::remove() | @@ -462,7 +460,7 @@ NNTreeIterator::remove() | ||
| 462 | } | 460 | } |
| 463 | } else { | 461 | } else { |
| 464 | // Next kid is in deleted kid's position | 462 | // Next kid is in deleted kid's position |
| 465 | - deepen(kids.getArrayItem(element->kid_number), true, true); | 463 | + deepen(kids.get(element->kid_number), true, true); |
| 466 | } | 464 | } |
| 467 | return; | 465 | return; |
| 468 | } | 466 | } |
| @@ -470,7 +468,7 @@ NNTreeIterator::remove() | @@ -470,7 +468,7 @@ NNTreeIterator::remove() | ||
| 470 | if (parent == path.end()) { | 468 | if (parent == path.end()) { |
| 471 | // We erased the very last item. Convert the root to an empty items array. | 469 | // We erased the very last item. Convert the root to an empty items array. |
| 472 | element->node.removeKey("/Kids"); | 470 | element->node.removeKey("/Kids"); |
| 473 | - element->node.replaceKey(impl.details.itemsKey(), QPDFObjectHandle::newArray()); | 471 | + element->node.replaceKey(impl.details.itemsKey(), Array()); |
| 474 | path.clear(); | 472 | path.clear(); |
| 475 | setItemNumber(impl.oh, -1); | 473 | setItemNumber(impl.oh, -1); |
| 476 | return; | 474 | return; |
| @@ -527,10 +525,7 @@ NNTreeIterator::operator==(NNTreeIterator const& other) const | @@ -527,10 +525,7 @@ NNTreeIterator::operator==(NNTreeIterator const& other) const | ||
| 527 | ++tpi; | 525 | ++tpi; |
| 528 | ++opi; | 526 | ++opi; |
| 529 | } | 527 | } |
| 530 | - if (item_number != other.item_number) { | ||
| 531 | - return false; | ||
| 532 | - } | ||
| 533 | - return true; | 528 | + return item_number == other.item_number; |
| 534 | } | 529 | } |
| 535 | 530 | ||
| 536 | void | 531 | void |
| @@ -574,27 +569,30 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | @@ -574,27 +569,30 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | ||
| 574 | return fail(a_node, "non-dictionary node while traversing name/number tree"); | 569 | return fail(a_node, "non-dictionary node while traversing name/number tree"); |
| 575 | } | 570 | } |
| 576 | 571 | ||
| 577 | - auto items = a_node.getKey(impl.details.itemsKey()); | 572 | + Array items = a_node.getKey(impl.details.itemsKey()); |
| 578 | int nitems = static_cast<int>(items.size()); | 573 | int nitems = static_cast<int>(items.size()); |
| 579 | if (nitems > 1) { | 574 | if (nitems > 1) { |
| 580 | setItemNumber(a_node, first ? 0 : nitems - 2); | 575 | setItemNumber(a_node, first ? 0 : nitems - 2); |
| 581 | break; | 576 | break; |
| 582 | } | 577 | } |
| 583 | 578 | ||
| 584 | - auto kids = a_node.getKey("/Kids"); | ||
| 585 | - int nkids = kids.isArray() ? static_cast<int>(kids.size()) : 0; | 579 | + Array kids = a_node.getKey("/Kids"); |
| 580 | + int nkids = static_cast<int>(kids.size()); | ||
| 586 | if (nkids > 0) { | 581 | if (nkids > 0) { |
| 587 | int kid_number = first ? 0 : nkids - 1; | 582 | int kid_number = first ? 0 : nkids - 1; |
| 588 | addPathElement(a_node, kid_number); | 583 | addPathElement(a_node, kid_number); |
| 589 | auto next = kids[kid_number]; | 584 | auto next = kids[kid_number]; |
| 590 | - if (!next.isIndirect()) { | 585 | + if (!next) { |
| 586 | + return fail(a_node, "kid number " + std::to_string(kid_number) + " is invalid"); | ||
| 587 | + } | ||
| 588 | + if (!next.indirect()) { | ||
| 591 | if (impl.auto_repair) { | 589 | if (impl.auto_repair) { |
| 592 | impl.warn( | 590 | impl.warn( |
| 593 | a_node, | 591 | a_node, |
| 594 | "converting kid number " + std::to_string(kid_number) + | 592 | "converting kid number " + std::to_string(kid_number) + |
| 595 | " to an indirect object"); | 593 | " to an indirect object"); |
| 596 | next = impl.qpdf.makeIndirectObject(next); | 594 | next = impl.qpdf.makeIndirectObject(next); |
| 597 | - kids.setArrayItem(kid_number, next); | 595 | + kids.set(kid_number, next); |
| 598 | } else { | 596 | } else { |
| 599 | impl.warn( | 597 | impl.warn( |
| 600 | a_node, | 598 | a_node, |
| @@ -602,7 +600,7 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | @@ -602,7 +600,7 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | ||
| 602 | } | 600 | } |
| 603 | } | 601 | } |
| 604 | a_node = next; | 602 | a_node = next; |
| 605 | - } else if (allow_empty && items.isArray()) { | 603 | + } else if (allow_empty && items) { |
| 606 | setItemNumber(a_node, -1); | 604 | setItemNumber(a_node, -1); |
| 607 | break; | 605 | break; |
| 608 | } else { | 606 | } else { |
| @@ -655,8 +653,8 @@ NNTreeImpl::last() | @@ -655,8 +653,8 @@ NNTreeImpl::last() | ||
| 655 | int | 653 | int |
| 656 | NNTreeImpl::withinLimits(QPDFObjectHandle const& key, QPDFObjectHandle const& node) | 654 | NNTreeImpl::withinLimits(QPDFObjectHandle const& key, QPDFObjectHandle const& node) |
| 657 | { | 655 | { |
| 658 | - auto limits = node.getKey("/Limits"); | ||
| 659 | - if (!(limits.size() >= 2 && details.keyValid(limits[0]) && details.keyValid(limits[1]))) { | 656 | + Array limits = node.getKey("/Limits"); |
| 657 | + if (!(details.keyValid(limits[0]) && details.keyValid(limits[1]))) { | ||
| 660 | error(node, "node is missing /Limits"); | 658 | error(node, "node is missing /Limits"); |
| 661 | } | 659 | } |
| 662 | if (details.compareKeys(key, limits[0]) < 0) { | 660 | if (details.compareKeys(key, limits[0]) < 0) { |
| @@ -734,7 +732,7 @@ void | @@ -734,7 +732,7 @@ void | ||
| 734 | NNTreeImpl::repair() | 732 | NNTreeImpl::repair() |
| 735 | { | 733 | { |
| 736 | auto new_node = QPDFObjectHandle::newDictionary(); | 734 | auto new_node = QPDFObjectHandle::newDictionary(); |
| 737 | - new_node.replaceKey(details.itemsKey(), QPDFObjectHandle::newArray()); | 735 | + new_node.replaceKey(details.itemsKey(), Array()); |
| 738 | NNTreeImpl repl(details, qpdf, new_node, false); | 736 | NNTreeImpl repl(details, qpdf, new_node, false); |
| 739 | for (auto const& i: *this) { | 737 | for (auto const& i: *this) { |
| 740 | repl.insert(i.first, i.second); | 738 | repl.insert(i.first, i.second); |
| @@ -750,7 +748,6 @@ NNTreeImpl::find(QPDFObjectHandle key, bool return_prev_if_not_found) | @@ -750,7 +748,6 @@ NNTreeImpl::find(QPDFObjectHandle key, bool return_prev_if_not_found) | ||
| 750 | return findInternal(key, return_prev_if_not_found); | 748 | return findInternal(key, return_prev_if_not_found); |
| 751 | } catch (QPDFExc& e) { | 749 | } catch (QPDFExc& e) { |
| 752 | if (auto_repair) { | 750 | if (auto_repair) { |
| 753 | - QTC::TC("qpdf", "NNTree repair"); | ||
| 754 | warn(oh, std::string("attempting to repair after error: ") + e.what()); | 751 | warn(oh, std::string("attempting to repair after error: ") + e.what()); |
| 755 | repair(); | 752 | repair(); |
| 756 | return findInternal(key, return_prev_if_not_found); | 753 | return findInternal(key, return_prev_if_not_found); |
| @@ -784,7 +781,7 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo | @@ -784,7 +781,7 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo | ||
| 784 | error(node, "loop detected in find"); | 781 | error(node, "loop detected in find"); |
| 785 | } | 782 | } |
| 786 | 783 | ||
| 787 | - auto items = node.getKey(details.itemsKey()); | 784 | + Array items = node.getKey(details.itemsKey()); |
| 788 | size_t nitems = items.size(); | 785 | size_t nitems = items.size(); |
| 789 | if (nitems > 1) { | 786 | if (nitems > 1) { |
| 790 | int idx = binarySearch( | 787 | int idx = binarySearch( |
| @@ -795,8 +792,8 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo | @@ -795,8 +792,8 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo | ||
| 795 | return result; | 792 | return result; |
| 796 | } | 793 | } |
| 797 | 794 | ||
| 798 | - auto kids = node.getKey("/Kids"); | ||
| 799 | - size_t nkids = kids.isArray() ? kids.size() : 0; | 795 | + Array kids = node.getKey("/Kids"); |
| 796 | + size_t nkids = kids.size(); | ||
| 800 | if (nkids > 0) { | 797 | if (nkids > 0) { |
| 801 | int idx = binarySearch(key, kids, nkids, true, &NNTreeImpl::compareKeyKid); | 798 | int idx = binarySearch(key, kids, nkids, true, &NNTreeImpl::compareKeyKid); |
| 802 | if (idx == -1) { | 799 | if (idx == -1) { |
| @@ -814,15 +811,15 @@ NNTreeImpl::iterator | @@ -814,15 +811,15 @@ NNTreeImpl::iterator | ||
| 814 | NNTreeImpl::insertFirst(QPDFObjectHandle const& key, QPDFObjectHandle const& value) | 811 | NNTreeImpl::insertFirst(QPDFObjectHandle const& key, QPDFObjectHandle const& value) |
| 815 | { | 812 | { |
| 816 | auto iter = begin(); | 813 | auto iter = begin(); |
| 817 | - QPDFObjectHandle items; | 814 | + Array items(nullptr); |
| 818 | if (iter.node.isDictionary()) { | 815 | if (iter.node.isDictionary()) { |
| 819 | items = iter.node.getKey(details.itemsKey()); | 816 | items = iter.node.getKey(details.itemsKey()); |
| 820 | } | 817 | } |
| 821 | - if (!items.isArray()) { | 818 | + if (!items) { |
| 822 | error(oh, "unable to find a valid items node"); | 819 | error(oh, "unable to find a valid items node"); |
| 823 | } | 820 | } |
| 824 | - items.insertItem(0, key); | ||
| 825 | - items.insertItem(1, value); | 821 | + items.insert(0, key); |
| 822 | + items.insert(1, value); | ||
| 826 | iter.setItemNumber(iter.node, 0); | 823 | iter.setItemNumber(iter.node, 0); |
| 827 | iter.resetLimits(iter.node, iter.lastPathElement()); | 824 | iter.resetLimits(iter.node, iter.lastPathElement()); |
| 828 | iter.split(iter.node, iter.lastPathElement()); | 825 | iter.split(iter.node, iter.lastPathElement()); |
| @@ -836,8 +833,8 @@ NNTreeImpl::insert(QPDFObjectHandle const& key, QPDFObjectHandle const& value) | @@ -836,8 +833,8 @@ NNTreeImpl::insert(QPDFObjectHandle const& key, QPDFObjectHandle const& value) | ||
| 836 | if (!iter.valid()) { | 833 | if (!iter.valid()) { |
| 837 | return insertFirst(key, value); | 834 | return insertFirst(key, value); |
| 838 | } else if (details.compareKeys(key, iter->first) == 0) { | 835 | } else if (details.compareKeys(key, iter->first) == 0) { |
| 839 | - auto items = iter.node.getKey(details.itemsKey()); | ||
| 840 | - items.setArrayItem(iter.item_number + 1, value); | 836 | + Array items = iter.node.getKey(details.itemsKey()); |
| 837 | + items.set(iter.item_number + 1, value); | ||
| 841 | iter.updateIValue(); | 838 | iter.updateIValue(); |
| 842 | } else { | 839 | } else { |
| 843 | iter.insertAfter(key, value); | 840 | iter.insertAfter(key, value); |
qpdf/qpdf.testcov
| @@ -513,8 +513,6 @@ qpdf-c called qpdf_oh_unparse_resolved 0 | @@ -513,8 +513,6 @@ qpdf-c called qpdf_oh_unparse_resolved 0 | ||
| 513 | qpdf-c called qpdf_oh_unparse_binary 0 | 513 | qpdf-c called qpdf_oh_unparse_binary 0 |
| 514 | QPDFWriter getFilterOnWrite false 0 | 514 | QPDFWriter getFilterOnWrite false 0 |
| 515 | QPDFPageObjectHelper::forEachXObject 3 | 515 | QPDFPageObjectHelper::forEachXObject 3 |
| 516 | -NNTree repair 0 | ||
| 517 | -NNTree insertAfter inserts first 0 | ||
| 518 | NNTree erased last kid/item in tree 1 | 516 | NNTree erased last kid/item in tree 1 |
| 519 | QPDFPageObjectHelper unresolved names 0 | 517 | QPDFPageObjectHelper unresolved names 0 |
| 520 | QPDFPageObjectHelper resolving unresolved 0 | 518 | QPDFPageObjectHelper resolving unresolved 0 |