Commit d4a563647ff62e5a01a32ea758de9cadf5a6ca0d

Authored by m-holger
1 parent 32e0bbe4

Refactor `NNTree::deepen`: replace `getKey` with subscript operator for `Array` …

…access, and streamline logic.
libqpdf/NNTree.cc
... ... @@ -382,7 +382,7 @@ NNTreeIterator::remove()
382 382 if (!valid()) {
383 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 386 int nitems = static_cast<int>(items.size());
387 387 if (std::cmp_greater(item_number + 2, nitems)) {
388 388 impl.error(node, "found short items array while removing an item");
... ... @@ -429,7 +429,7 @@ NNTreeIterator::remove()
429 429 auto element = lastPathElement();
430 430 auto parent = element;
431 431 --parent;
432   - Array kids = element->node.getKey("/Kids");
  432 + Array kids = element->node["/Kids"];
433 433 kids.erase(element->kid_number);
434 434 auto nkids = kids.size();
435 435 if (nkids > 0) {
... ... @@ -489,14 +489,14 @@ NNTreeIterator::operator==(NNTreeIterator const&amp; other) const
489 489 }
490 490  
491 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 494 // Starting at this node, descend through the first or last kid until we reach a node with
495 495 // items. If we succeed, return true; otherwise return false and leave path alone.
496 496  
497 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 500 impl.warn(failed_node, msg);
501 501 path = opath;
502 502 return false;
... ... @@ -511,51 +511,52 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty)
511 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 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 519 int nitems = static_cast<int>(items.size());
520 520 if (nitems > 1) {
521 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 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 532 return fail(
554 533 a_node,
555 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 562 NNTreeImpl::iterator
... ...
libqpdf/qpdf/NNTree.hh
... ... @@ -92,7 +92,7 @@ class NNTreeIterator final
92 92 {
93 93 }
94 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 96 void
97 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 33 B
34 34 W
35 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 37 /Bad4 -- invalid kid
38 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 39 WARNING: name-tree.pdf (Name/Number tree node (object 23)): skipping over invalid kid at index 1
... ...