aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-01-24 09:55:18 +0100
committerJay Berkenbilt <ejb@ql.org>2021-01-25 21:39:10 +0100
commit16a9bb3f6f63497946d0efbf403df92d0ce30745 (patch)
treeb2cec476622efcf477a72911e22f920564e35d8d
parentb5614f611d3057359dfd7ba63418c62787af5511 (diff)
downloadqpdf-16a9bb3f6f63497946d0efbf403df92d0ce30745.tar.zst
name/number trees: newEmpty, increment/decrement end()
-rw-r--r--include/qpdf/QPDFNameTreeObjectHelper.hh10
-rw-r--r--include/qpdf/QPDFNumberTreeObjectHelper.hh10
-rw-r--r--libqpdf/NNTree.cc6
-rw-r--r--libqpdf/QPDFNameTreeObjectHelper.cc7
-rw-r--r--libqpdf/QPDFNumberTreeObjectHelper.cc7
-rw-r--r--qpdf/qpdf.testcov1
-rw-r--r--qpdf/test_driver.cc52
7 files changed, 88 insertions, 5 deletions
diff --git a/include/qpdf/QPDFNameTreeObjectHelper.hh b/include/qpdf/QPDFNameTreeObjectHelper.hh
index 80a48b7f..f0a9b479 100644
--- a/include/qpdf/QPDFNameTreeObjectHelper.hh
+++ b/include/qpdf/QPDFNameTreeObjectHelper.hh
@@ -54,6 +54,12 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
// structure.
QPDF_DLL
QPDFNameTreeObjectHelper(QPDFObjectHandle);
+
+ // Create an empty name tree
+ QPDF_DLL
+ static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
+
+ // ABI: = default
QPDF_DLL
virtual ~QPDFNameTreeObjectHelper();
@@ -112,7 +118,9 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
};
// The iterator looks like map iterator, so i.first is a string
- // and i.second is a QPDFObjectHandle.
+ // and i.second is a QPDFObjectHandle. Incrementing end() brings
+ // you to the first item. Decrementing end() brings you to the
+ // last item.
QPDF_DLL
iterator begin() const;
QPDF_DLL
diff --git a/include/qpdf/QPDFNumberTreeObjectHelper.hh b/include/qpdf/QPDFNumberTreeObjectHelper.hh
index b4f31b12..43c438e4 100644
--- a/include/qpdf/QPDFNumberTreeObjectHelper.hh
+++ b/include/qpdf/QPDFNumberTreeObjectHelper.hh
@@ -51,11 +51,17 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
// structure.
QPDF_DLL
QPDFNumberTreeObjectHelper(QPDFObjectHandle);
+
+ // ABI: = default
QPDF_DLL
virtual ~QPDFNumberTreeObjectHelper()
{
}
+ // Create an empty number tree
+ QPDF_DLL
+ static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
+
typedef long long int numtree_number;
// Return overall minimum and maximum indices
@@ -131,7 +137,9 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
};
// The iterator looks like map iterator, so i.first is a string
- // and i.second is a QPDFObjectHandle.
+ // and i.second is a QPDFObjectHandle. Incrementing end() brings
+ // you to the first item. Decrementing end() brings you to the
+ // last item.
QPDF_DLL
iterator begin() const;
QPDF_DLL
diff --git a/libqpdf/NNTree.cc b/libqpdf/NNTree.cc
index 3d1388b4..05398602 100644
--- a/libqpdf/NNTree.cc
+++ b/libqpdf/NNTree.cc
@@ -103,9 +103,9 @@ NNTreeIterator::increment(bool backward)
{
if (this->item_number < 0)
{
- throw std::logic_error(
- "attempt made to increment or decrement an invalid"
- " name/number tree iterator");
+ QTC::TC("qpdf", "NNTree increment end()");
+ deepen(impl.oh, ! backward, true);
+ return;
}
bool found_valid_key = false;
while (valid() && (! found_valid_key))
diff --git a/libqpdf/QPDFNameTreeObjectHelper.cc b/libqpdf/QPDFNameTreeObjectHelper.cc
index 52201eff..ffcf95a3 100644
--- a/libqpdf/QPDFNameTreeObjectHelper.cc
+++ b/libqpdf/QPDFNameTreeObjectHelper.cc
@@ -56,6 +56,13 @@ QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper()
{
}
+QPDFNameTreeObjectHelper
+QPDFNameTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair)
+{
+ return QPDFNameTreeObjectHelper(
+ QPDFObjectHandle::parse("<< /Names [] >>"), qpdf, auto_repair);
+}
+
QPDFNameTreeObjectHelper::iterator::iterator(
std::shared_ptr<NNTreeIterator> const& i) :
impl(i)
diff --git a/libqpdf/QPDFNumberTreeObjectHelper.cc b/libqpdf/QPDFNumberTreeObjectHelper.cc
index f21d1e51..053fa421 100644
--- a/libqpdf/QPDFNumberTreeObjectHelper.cc
+++ b/libqpdf/QPDFNumberTreeObjectHelper.cc
@@ -52,6 +52,13 @@ QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper(QPDFObjectHandle oh) :
{
}
+QPDFNumberTreeObjectHelper
+QPDFNumberTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair)
+{
+ return QPDFNumberTreeObjectHelper(
+ QPDFObjectHandle::parse("<< /Nums [] >>"), qpdf, auto_repair);
+}
+
QPDFNumberTreeObjectHelper::iterator::iterator(
std::shared_ptr<NNTreeIterator> const& i) :
impl(i)
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index fdb004c9..996c565a 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -551,3 +551,4 @@ NNTree -1 in binary search 0
NNTree bad node during find 0
NNTree node is not a dictionary 0
NNTree limits didn't change 0
+NNTree increment end() 0
diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc
index c0e29854..526b0123 100644
--- a/qpdf/test_driver.cc
+++ b/qpdf/test_driver.cc
@@ -1776,6 +1776,32 @@ void runtest(int n, char const* filename1, char const* arg2)
assert("six" == oh.getStringValue());
assert(2 == offset);
+ auto new1 = QPDFNumberTreeObjectHelper::newEmpty(pdf);
+ auto iter1 = new1.begin();
+ assert(iter1 == new1.end());
+ ++iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert(iter1 == new1.end());
+ new1.insert(1, QPDFObjectHandle::newString("1"));
+ ++iter1;
+ assert((*iter1).first == 1);
+ --iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert((*iter1).first == 1);
+ new1.insert(2, QPDFObjectHandle::newString("2"));
+ ++iter1;
+ assert((*iter1).first == 2);
+ ++iter1;
+ assert(iter1 == new1.end());
+ ++iter1;
+ assert((*iter1).first == 1);
+ --iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert((*iter1).first == 2);
+
// Exercise deprecated API until qpdf 11
std::cout << "/Bad1: deprecated API" << std::endl;
auto bad1 = QPDFNumberTreeObjectHelper(
@@ -1909,6 +1935,32 @@ void runtest(int n, char const* filename1, char const* arg2)
assert((*last).first == "29 twenty-nine");
assert((*last).second.getUTF8Value() == "twenty-nine!");
+ auto new1 = QPDFNameTreeObjectHelper::newEmpty(pdf);
+ auto iter1 = new1.begin();
+ assert(iter1 == new1.end());
+ ++iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert(iter1 == new1.end());
+ new1.insert("1", QPDFObjectHandle::newString("1"));
+ ++iter1;
+ assert((*iter1).first == "1");
+ --iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert((*iter1).first == "1");
+ new1.insert("2", QPDFObjectHandle::newString("2"));
+ ++iter1;
+ assert((*iter1).first == "2");
+ ++iter1;
+ assert(iter1 == new1.end());
+ ++iter1;
+ assert((*iter1).first == "1");
+ --iter1;
+ assert(iter1 == new1.end());
+ --iter1;
+ assert((*iter1).first == "2");
+
std::vector<std::string> empties = {"/Empty1", "/Empty2"};
for (auto const& k: empties)
{