Commit d4a563647ff62e5a01a32ea758de9cadf5a6ca0d
1 parent
32e0bbe4
Refactor `NNTree::deepen`: replace `getKey` with subscript operator for `Array` …
…access, and streamline logic.
Showing
3 changed files
with
37 additions
and
36 deletions
libqpdf/NNTree.cc
| @@ -382,7 +382,7 @@ NNTreeIterator::remove() | @@ -382,7 +382,7 @@ NNTreeIterator::remove() | ||
| 382 | if (!valid()) { | 382 | if (!valid()) { |
| 383 | throw std::logic_error("attempt made to remove an invalid iterator"); | 383 | throw std::logic_error("attempt made to remove an invalid iterator"); |
| 384 | } | 384 | } |
| 385 | - Array items = node.getKey(impl.itemsKey()); | 385 | + Array items = node[impl.itemsKey()]; |
| 386 | int nitems = static_cast<int>(items.size()); | 386 | int nitems = static_cast<int>(items.size()); |
| 387 | if (std::cmp_greater(item_number + 2, nitems)) { | 387 | if (std::cmp_greater(item_number + 2, nitems)) { |
| 388 | impl.error(node, "found short items array while removing an item"); | 388 | impl.error(node, "found short items array while removing an item"); |
| @@ -429,7 +429,7 @@ NNTreeIterator::remove() | @@ -429,7 +429,7 @@ NNTreeIterator::remove() | ||
| 429 | auto element = lastPathElement(); | 429 | auto element = lastPathElement(); |
| 430 | auto parent = element; | 430 | auto parent = element; |
| 431 | --parent; | 431 | --parent; |
| 432 | - Array kids = element->node.getKey("/Kids"); | 432 | + Array kids = element->node["/Kids"]; |
| 433 | kids.erase(element->kid_number); | 433 | kids.erase(element->kid_number); |
| 434 | auto nkids = kids.size(); | 434 | auto nkids = kids.size(); |
| 435 | if (nkids > 0) { | 435 | if (nkids > 0) { |
| @@ -489,14 +489,14 @@ NNTreeIterator::operator==(NNTreeIterator const& other) const | @@ -489,14 +489,14 @@ NNTreeIterator::operator==(NNTreeIterator const& other) const | ||
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | bool | 491 | bool |
| 492 | -NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | 492 | +NNTreeIterator::deepen(Dictionary a_node, bool first, bool allow_empty) |
| 493 | { | 493 | { |
| 494 | // Starting at this node, descend through the first or last kid until we reach a node with | 494 | // Starting at this node, descend through the first or last kid until we reach a node with |
| 495 | // items. If we succeed, return true; otherwise return false and leave path alone. | 495 | // items. If we succeed, return true; otherwise return false and leave path alone. |
| 496 | 496 | ||
| 497 | auto opath = path; | 497 | auto opath = path; |
| 498 | 498 | ||
| 499 | - auto fail = [this, &opath](QPDFObjectHandle const& failed_node, std::string const& msg) { | 499 | + auto fail = [this, &opath](Dictionary const& failed_node, std::string const& msg) { |
| 500 | impl.warn(failed_node, msg); | 500 | impl.warn(failed_node, msg); |
| 501 | path = opath; | 501 | path = opath; |
| 502 | return false; | 502 | return false; |
| @@ -511,51 +511,52 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | @@ -511,51 +511,52 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) | ||
| 511 | return fail(a_node, "loop detected while traversing name/number tree"); | 511 | return fail(a_node, "loop detected while traversing name/number tree"); |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | - if (!a_node.isDictionary()) { | 514 | + if (!a_node) { |
| 515 | return fail(a_node, "non-dictionary node while traversing name/number tree"); | 515 | return fail(a_node, "non-dictionary node while traversing name/number tree"); |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | - Array items = a_node.getKey(impl.itemsKey()); | 518 | + Array items = a_node[impl.itemsKey()]; |
| 519 | int nitems = static_cast<int>(items.size()); | 519 | int nitems = static_cast<int>(items.size()); |
| 520 | if (nitems > 1) { | 520 | if (nitems > 1) { |
| 521 | setItemNumber(a_node, first ? 0 : nitems - 2); | 521 | setItemNumber(a_node, first ? 0 : nitems - 2); |
| 522 | - break; | 522 | + return true; |
| 523 | } | 523 | } |
| 524 | 524 | ||
| 525 | - Array kids = a_node.getKey("/Kids"); | 525 | + Array kids = a_node["/Kids"]; |
| 526 | int nkids = static_cast<int>(kids.size()); | 526 | int nkids = static_cast<int>(kids.size()); |
| 527 | - if (nkids > 0) { | ||
| 528 | - int kid_number = first ? 0 : nkids - 1; | ||
| 529 | - addPathElement(a_node, kid_number); | ||
| 530 | - auto next = kids[kid_number]; | ||
| 531 | - if (!next) { | ||
| 532 | - return fail(a_node, "kid number " + std::to_string(kid_number) + " is invalid"); | 527 | + if (nkids == 0) { |
| 528 | + if (allow_empty && items) { | ||
| 529 | + setItemNumber(a_node, -1); | ||
| 530 | + return true; | ||
| 533 | } | 531 | } |
| 534 | - if (!next.indirect()) { | ||
| 535 | - if (impl.auto_repair) { | ||
| 536 | - impl.warn( | ||
| 537 | - a_node, | ||
| 538 | - "converting kid number " + std::to_string(kid_number) + | ||
| 539 | - " to an indirect object"); | ||
| 540 | - next = impl.qpdf.makeIndirectObject(next); | ||
| 541 | - kids.set(kid_number, next); | ||
| 542 | - } else { | ||
| 543 | - impl.warn( | ||
| 544 | - a_node, | ||
| 545 | - "kid number " + std::to_string(kid_number) + " is not an indirect object"); | ||
| 546 | - } | ||
| 547 | - } | ||
| 548 | - a_node = next; | ||
| 549 | - } else if (allow_empty && items) { | ||
| 550 | - setItemNumber(a_node, -1); | ||
| 551 | - break; | ||
| 552 | - } else { | ||
| 553 | return fail( | 532 | return fail( |
| 554 | a_node, | 533 | a_node, |
| 555 | "name/number tree node has neither non-empty " + impl.itemsKey() + " nor /Kids"); | 534 | "name/number tree node has neither non-empty " + impl.itemsKey() + " nor /Kids"); |
| 556 | } | 535 | } |
| 536 | + | ||
| 537 | + int kid_number = first ? 0 : nkids - 1; | ||
| 538 | + addPathElement(a_node, kid_number); | ||
| 539 | + Dictionary next = kids[kid_number]; | ||
| 540 | + if (!next) { | ||
| 541 | + return fail(a_node, "kid number " + std::to_string(kid_number) + " is invalid"); | ||
| 542 | + } | ||
| 543 | + if (!next.indirect()) { | ||
| 544 | + if (impl.auto_repair) { | ||
| 545 | + impl.warn( | ||
| 546 | + a_node, | ||
| 547 | + "converting kid number " + std::to_string(kid_number) + | ||
| 548 | + " to an indirect object"); | ||
| 549 | + next = impl.qpdf.makeIndirectObject(next); | ||
| 550 | + kids.set(kid_number, next); | ||
| 551 | + } else { | ||
| 552 | + impl.warn( | ||
| 553 | + a_node, | ||
| 554 | + "kid number " + std::to_string(kid_number) + " is not an indirect object"); | ||
| 555 | + } | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + a_node = next; | ||
| 557 | } | 559 | } |
| 558 | - return true; | ||
| 559 | } | 560 | } |
| 560 | 561 | ||
| 561 | NNTreeImpl::iterator | 562 | NNTreeImpl::iterator |
libqpdf/qpdf/NNTree.hh
| @@ -92,7 +92,7 @@ class NNTreeIterator final | @@ -92,7 +92,7 @@ class NNTreeIterator final | ||
| 92 | { | 92 | { |
| 93 | } | 93 | } |
| 94 | void updateIValue(bool allow_invalid = true); | 94 | void updateIValue(bool allow_invalid = true); |
| 95 | - bool deepen(QPDFObjectHandle node, bool first, bool allow_empty); | 95 | + bool deepen(qpdf::Dictionary node, bool first, bool allow_empty); |
| 96 | void | 96 | void |
| 97 | setItemNumber(QPDFObjectHandle const& a_node, int n) | 97 | setItemNumber(QPDFObjectHandle const& a_node, int n) |
| 98 | { | 98 | { |
qpdf/qtest/qpdf/name-tree.out
| @@ -33,7 +33,7 @@ WARNING: name-tree.pdf (Name/Number tree node (object 17)): skipping over invali | @@ -33,7 +33,7 @@ WARNING: name-tree.pdf (Name/Number tree node (object 17)): skipping over invali | ||
| 33 | B | 33 | B |
| 34 | W | 34 | W |
| 35 | /Bad3 -- invalid kid | 35 | /Bad3 -- invalid kid |
| 36 | -WARNING: name-tree.pdf (Name/Number tree node (object 25)): non-dictionary node while traversing name/number tree | 36 | +WARNING: name-tree.pdf (Name/Number tree node (object 22)): kid number 0 is invalid |
| 37 | /Bad4 -- invalid kid | 37 | /Bad4 -- invalid kid |
| 38 | WARNING: name-tree.pdf (Name/Number tree node (object 23)): attempting to repair after error: name-tree.pdf (Name/Number tree node (object 23)): invalid kid at index 1 | 38 | WARNING: name-tree.pdf (Name/Number tree node (object 23)): attempting to repair after error: name-tree.pdf (Name/Number tree node (object 23)): invalid kid at index 1 |
| 39 | WARNING: name-tree.pdf (Name/Number tree node (object 23)): skipping over invalid kid at index 1 | 39 | WARNING: name-tree.pdf (Name/Number tree node (object 23)): skipping over invalid kid at index 1 |