Commit f110a23c48d74157b999715bf451118c920fa169
1 parent
0d8b0882
Refactor `NNTree::remove`: simplify logic, replace `getArrayItem` and `getArrayN…
…Items` with subscript operators, introduce `std::cmp` utilities, and remove redundant debug traces.
Showing
2 changed files
with
18 additions
and
41 deletions
libqpdf/NNTree.cc
| @@ -422,8 +422,8 @@ NNTreeIterator::remove() | @@ -422,8 +422,8 @@ NNTreeIterator::remove() | ||
| 422 | throw std::logic_error("attempt made to remove an invalid iterator"); | 422 | throw std::logic_error("attempt made to remove an invalid iterator"); |
| 423 | } | 423 | } |
| 424 | auto items = node.getKey(impl.details.itemsKey()); | 424 | auto items = node.getKey(impl.details.itemsKey()); |
| 425 | - int nitems = items.getArrayNItems(); | ||
| 426 | - if (item_number + 2 > nitems) { | 425 | + int nitems = static_cast<int>(items.size()); |
| 426 | + if (std::cmp_greater(item_number + 2, nitems)) { | ||
| 427 | impl.error(node, "found short items array while removing an item"); | 427 | impl.error(node, "found short items array while removing an item"); |
| 428 | } | 428 | } |
| 429 | 429 | ||
| @@ -437,20 +437,17 @@ NNTreeIterator::remove() | @@ -437,20 +437,17 @@ NNTreeIterator::remove() | ||
| 437 | if (item_number == 0 || item_number == nitems) { | 437 | if (item_number == 0 || item_number == nitems) { |
| 438 | // We removed either the first or last item of an items array that remains non-empty, so | 438 | // We removed either the first or last item of an items array that remains non-empty, so |
| 439 | // we have to adjust limits. | 439 | // we have to adjust limits. |
| 440 | - QTC::TC("qpdf", "NNTree remove reset limits"); | ||
| 441 | resetLimits(node, lastPathElement()); | 440 | resetLimits(node, lastPathElement()); |
| 442 | } | 441 | } |
| 443 | 442 | ||
| 444 | if (item_number == nitems) { | 443 | if (item_number == nitems) { |
| 445 | // We removed the last item of a non-empty items array, so advance to the successor of | 444 | // We removed the last item of a non-empty items array, so advance to the successor of |
| 446 | // the previous item. | 445 | // the previous item. |
| 447 | - QTC::TC("qpdf", "NNTree erased last item"); | ||
| 448 | item_number -= 2; | 446 | item_number -= 2; |
| 449 | increment(false); | 447 | increment(false); |
| 450 | } else if (item_number < nitems) { | 448 | } else if (item_number < nitems) { |
| 451 | // We don't have to do anything since the removed item's successor now occupies its | 449 | // We don't have to do anything since the removed item's successor now occupies its |
| 452 | // former location. | 450 | // former location. |
| 453 | - QTC::TC("qpdf", "NNTree erased non-last item"); | ||
| 454 | updateIValue(); | 451 | updateIValue(); |
| 455 | } else { | 452 | } else { |
| 456 | // We already checked to ensure this condition would not happen. | 453 | // We already checked to ensure this condition would not happen. |
| @@ -461,61 +458,51 @@ NNTreeIterator::remove() | @@ -461,61 +458,51 @@ NNTreeIterator::remove() | ||
| 461 | 458 | ||
| 462 | if (path.empty()) { | 459 | if (path.empty()) { |
| 463 | // Special case: if this is the root node, we can leave it empty. | 460 | // Special case: if this is the root node, we can leave it empty. |
| 464 | - QTC::TC("qpdf", "NNTree erased all items on leaf/root"); | ||
| 465 | setItemNumber(impl.oh, -1); | 461 | setItemNumber(impl.oh, -1); |
| 466 | return; | 462 | return; |
| 467 | } | 463 | } |
| 468 | 464 | ||
| 469 | - QTC::TC("qpdf", "NNTree items is empty after remove"); | ||
| 470 | - | ||
| 471 | // We removed the last item from this items array, so we need to remove this node from the | 465 | // We removed the last item from this items array, so we need to remove this node from the |
| 472 | // parent on up the tree. Then we need to position ourselves at the removed item's successor. | 466 | // parent on up the tree. Then we need to position ourselves at the removed item's successor. |
| 473 | - bool done = false; | ||
| 474 | - while (!done) { | 467 | + while (true) { |
| 475 | auto element = lastPathElement(); | 468 | auto element = lastPathElement(); |
| 476 | auto parent = element; | 469 | auto parent = element; |
| 477 | --parent; | 470 | --parent; |
| 478 | auto kids = element->node.getKey("/Kids"); | 471 | auto kids = element->node.getKey("/Kids"); |
| 479 | kids.eraseItem(element->kid_number); | 472 | kids.eraseItem(element->kid_number); |
| 480 | - auto nkids = kids.getArrayNItems(); | 473 | + auto nkids = kids.size(); |
| 481 | if (nkids > 0) { | 474 | if (nkids > 0) { |
| 482 | // The logic here is similar to the items case. | 475 | // The logic here is similar to the items case. |
| 483 | - if ((element->kid_number == 0) || (element->kid_number == nkids)) { | ||
| 484 | - QTC::TC("qpdf", "NNTree erased first or last kid"); | 476 | + if (element->kid_number == 0 || std::cmp_equal(element->kid_number, nkids)) { |
| 485 | resetLimits(element->node, parent); | 477 | resetLimits(element->node, parent); |
| 486 | } | 478 | } |
| 487 | - if (element->kid_number == nkids) { | 479 | + if (std::cmp_equal(element->kid_number, nkids)) { |
| 488 | // Move to the successor of the last child of the previous kid. | 480 | // Move to the successor of the last child of the previous kid. |
| 489 | - setItemNumber(QPDFObjectHandle(), -1); | 481 | + setItemNumber({}, -1); |
| 490 | --element->kid_number; | 482 | --element->kid_number; |
| 491 | - deepen(kids.getArrayItem(element->kid_number), false, true); | 483 | + deepen(kids[element->kid_number], false, true); |
| 492 | if (valid()) { | 484 | if (valid()) { |
| 493 | increment(false); | 485 | increment(false); |
| 494 | - if (!valid()) { | ||
| 495 | - QTC::TC("qpdf", "NNTree erased last item in tree"); | ||
| 496 | - } else { | ||
| 497 | - QTC::TC("qpdf", "NNTree erased last kid"); | ||
| 498 | - } | 486 | + QTC::TC("qpdf", "NNTree erased last kid/item in tree", valid() ? 0 : 1); |
| 499 | } | 487 | } |
| 500 | } else { | 488 | } else { |
| 501 | // Next kid is in deleted kid's position | 489 | // Next kid is in deleted kid's position |
| 502 | - QTC::TC("qpdf", "NNTree erased non-last kid"); | ||
| 503 | deepen(kids.getArrayItem(element->kid_number), true, true); | 490 | deepen(kids.getArrayItem(element->kid_number), true, true); |
| 504 | } | 491 | } |
| 505 | - done = true; | ||
| 506 | - } else if (parent == path.end()) { | 492 | + return; |
| 493 | + } | ||
| 494 | + | ||
| 495 | + if (parent == path.end()) { | ||
| 507 | // We erased the very last item. Convert the root to an empty items array. | 496 | // We erased the very last item. Convert the root to an empty items array. |
| 508 | - QTC::TC("qpdf", "NNTree non-flat tree is empty after remove"); | ||
| 509 | element->node.removeKey("/Kids"); | 497 | element->node.removeKey("/Kids"); |
| 510 | element->node.replaceKey(impl.details.itemsKey(), QPDFObjectHandle::newArray()); | 498 | element->node.replaceKey(impl.details.itemsKey(), QPDFObjectHandle::newArray()); |
| 511 | path.clear(); | 499 | path.clear(); |
| 512 | setItemNumber(impl.oh, -1); | 500 | setItemNumber(impl.oh, -1); |
| 513 | - done = true; | ||
| 514 | - } else { | ||
| 515 | - // Walk up the tree and continue | ||
| 516 | - QTC::TC("qpdf", "NNTree remove walking up tree"); | ||
| 517 | - path.pop_back(); | 501 | + return; |
| 518 | } | 502 | } |
| 503 | + | ||
| 504 | + // Walk up the tree and continue | ||
| 505 | + path.pop_back(); | ||
| 519 | } | 506 | } |
| 520 | } | 507 | } |
| 521 | 508 |
qpdf/qpdf.testcov
| @@ -534,17 +534,7 @@ NNTree split second half kid 0 | @@ -534,17 +534,7 @@ NNTree split second half kid 0 | ||
| 534 | NNTree limits didn't change 0 | 534 | NNTree limits didn't change 0 |
| 535 | NNTree increment end() 0 | 535 | NNTree increment end() 0 |
| 536 | NNTree insertAfter inserts first 0 | 536 | NNTree insertAfter inserts first 0 |
| 537 | -NNTree remove reset limits 0 | ||
| 538 | -NNTree erased last item 0 | ||
| 539 | -NNTree erased non-last item 0 | ||
| 540 | -NNTree items is empty after remove 0 | ||
| 541 | -NNTree erased all items on leaf/root 0 | ||
| 542 | -NNTree erased first or last kid 0 | ||
| 543 | -NNTree erased last kid 0 | ||
| 544 | -NNTree erased non-last kid 0 | ||
| 545 | -NNTree non-flat tree is empty after remove 0 | ||
| 546 | -NNTree remove walking up tree 0 | ||
| 547 | -NNTree erased last item in tree 0 | 537 | +NNTree erased last kid/item in tree 1 |
| 548 | NNTree remove limits from root 0 | 538 | NNTree remove limits from root 0 |
| 549 | QPDFPageObjectHelper unresolved names 0 | 539 | QPDFPageObjectHelper unresolved names 0 |
| 550 | QPDFPageObjectHelper resolving unresolved 0 | 540 | QPDFPageObjectHelper resolving unresolved 0 |