Commit 16a9bb3f6f63497946d0efbf403df92d0ce30745
1 parent
b5614f61
name/number trees: newEmpty, increment/decrement end()
Showing
7 changed files
with
88 additions
and
5 deletions
include/qpdf/QPDFNameTreeObjectHelper.hh
| @@ -54,6 +54,12 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper | @@ -54,6 +54,12 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper | ||
| 54 | // structure. | 54 | // structure. |
| 55 | QPDF_DLL | 55 | QPDF_DLL |
| 56 | QPDFNameTreeObjectHelper(QPDFObjectHandle); | 56 | QPDFNameTreeObjectHelper(QPDFObjectHandle); |
| 57 | + | ||
| 58 | + // Create an empty name tree | ||
| 59 | + QPDF_DLL | ||
| 60 | + static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); | ||
| 61 | + | ||
| 62 | + // ABI: = default | ||
| 57 | QPDF_DLL | 63 | QPDF_DLL |
| 58 | virtual ~QPDFNameTreeObjectHelper(); | 64 | virtual ~QPDFNameTreeObjectHelper(); |
| 59 | 65 | ||
| @@ -112,7 +118,9 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper | @@ -112,7 +118,9 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper | ||
| 112 | }; | 118 | }; |
| 113 | 119 | ||
| 114 | // The iterator looks like map iterator, so i.first is a string | 120 | // The iterator looks like map iterator, so i.first is a string |
| 115 | - // and i.second is a QPDFObjectHandle. | 121 | + // and i.second is a QPDFObjectHandle. Incrementing end() brings |
| 122 | + // you to the first item. Decrementing end() brings you to the | ||
| 123 | + // last item. | ||
| 116 | QPDF_DLL | 124 | QPDF_DLL |
| 117 | iterator begin() const; | 125 | iterator begin() const; |
| 118 | QPDF_DLL | 126 | QPDF_DLL |
include/qpdf/QPDFNumberTreeObjectHelper.hh
| @@ -51,11 +51,17 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper | @@ -51,11 +51,17 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper | ||
| 51 | // structure. | 51 | // structure. |
| 52 | QPDF_DLL | 52 | QPDF_DLL |
| 53 | QPDFNumberTreeObjectHelper(QPDFObjectHandle); | 53 | QPDFNumberTreeObjectHelper(QPDFObjectHandle); |
| 54 | + | ||
| 55 | + // ABI: = default | ||
| 54 | QPDF_DLL | 56 | QPDF_DLL |
| 55 | virtual ~QPDFNumberTreeObjectHelper() | 57 | virtual ~QPDFNumberTreeObjectHelper() |
| 56 | { | 58 | { |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 61 | + // Create an empty number tree | ||
| 62 | + QPDF_DLL | ||
| 63 | + static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); | ||
| 64 | + | ||
| 59 | typedef long long int numtree_number; | 65 | typedef long long int numtree_number; |
| 60 | 66 | ||
| 61 | // Return overall minimum and maximum indices | 67 | // Return overall minimum and maximum indices |
| @@ -131,7 +137,9 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper | @@ -131,7 +137,9 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper | ||
| 131 | }; | 137 | }; |
| 132 | 138 | ||
| 133 | // The iterator looks like map iterator, so i.first is a string | 139 | // The iterator looks like map iterator, so i.first is a string |
| 134 | - // and i.second is a QPDFObjectHandle. | 140 | + // and i.second is a QPDFObjectHandle. Incrementing end() brings |
| 141 | + // you to the first item. Decrementing end() brings you to the | ||
| 142 | + // last item. | ||
| 135 | QPDF_DLL | 143 | QPDF_DLL |
| 136 | iterator begin() const; | 144 | iterator begin() const; |
| 137 | QPDF_DLL | 145 | QPDF_DLL |
libqpdf/NNTree.cc
| @@ -103,9 +103,9 @@ NNTreeIterator::increment(bool backward) | @@ -103,9 +103,9 @@ NNTreeIterator::increment(bool backward) | ||
| 103 | { | 103 | { |
| 104 | if (this->item_number < 0) | 104 | if (this->item_number < 0) |
| 105 | { | 105 | { |
| 106 | - throw std::logic_error( | ||
| 107 | - "attempt made to increment or decrement an invalid" | ||
| 108 | - " name/number tree iterator"); | 106 | + QTC::TC("qpdf", "NNTree increment end()"); |
| 107 | + deepen(impl.oh, ! backward, true); | ||
| 108 | + return; | ||
| 109 | } | 109 | } |
| 110 | bool found_valid_key = false; | 110 | bool found_valid_key = false; |
| 111 | while (valid() && (! found_valid_key)) | 111 | while (valid() && (! found_valid_key)) |
libqpdf/QPDFNameTreeObjectHelper.cc
| @@ -56,6 +56,13 @@ QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper() | @@ -56,6 +56,13 @@ QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper() | ||
| 56 | { | 56 | { |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | +QPDFNameTreeObjectHelper | ||
| 60 | +QPDFNameTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair) | ||
| 61 | +{ | ||
| 62 | + return QPDFNameTreeObjectHelper( | ||
| 63 | + QPDFObjectHandle::parse("<< /Names [] >>"), qpdf, auto_repair); | ||
| 64 | +} | ||
| 65 | + | ||
| 59 | QPDFNameTreeObjectHelper::iterator::iterator( | 66 | QPDFNameTreeObjectHelper::iterator::iterator( |
| 60 | std::shared_ptr<NNTreeIterator> const& i) : | 67 | std::shared_ptr<NNTreeIterator> const& i) : |
| 61 | impl(i) | 68 | impl(i) |
libqpdf/QPDFNumberTreeObjectHelper.cc
| @@ -52,6 +52,13 @@ QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper(QPDFObjectHandle oh) : | @@ -52,6 +52,13 @@ QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper(QPDFObjectHandle oh) : | ||
| 52 | { | 52 | { |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | +QPDFNumberTreeObjectHelper | ||
| 56 | +QPDFNumberTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair) | ||
| 57 | +{ | ||
| 58 | + return QPDFNumberTreeObjectHelper( | ||
| 59 | + QPDFObjectHandle::parse("<< /Nums [] >>"), qpdf, auto_repair); | ||
| 60 | +} | ||
| 61 | + | ||
| 55 | QPDFNumberTreeObjectHelper::iterator::iterator( | 62 | QPDFNumberTreeObjectHelper::iterator::iterator( |
| 56 | std::shared_ptr<NNTreeIterator> const& i) : | 63 | std::shared_ptr<NNTreeIterator> const& i) : |
| 57 | impl(i) | 64 | impl(i) |
qpdf/qpdf.testcov
| @@ -551,3 +551,4 @@ NNTree -1 in binary search 0 | @@ -551,3 +551,4 @@ NNTree -1 in binary search 0 | ||
| 551 | NNTree bad node during find 0 | 551 | NNTree bad node during find 0 |
| 552 | NNTree node is not a dictionary 0 | 552 | NNTree node is not a dictionary 0 |
| 553 | NNTree limits didn't change 0 | 553 | NNTree limits didn't change 0 |
| 554 | +NNTree increment end() 0 |
qpdf/test_driver.cc
| @@ -1776,6 +1776,32 @@ void runtest(int n, char const* filename1, char const* arg2) | @@ -1776,6 +1776,32 @@ void runtest(int n, char const* filename1, char const* arg2) | ||
| 1776 | assert("six" == oh.getStringValue()); | 1776 | assert("six" == oh.getStringValue()); |
| 1777 | assert(2 == offset); | 1777 | assert(2 == offset); |
| 1778 | 1778 | ||
| 1779 | + auto new1 = QPDFNumberTreeObjectHelper::newEmpty(pdf); | ||
| 1780 | + auto iter1 = new1.begin(); | ||
| 1781 | + assert(iter1 == new1.end()); | ||
| 1782 | + ++iter1; | ||
| 1783 | + assert(iter1 == new1.end()); | ||
| 1784 | + --iter1; | ||
| 1785 | + assert(iter1 == new1.end()); | ||
| 1786 | + new1.insert(1, QPDFObjectHandle::newString("1")); | ||
| 1787 | + ++iter1; | ||
| 1788 | + assert((*iter1).first == 1); | ||
| 1789 | + --iter1; | ||
| 1790 | + assert(iter1 == new1.end()); | ||
| 1791 | + --iter1; | ||
| 1792 | + assert((*iter1).first == 1); | ||
| 1793 | + new1.insert(2, QPDFObjectHandle::newString("2")); | ||
| 1794 | + ++iter1; | ||
| 1795 | + assert((*iter1).first == 2); | ||
| 1796 | + ++iter1; | ||
| 1797 | + assert(iter1 == new1.end()); | ||
| 1798 | + ++iter1; | ||
| 1799 | + assert((*iter1).first == 1); | ||
| 1800 | + --iter1; | ||
| 1801 | + assert(iter1 == new1.end()); | ||
| 1802 | + --iter1; | ||
| 1803 | + assert((*iter1).first == 2); | ||
| 1804 | + | ||
| 1779 | // Exercise deprecated API until qpdf 11 | 1805 | // Exercise deprecated API until qpdf 11 |
| 1780 | std::cout << "/Bad1: deprecated API" << std::endl; | 1806 | std::cout << "/Bad1: deprecated API" << std::endl; |
| 1781 | auto bad1 = QPDFNumberTreeObjectHelper( | 1807 | auto bad1 = QPDFNumberTreeObjectHelper( |
| @@ -1909,6 +1935,32 @@ void runtest(int n, char const* filename1, char const* arg2) | @@ -1909,6 +1935,32 @@ void runtest(int n, char const* filename1, char const* arg2) | ||
| 1909 | assert((*last).first == "29 twenty-nine"); | 1935 | assert((*last).first == "29 twenty-nine"); |
| 1910 | assert((*last).second.getUTF8Value() == "twenty-nine!"); | 1936 | assert((*last).second.getUTF8Value() == "twenty-nine!"); |
| 1911 | 1937 | ||
| 1938 | + auto new1 = QPDFNameTreeObjectHelper::newEmpty(pdf); | ||
| 1939 | + auto iter1 = new1.begin(); | ||
| 1940 | + assert(iter1 == new1.end()); | ||
| 1941 | + ++iter1; | ||
| 1942 | + assert(iter1 == new1.end()); | ||
| 1943 | + --iter1; | ||
| 1944 | + assert(iter1 == new1.end()); | ||
| 1945 | + new1.insert("1", QPDFObjectHandle::newString("1")); | ||
| 1946 | + ++iter1; | ||
| 1947 | + assert((*iter1).first == "1"); | ||
| 1948 | + --iter1; | ||
| 1949 | + assert(iter1 == new1.end()); | ||
| 1950 | + --iter1; | ||
| 1951 | + assert((*iter1).first == "1"); | ||
| 1952 | + new1.insert("2", QPDFObjectHandle::newString("2")); | ||
| 1953 | + ++iter1; | ||
| 1954 | + assert((*iter1).first == "2"); | ||
| 1955 | + ++iter1; | ||
| 1956 | + assert(iter1 == new1.end()); | ||
| 1957 | + ++iter1; | ||
| 1958 | + assert((*iter1).first == "1"); | ||
| 1959 | + --iter1; | ||
| 1960 | + assert(iter1 == new1.end()); | ||
| 1961 | + --iter1; | ||
| 1962 | + assert((*iter1).first == "2"); | ||
| 1963 | + | ||
| 1912 | std::vector<std::string> empties = {"/Empty1", "/Empty2"}; | 1964 | std::vector<std::string> empties = {"/Empty1", "/Empty2"}; |
| 1913 | for (auto const& k: empties) | 1965 | for (auto const& k: empties) |
| 1914 | { | 1966 | { |