Commit 67796b3ff0c3503a78d45646568c7fae4f545d22
1 parent
5e7b37e1
Refactor `NNTree` implementation to simplify key validation logic
- Removed `NNTreeDetails` and moved key validation logic directly into `NNTreeImpl`. - Replaced type determination with `qpdf_object_type_e` for improved clarity. - Updated `QPDFNameTreeObjectHelper` and `QPDFNumberTreeObjectHelper` to align with the new `NNTreeImpl` structure. - Simplified methods accessing tree items and validating keys.
Showing
4 changed files
with
71 additions
and
114 deletions
libqpdf/NNTree.cc
| ... | ... | @@ -68,7 +68,7 @@ NNTreeIterator::updateIValue(bool allow_invalid) |
| 68 | 68 | ivalue.second = QPDFObjectHandle(); |
| 69 | 69 | return; |
| 70 | 70 | } |
| 71 | - Array items = node.getKey(impl.details.itemsKey()); | |
| 71 | + Array items = node.getKey(impl.itemsKey()); | |
| 72 | 72 | if (!std::cmp_less(item_number + 1, items.size())) { |
| 73 | 73 | impl.error(node, "update ivalue: items array is too short"); |
| 74 | 74 | } |
| ... | ... | @@ -91,7 +91,7 @@ NNTreeIterator::getNextKid(PathElement& pe, bool backward) |
| 91 | 91 | if (pe.kid_number >= 0 && std::cmp_less(pe.kid_number, kids.size())) { |
| 92 | 92 | auto result = kids[pe.kid_number]; |
| 93 | 93 | if (result.isDictionary() && |
| 94 | - (result.hasKey("/Kids") || result.hasKey(impl.details.itemsKey()))) { | |
| 94 | + (result.hasKey("/Kids") || result.hasKey(impl.itemsKey()))) { | |
| 95 | 95 | return result; |
| 96 | 96 | } else { |
| 97 | 97 | impl.warn( |
| ... | ... | @@ -121,7 +121,7 @@ NNTreeIterator::increment(bool backward) |
| 121 | 121 | |
| 122 | 122 | while (valid()) { |
| 123 | 123 | item_number += backward ? -2 : 2; |
| 124 | - Array items = node.getKey(impl.details.itemsKey()); | |
| 124 | + Array items = node.getKey(impl.itemsKey()); | |
| 125 | 125 | if (item_number < 0 || std::cmp_greater_equal(item_number, items.size())) { |
| 126 | 126 | bool found = false; |
| 127 | 127 | setItemNumber(QPDFObjectHandle(), -1); |
| ... | ... | @@ -136,10 +136,10 @@ NNTreeIterator::increment(bool backward) |
| 136 | 136 | } |
| 137 | 137 | } |
| 138 | 138 | if (item_number >= 0) { |
| 139 | - items = node.getKey(impl.details.itemsKey()); | |
| 139 | + items = node.getKey(impl.itemsKey()); | |
| 140 | 140 | if (std::cmp_greater_equal(item_number + 1, items.size())) { |
| 141 | 141 | impl.warn(node, "items array doesn't have enough elements"); |
| 142 | - } else if (!impl.details.keyValid(items[item_number])) { | |
| 142 | + } else if (!impl.keyValid(items[item_number])) { | |
| 143 | 143 | impl.warn(node, ("item " + std::to_string(item_number) + " has the wrong type")); |
| 144 | 144 | } else if (!impl.value_valid(items[item_number + 1])) { |
| 145 | 145 | impl.warn(node, "item " + std::to_string(item_number + 1) + " is invalid"); |
| ... | ... | @@ -160,7 +160,7 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite |
| 160 | 160 | } |
| 161 | 161 | Array kids = a_node.getKey("/Kids"); |
| 162 | 162 | size_t nkids = kids.size(); |
| 163 | - Array items = a_node.getKey(impl.details.itemsKey()); | |
| 163 | + Array items = a_node.getKey(impl.itemsKey()); | |
| 164 | 164 | size_t nitems = items.size(); |
| 165 | 165 | |
| 166 | 166 | bool changed = true; |
| ... | ... | @@ -187,9 +187,8 @@ NNTreeIterator::resetLimits(QPDFObjectHandle a_node, std::list<PathElement>::ite |
| 187 | 187 | if (olimits.size() == 2) { |
| 188 | 188 | auto ofirst = olimits[0]; |
| 189 | 189 | auto olast = olimits[1]; |
| 190 | - if (impl.details.keyValid(ofirst) && impl.details.keyValid(olast) && | |
| 191 | - impl.details.compareKeys(first, ofirst) == 0 && | |
| 192 | - impl.details.compareKeys(last, olast) == 0) { | |
| 190 | + if (impl.keyValid(ofirst) && impl.keyValid(olast) && | |
| 191 | + impl.compareKeys(first, ofirst) == 0 && impl.compareKeys(last, olast) == 0) { | |
| 193 | 192 | changed = false; |
| 194 | 193 | } |
| 195 | 194 | } |
| ... | ... | @@ -246,7 +245,7 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato |
| 246 | 245 | // Find the array we actually need to split, which is either this node's kids or items. |
| 247 | 246 | Array kids = to_split.getKey("/Kids"); |
| 248 | 247 | size_t nkids = kids.size(); |
| 249 | - Array items = to_split.getKey(impl.details.itemsKey()); | |
| 248 | + Array items = to_split.getKey(impl.itemsKey()); | |
| 250 | 249 | size_t nitems = items.size(); |
| 251 | 250 | |
| 252 | 251 | Array first_half; |
| ... | ... | @@ -261,7 +260,7 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato |
| 261 | 260 | first_half = items; |
| 262 | 261 | n = nitems; |
| 263 | 262 | threshold *= 2; |
| 264 | - key = impl.details.itemsKey(); | |
| 263 | + key = impl.itemsKey(); | |
| 265 | 264 | } else { |
| 266 | 265 | throw std::logic_error("NNTreeIterator::split called on invalid node"); |
| 267 | 266 | } |
| ... | ... | @@ -295,7 +294,7 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato |
| 295 | 294 | Array new_kids; |
| 296 | 295 | new_kids.push_back(first_node); |
| 297 | 296 | to_split.removeKey("/Limits"); // already shouldn't be there for root |
| 298 | - to_split.removeKey(impl.details.itemsKey()); | |
| 297 | + to_split.removeKey(impl.itemsKey()); | |
| 299 | 298 | to_split.replaceKey("/Kids", new_kids); |
| 300 | 299 | if (is_leaf) { |
| 301 | 300 | node = first_node; |
| ... | ... | @@ -375,7 +374,7 @@ NNTreeIterator::insertAfter(QPDFObjectHandle const& key, QPDFObjectHandle const& |
| 375 | 374 | return; |
| 376 | 375 | } |
| 377 | 376 | |
| 378 | - Array items = node.getKey(impl.details.itemsKey()); | |
| 377 | + Array items = node.getKey(impl.itemsKey()); | |
| 379 | 378 | if (!items) { |
| 380 | 379 | impl.error(node, "node contains no items array"); |
| 381 | 380 | } |
| ... | ... | @@ -404,7 +403,7 @@ NNTreeIterator::remove() |
| 404 | 403 | if (!valid()) { |
| 405 | 404 | throw std::logic_error("attempt made to remove an invalid iterator"); |
| 406 | 405 | } |
| 407 | - Array items = node.getKey(impl.details.itemsKey()); | |
| 406 | + Array items = node.getKey(impl.itemsKey()); | |
| 408 | 407 | int nitems = static_cast<int>(items.size()); |
| 409 | 408 | if (std::cmp_greater(item_number + 2, nitems)) { |
| 410 | 409 | impl.error(node, "found short items array while removing an item"); |
| ... | ... | @@ -478,7 +477,7 @@ NNTreeIterator::remove() |
| 478 | 477 | if (parent == path.end()) { |
| 479 | 478 | // We erased the very last item. Convert the root to an empty items array. |
| 480 | 479 | element->node.removeKey("/Kids"); |
| 481 | - element->node.replaceKey(impl.details.itemsKey(), Array()); | |
| 480 | + element->node.replaceKey(impl.itemsKey(), Array()); | |
| 482 | 481 | path.clear(); |
| 483 | 482 | setItemNumber(impl.oh, -1); |
| 484 | 483 | return; |
| ... | ... | @@ -579,7 +578,7 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) |
| 579 | 578 | return fail(a_node, "non-dictionary node while traversing name/number tree"); |
| 580 | 579 | } |
| 581 | 580 | |
| 582 | - Array items = a_node.getKey(impl.details.itemsKey()); | |
| 581 | + Array items = a_node.getKey(impl.itemsKey()); | |
| 583 | 582 | int nitems = static_cast<int>(items.size()); |
| 584 | 583 | if (nitems > 1) { |
| 585 | 584 | setItemNumber(a_node, first ? 0 : nitems - 2); |
| ... | ... | @@ -616,22 +615,22 @@ NNTreeIterator::deepen(QPDFObjectHandle a_node, bool first, bool allow_empty) |
| 616 | 615 | } else { |
| 617 | 616 | return fail( |
| 618 | 617 | a_node, |
| 619 | - "name/number tree node has neither non-empty " + impl.details.itemsKey() + | |
| 620 | - " nor /Kids"); | |
| 618 | + "name/number tree node has neither non-empty " + impl.itemsKey() + " nor /Kids"); | |
| 621 | 619 | } |
| 622 | 620 | } |
| 623 | 621 | return true; |
| 624 | 622 | } |
| 625 | 623 | |
| 626 | 624 | NNTreeImpl::NNTreeImpl( |
| 627 | - NNTreeDetails const& details, | |
| 628 | 625 | QPDF& qpdf, |
| 629 | 626 | QPDFObjectHandle& oh, |
| 627 | + qpdf_object_type_e key_type, | |
| 630 | 628 | std::function<bool(QPDFObjectHandle const&)> value_validator, |
| 631 | 629 | bool auto_repair) : |
| 632 | - details(details), | |
| 633 | 630 | qpdf(qpdf), |
| 634 | 631 | oh(oh), |
| 632 | + key_type(key_type), | |
| 633 | + items_key(key_type == ::ot_string ? "/Names" : "/Nums"), | |
| 635 | 634 | value_valid(value_validator), |
| 636 | 635 | auto_repair(auto_repair) |
| 637 | 636 | { |
| ... | ... | @@ -666,16 +665,32 @@ NNTreeImpl::last() |
| 666 | 665 | } |
| 667 | 666 | |
| 668 | 667 | int |
| 668 | +NNTreeImpl::compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const | |
| 669 | +{ | |
| 670 | + // We don't call this without calling keyValid first | |
| 671 | + qpdf_assert_debug(keyValid(a)); | |
| 672 | + qpdf_assert_debug(keyValid(b)); | |
| 673 | + if (key_type == ::ot_string) { | |
| 674 | + auto as = a.getUTF8Value(); | |
| 675 | + auto bs = b.getUTF8Value(); | |
| 676 | + return as < bs ? -1 : (as > bs ? 1 : 0); | |
| 677 | + } | |
| 678 | + auto as = a.getIntValue(); | |
| 679 | + auto bs = b.getIntValue(); | |
| 680 | + return as < bs ? -1 : (as > bs ? 1 : 0); | |
| 681 | +} | |
| 682 | + | |
| 683 | +int | |
| 669 | 684 | NNTreeImpl::withinLimits(QPDFObjectHandle const& key, QPDFObjectHandle const& node) |
| 670 | 685 | { |
| 671 | 686 | Array limits = node.getKey("/Limits"); |
| 672 | - if (!(details.keyValid(limits[0]) && details.keyValid(limits[1]))) { | |
| 687 | + if (!(keyValid(limits[0]) && keyValid(limits[1]))) { | |
| 673 | 688 | error(node, "node is missing /Limits"); |
| 674 | 689 | } |
| 675 | - if (details.compareKeys(key, limits[0]) < 0) { | |
| 690 | + if (compareKeys(key, limits[0]) < 0) { | |
| 676 | 691 | return -1; |
| 677 | 692 | } |
| 678 | - if (details.compareKeys(key, limits[1]) > 0) { | |
| 693 | + if (compareKeys(key, limits[1]) > 0) { | |
| 679 | 694 | return 1; |
| 680 | 695 | } |
| 681 | 696 | return 0; |
| ... | ... | @@ -728,10 +743,10 @@ NNTreeImpl::binarySearch( |
| 728 | 743 | int |
| 729 | 744 | NNTreeImpl::compareKeyItem(QPDFObjectHandle& key, QPDFObjectHandle& items, int idx) |
| 730 | 745 | { |
| 731 | - if (!(std::cmp_greater(items.size(), 2 * idx) && details.keyValid(items[2 * idx]))) { | |
| 746 | + if (!(std::cmp_greater(items.size(), 2 * idx) && keyValid(items[2 * idx]))) { | |
| 732 | 747 | error(oh, ("item at index " + std::to_string(2 * idx) + " is not the right type")); |
| 733 | 748 | } |
| 734 | - return details.compareKeys(key, items[2 * idx]); | |
| 749 | + return compareKeys(key, items[2 * idx]); | |
| 735 | 750 | } |
| 736 | 751 | |
| 737 | 752 | int |
| ... | ... | @@ -747,15 +762,15 @@ void |
| 747 | 762 | NNTreeImpl::repair() |
| 748 | 763 | { |
| 749 | 764 | auto new_node = QPDFObjectHandle::newDictionary(); |
| 750 | - new_node.replaceKey(details.itemsKey(), Array()); | |
| 751 | - NNTreeImpl repl(details, qpdf, new_node, value_valid, false); | |
| 765 | + new_node.replaceKey(itemsKey(), Array()); | |
| 766 | + NNTreeImpl repl(qpdf, new_node, key_type, value_valid, false); | |
| 752 | 767 | for (auto const& [key, value]: *this) { |
| 753 | 768 | if (key && value) { |
| 754 | 769 | repl.insert(key, value); |
| 755 | 770 | } |
| 756 | 771 | } |
| 757 | 772 | oh.replaceKey("/Kids", new_node.getKey("/Kids")); |
| 758 | - oh.replaceKey(details.itemsKey(), new_node.getKey(details.itemsKey())); | |
| 773 | + oh.replaceKey(itemsKey(), new_node.getKey(itemsKey())); | |
| 759 | 774 | } |
| 760 | 775 | |
| 761 | 776 | NNTreeImpl::iterator |
| ... | ... | @@ -783,13 +798,13 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo |
| 783 | 798 | return end(); |
| 784 | 799 | } |
| 785 | 800 | if (first_item.valid()) { |
| 786 | - if (!details.keyValid(first_item->first)) { | |
| 801 | + if (!keyValid(first_item->first)) { | |
| 787 | 802 | error(oh, "encountered invalid key in find"); |
| 788 | 803 | } |
| 789 | 804 | if (!value_valid(first_item->second)) { |
| 790 | 805 | error(oh, "encountered invalid value in find"); |
| 791 | 806 | } |
| 792 | - if (details.compareKeys(key, first_item->first) < 0) { | |
| 807 | + if (compareKeys(key, first_item->first) < 0) { | |
| 793 | 808 | // Before the first key |
| 794 | 809 | return end(); |
| 795 | 810 | } |
| ... | ... | @@ -805,14 +820,14 @@ NNTreeImpl::findInternal(QPDFObjectHandle const& key, bool return_prev_if_not_fo |
| 805 | 820 | error(node, "loop detected in find"); |
| 806 | 821 | } |
| 807 | 822 | |
| 808 | - Array items = node.getKey(details.itemsKey()); | |
| 823 | + Array items = node.getKey(itemsKey()); | |
| 809 | 824 | size_t nitems = items.size(); |
| 810 | 825 | if (nitems > 1) { |
| 811 | 826 | int idx = binarySearch( |
| 812 | 827 | key, items, nitems / 2, return_prev_if_not_found, &NNTreeImpl::compareKeyItem); |
| 813 | 828 | if (idx >= 0) { |
| 814 | 829 | result.setItemNumber(node, 2 * idx); |
| 815 | - if (!result.impl.details.keyValid(result.ivalue.first)) { | |
| 830 | + if (!result.impl.keyValid(result.ivalue.first)) { | |
| 816 | 831 | error(node, "encountered invalid key in find"); |
| 817 | 832 | } |
| 818 | 833 | if (!result.impl.value_valid(result.ivalue.second)) { |
| ... | ... | @@ -843,7 +858,7 @@ NNTreeImpl::insertFirst(QPDFObjectHandle const& key, QPDFObjectHandle const& val |
| 843 | 858 | auto iter = begin(); |
| 844 | 859 | Array items(nullptr); |
| 845 | 860 | if (iter.node.isDictionary()) { |
| 846 | - items = iter.node.getKey(details.itemsKey()); | |
| 861 | + items = iter.node.getKey(itemsKey()); | |
| 847 | 862 | } |
| 848 | 863 | if (!items) { |
| 849 | 864 | error(oh, "unable to find a valid items node"); |
| ... | ... | @@ -868,8 +883,8 @@ NNTreeImpl::insert(QPDFObjectHandle const& key, QPDFObjectHandle const& value) |
| 868 | 883 | auto iter = find(key, true); |
| 869 | 884 | if (!iter.valid()) { |
| 870 | 885 | return insertFirst(key, value); |
| 871 | - } else if (details.compareKeys(key, iter->first) == 0) { | |
| 872 | - Array items = iter.node.getKey(details.itemsKey()); | |
| 886 | + } else if (compareKeys(key, iter->first) == 0) { | |
| 887 | + Array items = iter.node.getKey(itemsKey()); | |
| 873 | 888 | items.set(iter.item_number + 1, value); |
| 874 | 889 | iter.updateIValue(); |
| 875 | 890 | } else { |
| ... | ... | @@ -899,7 +914,7 @@ NNTreeImpl::validate(bool a_repair) |
| 899 | 914 | QPDFObjectHandle last_key; |
| 900 | 915 | try { |
| 901 | 916 | for (auto const& [key, value]: *this) { |
| 902 | - if (!details.keyValid(key)) { | |
| 917 | + if (!keyValid(key)) { | |
| 903 | 918 | error(oh, "invalid key in validate"); |
| 904 | 919 | } |
| 905 | 920 | if (!value_valid(value)) { |
| ... | ... | @@ -907,7 +922,7 @@ NNTreeImpl::validate(bool a_repair) |
| 907 | 922 | } |
| 908 | 923 | if (first) { |
| 909 | 924 | first = false; |
| 910 | - } else if (last_key && details.compareKeys(last_key, key) != -1) { | |
| 925 | + } else if (last_key && compareKeys(last_key, key) != -1) { | |
| 911 | 926 | error(oh, "keys are not sorted in validate"); |
| 912 | 927 | } |
| 913 | 928 | last_key = key; | ... | ... |
libqpdf/QPDFNameTreeObjectHelper.cc
| ... | ... | @@ -2,38 +2,6 @@ |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/NNTree.hh> |
| 4 | 4 | |
| 5 | -namespace | |
| 6 | -{ | |
| 7 | - class NameTreeDetails: public NNTreeDetails | |
| 8 | - { | |
| 9 | - public: | |
| 10 | - std::string const& | |
| 11 | - itemsKey() const override | |
| 12 | - { | |
| 13 | - static std::string k("/Names"); | |
| 14 | - return k; | |
| 15 | - } | |
| 16 | - bool | |
| 17 | - keyValid(QPDFObjectHandle oh) const override | |
| 18 | - { | |
| 19 | - return oh.isString(); | |
| 20 | - } | |
| 21 | - int | |
| 22 | - compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const override | |
| 23 | - { | |
| 24 | - if (!(keyValid(a) && keyValid(b))) { | |
| 25 | - // We don't call this without calling keyValid first | |
| 26 | - throw std::logic_error("comparing invalid keys"); | |
| 27 | - } | |
| 28 | - auto as = a.getUTF8Value(); | |
| 29 | - auto bs = b.getUTF8Value(); | |
| 30 | - return ((as < bs) ? -1 : (as > bs) ? 1 : 0); | |
| 31 | - } | |
| 32 | - }; | |
| 33 | -} // namespace | |
| 34 | - | |
| 35 | -static NameTreeDetails name_tree_details; | |
| 36 | - | |
| 37 | 5 | QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper() // NOLINT (modernize-use-equals-default) |
| 38 | 6 | { |
| 39 | 7 | // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer. For this specific |
| ... | ... | @@ -45,7 +13,7 @@ QPDFNameTreeObjectHelper::Members::Members( |
| 45 | 13 | QPDF& q, |
| 46 | 14 | std::function<bool(QPDFObjectHandle const&)> value_validator, |
| 47 | 15 | bool auto_repair) : |
| 48 | - impl(std::make_shared<NNTreeImpl>(name_tree_details, q, oh, value_validator, auto_repair)) | |
| 16 | + impl(std::make_shared<NNTreeImpl>(q, oh, ::ot_string, value_validator, auto_repair)) | |
| 49 | 17 | { |
| 50 | 18 | } |
| 51 | 19 | ... | ... |
libqpdf/QPDFNumberTreeObjectHelper.cc
| ... | ... | @@ -3,38 +3,6 @@ |
| 3 | 3 | #include <qpdf/NNTree.hh> |
| 4 | 4 | #include <qpdf/QIntC.hh> |
| 5 | 5 | |
| 6 | -namespace | |
| 7 | -{ | |
| 8 | - class NumberTreeDetails: public NNTreeDetails | |
| 9 | - { | |
| 10 | - public: | |
| 11 | - std::string const& | |
| 12 | - itemsKey() const override | |
| 13 | - { | |
| 14 | - static std::string k("/Nums"); | |
| 15 | - return k; | |
| 16 | - } | |
| 17 | - bool | |
| 18 | - keyValid(QPDFObjectHandle oh) const override | |
| 19 | - { | |
| 20 | - return oh.isInteger(); | |
| 21 | - } | |
| 22 | - int | |
| 23 | - compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const override | |
| 24 | - { | |
| 25 | - if (!(keyValid(a) && keyValid(b))) { | |
| 26 | - // We don't call this without calling keyValid first | |
| 27 | - throw std::logic_error("comparing invalid keys"); | |
| 28 | - } | |
| 29 | - auto as = a.getIntValue(); | |
| 30 | - auto bs = b.getIntValue(); | |
| 31 | - return ((as < bs) ? -1 : (as > bs) ? 1 : 0); | |
| 32 | - } | |
| 33 | - }; | |
| 34 | -} // namespace | |
| 35 | - | |
| 36 | -static NumberTreeDetails number_tree_details; | |
| 37 | - | |
| 38 | 6 | QPDFNumberTreeObjectHelper::~QPDFNumberTreeObjectHelper() // NOLINT (modernize-use-equals-default) |
| 39 | 7 | { |
| 40 | 8 | // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer. For this specific |
| ... | ... | @@ -46,7 +14,7 @@ QPDFNumberTreeObjectHelper::Members::Members( |
| 46 | 14 | QPDF& q, |
| 47 | 15 | std::function<bool(QPDFObjectHandle const&)> value_validator, |
| 48 | 16 | bool auto_repair) : |
| 49 | - impl(std::make_shared<NNTreeImpl>(number_tree_details, q, oh, value_validator, auto_repair)) | |
| 17 | + impl(std::make_shared<NNTreeImpl>(q, oh, ::ot_integer, value_validator, auto_repair)) | |
| 50 | 18 | { |
| 51 | 19 | } |
| 52 | 20 | ... | ... |
libqpdf/qpdf/NNTree.hh
| ... | ... | @@ -2,20 +2,12 @@ |
| 2 | 2 | #define NNTREE_HH |
| 3 | 3 | |
| 4 | 4 | #include <qpdf/QPDF.hh> |
| 5 | -#include <qpdf/QPDFObjectHandle.hh> | |
| 5 | +#include <qpdf/QPDFObjectHandle_private.hh> | |
| 6 | 6 | |
| 7 | 7 | #include <iterator> |
| 8 | 8 | #include <list> |
| 9 | 9 | #include <memory> |
| 10 | 10 | |
| 11 | -class NNTreeDetails | |
| 12 | -{ | |
| 13 | - public: | |
| 14 | - virtual std::string const& itemsKey() const = 0; | |
| 15 | - virtual bool keyValid(QPDFObjectHandle) const = 0; | |
| 16 | - virtual int compareKeys(QPDFObjectHandle, QPDFObjectHandle) const = 0; | |
| 17 | -}; | |
| 18 | - | |
| 19 | 11 | class NNTreeImpl; |
| 20 | 12 | class NNTreeIterator |
| 21 | 13 | { |
| ... | ... | @@ -96,9 +88,9 @@ class NNTreeImpl |
| 96 | 88 | typedef NNTreeIterator iterator; |
| 97 | 89 | |
| 98 | 90 | NNTreeImpl( |
| 99 | - NNTreeDetails const&, | |
| 100 | 91 | QPDF&, |
| 101 | 92 | QPDFObjectHandle&, |
| 93 | + qpdf_object_type_e key_type, | |
| 102 | 94 | std::function<bool(QPDFObjectHandle const&)> value_validator, |
| 103 | 95 | bool auto_repair = true); |
| 104 | 96 | iterator begin(); |
| ... | ... | @@ -130,10 +122,24 @@ class NNTreeImpl |
| 130 | 122 | void warn(QPDFObjectHandle const& node, std::string const& msg); |
| 131 | 123 | void error(QPDFObjectHandle const& node, std::string const& msg); |
| 132 | 124 | |
| 133 | - NNTreeDetails const& details; | |
| 125 | + std::string const& | |
| 126 | + itemsKey() const | |
| 127 | + { | |
| 128 | + return items_key; | |
| 129 | + } | |
| 130 | + bool | |
| 131 | + keyValid(QPDFObjectHandle o) const | |
| 132 | + { | |
| 133 | + return o.resolved_type_code() == key_type; | |
| 134 | + } | |
| 135 | + int | |
| 136 | + compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const; | |
| 137 | + | |
| 134 | 138 | QPDF& qpdf; |
| 135 | 139 | int split_threshold{32}; |
| 136 | 140 | QPDFObjectHandle oh; |
| 141 | + const qpdf_object_type_e key_type; | |
| 142 | + const std::string items_key; | |
| 137 | 143 | const std::function<bool(QPDFObjectHandle const&)> value_valid; |
| 138 | 144 | bool auto_repair{true}; |
| 139 | 145 | size_t error_count{0}; | ... | ... |