mirror of
https://github.com/qpdf/qpdf.git
synced 2025-04-06 00:01:50 +00:00
NNTree: rework iterators to be more memory efficient
Keep a std::pair internal to the iterators so that operator* can return a reference and operator-> can work, and each can work without copying pairs of objects around.
This commit is contained in:
parent
e7e20772ed
commit
8ed3e8c79b
@ -75,9 +75,6 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
|
|
||||||
class iterator: public std::iterator<
|
class iterator: public std::iterator<
|
||||||
std::bidirectional_iterator_tag,
|
std::bidirectional_iterator_tag,
|
||||||
std::pair<std::string, QPDFObjectHandle>,
|
|
||||||
void,
|
|
||||||
std::pair<std::string, QPDFObjectHandle>*,
|
|
||||||
std::pair<std::string, QPDFObjectHandle>>
|
std::pair<std::string, QPDFObjectHandle>>
|
||||||
{
|
{
|
||||||
friend class QPDFNameTreeObjectHelper;
|
friend class QPDFNameTreeObjectHelper;
|
||||||
@ -105,6 +102,8 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
reference operator*();
|
reference operator*();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
pointer operator->();
|
||||||
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool operator!=(iterator const& other) const
|
||||||
@ -131,8 +130,11 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
void remove();
|
void remove();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateIValue();
|
||||||
|
|
||||||
iterator(std::shared_ptr<NNTreeIterator> const&);
|
iterator(std::shared_ptr<NNTreeIterator> const&);
|
||||||
std::shared_ptr<NNTreeIterator> impl;
|
std::shared_ptr<NNTreeIterator> impl;
|
||||||
|
value_type ivalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The iterator looks like map iterator, so i.first is a string
|
// The iterator looks like map iterator, so i.first is a string
|
||||||
|
@ -94,9 +94,6 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
|
|
||||||
class iterator: public std::iterator<
|
class iterator: public std::iterator<
|
||||||
std::bidirectional_iterator_tag,
|
std::bidirectional_iterator_tag,
|
||||||
std::pair<numtree_number, QPDFObjectHandle>,
|
|
||||||
void,
|
|
||||||
std::pair<numtree_number, QPDFObjectHandle>*,
|
|
||||||
std::pair<numtree_number, QPDFObjectHandle>>
|
std::pair<numtree_number, QPDFObjectHandle>>
|
||||||
{
|
{
|
||||||
friend class QPDFNumberTreeObjectHelper;
|
friend class QPDFNumberTreeObjectHelper;
|
||||||
@ -124,6 +121,8 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
reference operator*();
|
reference operator*();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
pointer operator->();
|
||||||
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool operator!=(iterator const& other) const
|
||||||
@ -150,8 +149,11 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
void remove();
|
void remove();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateIValue();
|
||||||
|
|
||||||
iterator(std::shared_ptr<NNTreeIterator> const&);
|
iterator(std::shared_ptr<NNTreeIterator> const&);
|
||||||
std::shared_ptr<NNTreeIterator> impl;
|
std::shared_ptr<NNTreeIterator> impl;
|
||||||
|
value_type ivalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The iterator looks like map iterator, so i.first is a string
|
// The iterator looks like map iterator, so i.first is a string
|
||||||
|
@ -50,6 +50,57 @@ NNTreeIterator::NNTreeIterator(NNTreeImpl& impl) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NNTreeIterator::updateIValue(bool allow_invalid)
|
||||||
|
{
|
||||||
|
// ivalue should never be used inside the class since we return a
|
||||||
|
// pointer/reference to it. Every bit of code that ever changes
|
||||||
|
// what object the iterator points to should take care to call
|
||||||
|
// updateIValue. Failure to do this means that any old references
|
||||||
|
// to *iter will point to incorrect objects, though the next
|
||||||
|
// dereference of the iterator will fix it. This isn't necessarily
|
||||||
|
// catastrophic, but it would be confusing. The test suite
|
||||||
|
// attempts to exercise various cases to ensure we don't introduce
|
||||||
|
// that bug in the future, but sadly it's tricky to verify by
|
||||||
|
// reasoning about the code that this constraint is always
|
||||||
|
// satisfied. Whenever we update what the iterator points to, we
|
||||||
|
// should call setItemNumber, which calls this. If we change what
|
||||||
|
// the iterator in some other way, such as replacing a value or
|
||||||
|
// removing an item and making the iterator point at a different
|
||||||
|
// item in potentially the same position, we must call
|
||||||
|
// updateIValue as well. These cases are handled, and for good
|
||||||
|
// measure, we also call updateIValue in operator* and operator->.
|
||||||
|
|
||||||
|
bool okay = false;
|
||||||
|
if ((item_number >= 0) &&
|
||||||
|
this->node.isInitialized() &&
|
||||||
|
this->node.isDictionary())
|
||||||
|
{
|
||||||
|
auto items = this->node.getKey(impl.details.itemsKey());
|
||||||
|
if (this->item_number + 1 < items.getArrayNItems())
|
||||||
|
{
|
||||||
|
okay = true;
|
||||||
|
this->ivalue.first = items.getArrayItem(this->item_number);
|
||||||
|
this->ivalue.second = items.getArrayItem(1+this->item_number);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error(impl.qpdf, node, "update ivalue: items array is too short");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! okay)
|
||||||
|
{
|
||||||
|
if (! allow_invalid)
|
||||||
|
{
|
||||||
|
throw std::logic_error(
|
||||||
|
"attempt made to dereference an invalid"
|
||||||
|
" name/number tree iterator");
|
||||||
|
}
|
||||||
|
this->ivalue.first = QPDFObjectHandle();
|
||||||
|
this->ivalue.second = QPDFObjectHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NNTreeIterator::PathElement::PathElement(
|
NNTreeIterator::PathElement::PathElement(
|
||||||
QPDFObjectHandle const& node, int kid_number) :
|
QPDFObjectHandle const& node, int kid_number) :
|
||||||
node(node),
|
node(node),
|
||||||
@ -522,6 +573,7 @@ NNTreeIterator::remove()
|
|||||||
// We don't have to do anything since the removed item's
|
// We don't have to do anything since the removed item's
|
||||||
// successor now occupies its former location.
|
// successor now occupies its former location.
|
||||||
QTC::TC("qpdf", "NNTree erased non-last item");
|
QTC::TC("qpdf", "NNTree erased non-last item");
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -630,19 +682,15 @@ NNTreeIterator::operator--()
|
|||||||
NNTreeIterator::reference
|
NNTreeIterator::reference
|
||||||
NNTreeIterator::operator*()
|
NNTreeIterator::operator*()
|
||||||
{
|
{
|
||||||
if (this->item_number < 0)
|
updateIValue(false);
|
||||||
{
|
return this->ivalue;
|
||||||
throw std::logic_error(
|
}
|
||||||
"attempt made to dereference an invalid"
|
|
||||||
" name/number tree iterator");
|
NNTreeIterator::pointer
|
||||||
}
|
NNTreeIterator::operator->()
|
||||||
auto items = this->node.getKey(impl.details.itemsKey());
|
{
|
||||||
if (items.getArrayNItems() < this->item_number + 2)
|
updateIValue(false);
|
||||||
{
|
return &(this->ivalue);
|
||||||
error(impl.qpdf, node, "operator*: items array is too short");
|
|
||||||
}
|
|
||||||
return std::make_pair(items.getArrayItem(this->item_number),
|
|
||||||
items.getArrayItem(1+this->item_number));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -660,7 +708,7 @@ NNTreeIterator::operator==(NNTreeIterator const& other) const
|
|||||||
auto opi = other.path.begin();
|
auto opi = other.path.begin();
|
||||||
while (tpi != this->path.end())
|
while (tpi != this->path.end())
|
||||||
{
|
{
|
||||||
if ((*tpi).kid_number != (*opi).kid_number)
|
if (tpi->kid_number != opi->kid_number)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -679,6 +727,7 @@ NNTreeIterator::setItemNumber(QPDFObjectHandle const& node, int n)
|
|||||||
{
|
{
|
||||||
this->node = node;
|
this->node = node;
|
||||||
this->item_number = n;
|
this->item_number = n;
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -961,7 +1010,7 @@ NNTreeImpl::repair()
|
|||||||
auto new_node = QPDFObjectHandle::newDictionary();
|
auto new_node = QPDFObjectHandle::newDictionary();
|
||||||
new_node.replaceKey(details.itemsKey(), QPDFObjectHandle::newArray());
|
new_node.replaceKey(details.itemsKey(), QPDFObjectHandle::newArray());
|
||||||
NNTreeImpl repl(details, qpdf, new_node, false);
|
NNTreeImpl repl(details, qpdf, new_node, false);
|
||||||
for (auto i: *this)
|
for (auto const& i: *this)
|
||||||
{
|
{
|
||||||
repl.insert(i.first, i.second);
|
repl.insert(i.first, i.second);
|
||||||
}
|
}
|
||||||
@ -1005,15 +1054,15 @@ NNTreeImpl::findInternal(QPDFObjectHandle key, bool return_prev_if_not_found)
|
|||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
else if (first_item.valid() &&
|
else if (first_item.valid() &&
|
||||||
details.keyValid((*first_item).first) &&
|
details.keyValid(first_item->first) &&
|
||||||
details.compareKeys(key, (*first_item).first) < 0)
|
details.compareKeys(key, first_item->first) < 0)
|
||||||
{
|
{
|
||||||
// Before the first key
|
// Before the first key
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
else if (last_item.valid() &&
|
else if (last_item.valid() &&
|
||||||
details.keyValid((*last_item).first) &&
|
details.keyValid(last_item->first) &&
|
||||||
details.compareKeys(key, (*last_item).first) > 0)
|
details.compareKeys(key, last_item->first) > 0)
|
||||||
{
|
{
|
||||||
// After the last key
|
// After the last key
|
||||||
if (return_prev_if_not_found)
|
if (return_prev_if_not_found)
|
||||||
@ -1097,10 +1146,10 @@ NNTreeImpl::insertFirst(QPDFObjectHandle key, QPDFObjectHandle value)
|
|||||||
}
|
}
|
||||||
items.insertItem(0, key);
|
items.insertItem(0, key);
|
||||||
items.insertItem(1, value);
|
items.insertItem(1, value);
|
||||||
iter.item_number = 0;
|
iter.setItemNumber(iter.node, 0);
|
||||||
iter.resetLimits(iter.node, iter.lastPathElement());
|
iter.resetLimits(iter.node, iter.lastPathElement());
|
||||||
iter.split(iter.node, iter.lastPathElement());
|
iter.split(iter.node, iter.lastPathElement());
|
||||||
return begin();
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
NNTreeImpl::iterator
|
NNTreeImpl::iterator
|
||||||
@ -1112,11 +1161,12 @@ NNTreeImpl::insert(QPDFObjectHandle key, QPDFObjectHandle value)
|
|||||||
QTC::TC("qpdf", "NNTree insert inserts first");
|
QTC::TC("qpdf", "NNTree insert inserts first");
|
||||||
return insertFirst(key, value);
|
return insertFirst(key, value);
|
||||||
}
|
}
|
||||||
else if (details.compareKeys(key, (*iter).first) == 0)
|
else if (details.compareKeys(key, iter->first) == 0)
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "NNTree insert replaces");
|
QTC::TC("qpdf", "NNTree insert replaces");
|
||||||
auto items = iter.node.getKey(details.itemsKey());
|
auto items = iter.node.getKey(details.itemsKey());
|
||||||
items.setArrayItem(iter.item_number + 1, value);
|
items.setArrayItem(iter.item_number + 1, value);
|
||||||
|
iter.updateIValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1137,7 +1187,7 @@ NNTreeImpl::remove(QPDFObjectHandle key, QPDFObjectHandle* value)
|
|||||||
}
|
}
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
*value = (*iter).second;
|
*value = iter->second;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
return true;
|
return true;
|
||||||
|
@ -3011,7 +3011,7 @@ QPDF::findAttachmentStreams()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QPDFNameTreeObjectHelper ef_tree(embedded_files, *this);
|
QPDFNameTreeObjectHelper ef_tree(embedded_files, *this);
|
||||||
for (auto i: ef_tree)
|
for (auto const& i: ef_tree)
|
||||||
{
|
{
|
||||||
QPDFObjectHandle item = i.second;
|
QPDFObjectHandle item = i.second;
|
||||||
if (item.isDictionary() &&
|
if (item.isDictionary() &&
|
||||||
|
@ -79,6 +79,7 @@ QPDFNameTreeObjectHelper::iterator&
|
|||||||
QPDFNameTreeObjectHelper::iterator::operator++()
|
QPDFNameTreeObjectHelper::iterator::operator++()
|
||||||
{
|
{
|
||||||
++(*impl);
|
++(*impl);
|
||||||
|
updateIValue();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,14 +87,38 @@ QPDFNameTreeObjectHelper::iterator&
|
|||||||
QPDFNameTreeObjectHelper::iterator::operator--()
|
QPDFNameTreeObjectHelper::iterator::operator--()
|
||||||
{
|
{
|
||||||
--(*impl);
|
--(*impl);
|
||||||
|
updateIValue();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFNameTreeObjectHelper::iterator::updateIValue()
|
||||||
|
{
|
||||||
|
if (impl->valid())
|
||||||
|
{
|
||||||
|
auto p = *impl;
|
||||||
|
this->ivalue.first = p->first.getUTF8Value();
|
||||||
|
this->ivalue.second = p->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->ivalue.first = "";
|
||||||
|
this->ivalue.second = QPDFObjectHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QPDFNameTreeObjectHelper::iterator::reference
|
QPDFNameTreeObjectHelper::iterator::reference
|
||||||
QPDFNameTreeObjectHelper::iterator::operator*()
|
QPDFNameTreeObjectHelper::iterator::operator*()
|
||||||
{
|
{
|
||||||
auto p = **impl;
|
updateIValue();
|
||||||
return std::make_pair(p.first.getUTF8Value(), p.second);
|
return this->ivalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPDFNameTreeObjectHelper::iterator::pointer
|
||||||
|
QPDFNameTreeObjectHelper::iterator::operator->()
|
||||||
|
{
|
||||||
|
updateIValue();
|
||||||
|
return &this->ivalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -107,12 +132,14 @@ QPDFNameTreeObjectHelper::iterator::insertAfter(
|
|||||||
std::string const& key, QPDFObjectHandle value)
|
std::string const& key, QPDFObjectHandle value)
|
||||||
{
|
{
|
||||||
impl->insertAfter(QPDFObjectHandle::newUnicodeString(key), value);
|
impl->insertAfter(QPDFObjectHandle::newUnicodeString(key), value);
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFNameTreeObjectHelper::iterator::remove()
|
QPDFNameTreeObjectHelper::iterator::remove()
|
||||||
{
|
{
|
||||||
impl->remove();
|
impl->remove();
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFNameTreeObjectHelper::iterator
|
QPDFNameTreeObjectHelper::iterator
|
||||||
@ -175,7 +202,7 @@ QPDFNameTreeObjectHelper::findObject(
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
oh = (*i).second;
|
oh = i->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ QPDFNumberTreeObjectHelper::iterator&
|
|||||||
QPDFNumberTreeObjectHelper::iterator::operator++()
|
QPDFNumberTreeObjectHelper::iterator::operator++()
|
||||||
{
|
{
|
||||||
++(*impl);
|
++(*impl);
|
||||||
|
updateIValue();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,14 +83,38 @@ QPDFNumberTreeObjectHelper::iterator&
|
|||||||
QPDFNumberTreeObjectHelper::iterator::operator--()
|
QPDFNumberTreeObjectHelper::iterator::operator--()
|
||||||
{
|
{
|
||||||
--(*impl);
|
--(*impl);
|
||||||
|
updateIValue();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFNumberTreeObjectHelper::iterator::updateIValue()
|
||||||
|
{
|
||||||
|
if (impl->valid())
|
||||||
|
{
|
||||||
|
auto p = *impl;
|
||||||
|
this->ivalue.first = p->first.getIntValue();
|
||||||
|
this->ivalue.second = p->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->ivalue.first = 0;
|
||||||
|
this->ivalue.second = QPDFObjectHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QPDFNumberTreeObjectHelper::iterator::reference
|
QPDFNumberTreeObjectHelper::iterator::reference
|
||||||
QPDFNumberTreeObjectHelper::iterator::operator*()
|
QPDFNumberTreeObjectHelper::iterator::operator*()
|
||||||
{
|
{
|
||||||
auto p = **impl;
|
updateIValue();
|
||||||
return std::make_pair(p.first.getIntValue(), p.second);
|
return this->ivalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPDFNumberTreeObjectHelper::iterator::pointer
|
||||||
|
QPDFNumberTreeObjectHelper::iterator::operator->()
|
||||||
|
{
|
||||||
|
updateIValue();
|
||||||
|
return &this->ivalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -103,12 +128,14 @@ QPDFNumberTreeObjectHelper::iterator::insertAfter(
|
|||||||
numtree_number key, QPDFObjectHandle value)
|
numtree_number key, QPDFObjectHandle value)
|
||||||
{
|
{
|
||||||
impl->insertAfter(QPDFObjectHandle::newInteger(key), value);
|
impl->insertAfter(QPDFObjectHandle::newInteger(key), value);
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFNumberTreeObjectHelper::iterator::remove()
|
QPDFNumberTreeObjectHelper::iterator::remove()
|
||||||
{
|
{
|
||||||
impl->remove();
|
impl->remove();
|
||||||
|
updateIValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFNumberTreeObjectHelper::iterator
|
QPDFNumberTreeObjectHelper::iterator
|
||||||
@ -162,7 +189,7 @@ QPDFNumberTreeObjectHelper::getMin()
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (*i).first;
|
return i->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFNumberTreeObjectHelper::numtree_number
|
QPDFNumberTreeObjectHelper::numtree_number
|
||||||
@ -173,7 +200,7 @@ QPDFNumberTreeObjectHelper::getMax()
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (*i).first;
|
return i->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -192,7 +219,7 @@ QPDFNumberTreeObjectHelper::findObject(
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
oh = (*i).second;
|
oh = i->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +233,8 @@ QPDFNumberTreeObjectHelper::findObjectAtOrBelow(
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
oh = (*i).second;
|
oh = i->second;
|
||||||
offset = idx - (*i).first;
|
offset = idx - i->first;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class NNTreeDetails
|
class NNTreeDetails
|
||||||
{
|
{
|
||||||
@ -18,9 +19,6 @@ class NNTreeDetails
|
|||||||
class NNTreeImpl;
|
class NNTreeImpl;
|
||||||
class NNTreeIterator: public std::iterator<
|
class NNTreeIterator: public std::iterator<
|
||||||
std::bidirectional_iterator_tag,
|
std::bidirectional_iterator_tag,
|
||||||
std::pair<QPDFObjectHandle, QPDFObjectHandle>,
|
|
||||||
void,
|
|
||||||
std::pair<QPDFObjectHandle, QPDFObjectHandle>*,
|
|
||||||
std::pair<QPDFObjectHandle, QPDFObjectHandle>>
|
std::pair<QPDFObjectHandle, QPDFObjectHandle>>
|
||||||
{
|
{
|
||||||
friend class NNTreeImpl;
|
friend class NNTreeImpl;
|
||||||
@ -41,6 +39,7 @@ class NNTreeIterator: public std::iterator<
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
reference operator*();
|
reference operator*();
|
||||||
|
pointer operator->();
|
||||||
bool operator==(NNTreeIterator const& other) const;
|
bool operator==(NNTreeIterator const& other) const;
|
||||||
bool operator!=(NNTreeIterator const& other) const
|
bool operator!=(NNTreeIterator const& other) const
|
||||||
{
|
{
|
||||||
@ -63,6 +62,7 @@ class NNTreeIterator: public std::iterator<
|
|||||||
|
|
||||||
// ABI: for qpdf 11, make qpdf a reference
|
// ABI: for qpdf 11, make qpdf a reference
|
||||||
NNTreeIterator(NNTreeImpl& impl);
|
NNTreeIterator(NNTreeImpl& impl);
|
||||||
|
void updateIValue(bool allow_invalid = true);
|
||||||
bool deepen(QPDFObjectHandle node, bool first, bool allow_empty);
|
bool deepen(QPDFObjectHandle node, bool first, bool allow_empty);
|
||||||
void setItemNumber(QPDFObjectHandle const& node, int);
|
void setItemNumber(QPDFObjectHandle const& node, int);
|
||||||
void addPathElement(QPDFObjectHandle const& node, int kid_number);
|
void addPathElement(QPDFObjectHandle const& node, int kid_number);
|
||||||
@ -79,6 +79,7 @@ class NNTreeIterator: public std::iterator<
|
|||||||
std::list<PathElement> path;
|
std::list<PathElement> path;
|
||||||
QPDFObjectHandle node;
|
QPDFObjectHandle node;
|
||||||
int item_number;
|
int item_number;
|
||||||
|
value_type ivalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NNTreeImpl
|
class NNTreeImpl
|
||||||
|
@ -1749,7 +1749,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
// number-tree.pdf
|
// number-tree.pdf
|
||||||
QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest");
|
QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest");
|
||||||
QPDFNumberTreeObjectHelper ntoh(qtest, pdf);
|
QPDFNumberTreeObjectHelper ntoh(qtest, pdf);
|
||||||
for (auto iter: ntoh)
|
for (auto& iter: ntoh)
|
||||||
{
|
{
|
||||||
std::cout << iter.first << " "
|
std::cout << iter.first << " "
|
||||||
<< iter.second.getStringValue()
|
<< iter.second.getStringValue()
|
||||||
@ -1785,32 +1785,36 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
new1.insert(1, QPDFObjectHandle::newString("1"));
|
new1.insert(1, QPDFObjectHandle::newString("1"));
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == 1);
|
assert((*iter1).first == 1); // exercise operator* explicitly
|
||||||
|
auto& iter1_val = *iter1;
|
||||||
--iter1;
|
--iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
--iter1;
|
--iter1;
|
||||||
assert((*iter1).first == 1);
|
assert(iter1->first == 1);
|
||||||
|
assert(iter1_val.first == 1);
|
||||||
new1.insert(2, QPDFObjectHandle::newString("2"));
|
new1.insert(2, QPDFObjectHandle::newString("2"));
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == 2);
|
assert(iter1->first == 2);
|
||||||
|
assert(iter1_val.first == 2);
|
||||||
++iter1;
|
++iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
|
assert(! iter1_val.second.isInitialized());
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == 1);
|
assert(iter1->first == 1);
|
||||||
--iter1;
|
--iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
--iter1;
|
--iter1;
|
||||||
assert((*iter1).first == 2);
|
assert(iter1->first == 2);
|
||||||
|
|
||||||
std::cout << "insertAfter" << std::endl;
|
std::cout << "insertAfter" << std::endl;
|
||||||
auto new2 = QPDFNumberTreeObjectHelper::newEmpty(pdf);
|
auto new2 = QPDFNumberTreeObjectHelper::newEmpty(pdf);
|
||||||
auto iter2 = new2.begin();
|
auto iter2 = new2.begin();
|
||||||
assert(iter2 == new2.end());
|
assert(iter2 == new2.end());
|
||||||
iter2.insertAfter(3, QPDFObjectHandle::newString("3!"));
|
iter2.insertAfter(3, QPDFObjectHandle::newString("3!"));
|
||||||
assert((*iter2).first == 3);
|
assert(iter2->first == 3);
|
||||||
iter2.insertAfter(4, QPDFObjectHandle::newString("4!"));
|
iter2.insertAfter(4, QPDFObjectHandle::newString("4!"));
|
||||||
assert((*iter2).first == 4);
|
assert(iter2->first == 4);
|
||||||
for (auto i: new2)
|
for (auto& i: new2)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1830,7 +1834,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad2" << std::endl;
|
std::cout << "/Bad2" << std::endl;
|
||||||
auto bad2 = QPDFNumberTreeObjectHelper(
|
auto bad2 = QPDFNumberTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad2"), pdf);
|
pdf.getTrailer().getKey("/Bad2"), pdf);
|
||||||
for (auto i: bad2)
|
for (auto& i: bad2)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1844,21 +1848,21 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(empty.begin() == empty.end());
|
assert(empty.begin() == empty.end());
|
||||||
assert(empty.last() == empty.end());
|
assert(empty.last() == empty.end());
|
||||||
auto i = empty.insert(5, QPDFObjectHandle::newString("5"));
|
auto i = empty.insert(5, QPDFObjectHandle::newString("5"));
|
||||||
assert((*i).first == 5);
|
assert(i->first == 5);
|
||||||
assert((*i).second.getStringValue() == "5");
|
assert(i->second.getStringValue() == "5");
|
||||||
assert((*empty.begin()).first == 5);
|
assert(empty.begin()->first == 5);
|
||||||
assert((*empty.last()).first == 5);
|
assert(empty.last()->first == 5);
|
||||||
assert((*empty.begin()).second.getStringValue() == "5");
|
assert(empty.begin()->second.getStringValue() == "5");
|
||||||
i = empty.insert(5, QPDFObjectHandle::newString("5+"));
|
i = empty.insert(5, QPDFObjectHandle::newString("5+"));
|
||||||
assert((*i).first == 5);
|
assert(i->first == 5);
|
||||||
assert((*i).second.getStringValue() == "5+");
|
assert(i->second.getStringValue() == "5+");
|
||||||
assert((*empty.begin()).second.getStringValue() == "5+");
|
assert(empty.begin()->second.getStringValue() == "5+");
|
||||||
i = empty.insert(6, QPDFObjectHandle::newString("6"));
|
i = empty.insert(6, QPDFObjectHandle::newString("6"));
|
||||||
assert((*i).first == 6);
|
assert(i->first == 6);
|
||||||
assert((*i).second.getStringValue() == "6");
|
assert(i->second.getStringValue() == "6");
|
||||||
assert((*empty.begin()).second.getStringValue() == "5+");
|
assert(empty.begin()->second.getStringValue() == "5+");
|
||||||
assert((*empty.last()).first == 6);
|
assert(empty.last()->first == 6);
|
||||||
assert((*empty.last()).second.getStringValue() == "6");
|
assert(empty.last()->second.getStringValue() == "6");
|
||||||
}
|
}
|
||||||
std::cout << "Insert into invalid" << std::endl;
|
std::cout << "Insert into invalid" << std::endl;
|
||||||
auto invalid1 = QPDFNumberTreeObjectHelper(
|
auto invalid1 = QPDFNumberTreeObjectHelper(
|
||||||
@ -1875,7 +1879,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad3, no repair" << std::endl;
|
std::cout << "/Bad3, no repair" << std::endl;
|
||||||
auto bad3_oh = pdf.getTrailer().getKey("/Bad3");
|
auto bad3_oh = pdf.getTrailer().getKey("/Bad3");
|
||||||
auto bad3 = QPDFNumberTreeObjectHelper(bad3_oh, pdf, false);
|
auto bad3 = QPDFNumberTreeObjectHelper(bad3_oh, pdf, false);
|
||||||
for (auto i: bad3)
|
for (auto& i: bad3)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1883,7 +1887,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
|
|
||||||
std::cout << "/Bad3, repair" << std::endl;
|
std::cout << "/Bad3, repair" << std::endl;
|
||||||
bad3 = QPDFNumberTreeObjectHelper(bad3_oh, pdf, true);
|
bad3 = QPDFNumberTreeObjectHelper(bad3_oh, pdf, true);
|
||||||
for (auto i: bad3)
|
for (auto& i: bad3)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1893,7 +1897,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
auto bad4 = QPDFNumberTreeObjectHelper(
|
auto bad4 = QPDFNumberTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad4"), pdf);
|
pdf.getTrailer().getKey("/Bad4"), pdf);
|
||||||
bad4.insert(5, QPDFObjectHandle::newString("5"));
|
bad4.insert(5, QPDFObjectHandle::newString("5"));
|
||||||
for (auto i: bad4)
|
for (auto& i: bad4)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1924,7 +1928,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
// name-tree.pdf
|
// name-tree.pdf
|
||||||
QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest");
|
QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest");
|
||||||
QPDFNameTreeObjectHelper ntoh(qtest, pdf);
|
QPDFNameTreeObjectHelper ntoh(qtest, pdf);
|
||||||
for (auto iter: ntoh)
|
for (auto& iter: ntoh)
|
||||||
{
|
{
|
||||||
std::cout << iter.first << " -> "
|
std::cout << iter.first << " -> "
|
||||||
<< iter.second.getStringValue()
|
<< iter.second.getStringValue()
|
||||||
@ -1945,8 +1949,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(ntoh.findObject("07 sev\xe2\x80\xa2n", oh));
|
assert(ntoh.findObject("07 sev\xe2\x80\xa2n", oh));
|
||||||
assert("seven!" == oh.getStringValue());
|
assert("seven!" == oh.getStringValue());
|
||||||
auto last = ntoh.last();
|
auto last = ntoh.last();
|
||||||
assert((*last).first == "29 twenty-nine");
|
assert(last->first == "29 twenty-nine");
|
||||||
assert((*last).second.getUTF8Value() == "twenty-nine!");
|
assert(last->second.getUTF8Value() == "twenty-nine!");
|
||||||
|
|
||||||
auto new1 = QPDFNameTreeObjectHelper::newEmpty(pdf);
|
auto new1 = QPDFNameTreeObjectHelper::newEmpty(pdf);
|
||||||
auto iter1 = new1.begin();
|
auto iter1 = new1.begin();
|
||||||
@ -1957,32 +1961,36 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
new1.insert("1", QPDFObjectHandle::newString("1"));
|
new1.insert("1", QPDFObjectHandle::newString("1"));
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == "1");
|
assert(iter1->first == "1");
|
||||||
|
auto& iter1_val = *iter1;
|
||||||
--iter1;
|
--iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
--iter1;
|
--iter1;
|
||||||
assert((*iter1).first == "1");
|
assert(iter1->first == "1");
|
||||||
|
assert(iter1_val.first == "1");
|
||||||
new1.insert("2", QPDFObjectHandle::newString("2"));
|
new1.insert("2", QPDFObjectHandle::newString("2"));
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == "2");
|
assert(iter1->first == "2");
|
||||||
|
assert(iter1_val.first == "2");
|
||||||
++iter1;
|
++iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
|
assert(! iter1_val.second.isInitialized());
|
||||||
++iter1;
|
++iter1;
|
||||||
assert((*iter1).first == "1");
|
assert(iter1->first == "1");
|
||||||
--iter1;
|
--iter1;
|
||||||
assert(iter1 == new1.end());
|
assert(iter1 == new1.end());
|
||||||
--iter1;
|
--iter1;
|
||||||
assert((*iter1).first == "2");
|
assert(iter1->first == "2");
|
||||||
|
|
||||||
std::cout << "insertAfter" << std::endl;
|
std::cout << "insertAfter" << std::endl;
|
||||||
auto new2 = QPDFNameTreeObjectHelper::newEmpty(pdf);
|
auto new2 = QPDFNameTreeObjectHelper::newEmpty(pdf);
|
||||||
auto iter2 = new2.begin();
|
auto iter2 = new2.begin();
|
||||||
assert(iter2 == new2.end());
|
assert(iter2 == new2.end());
|
||||||
iter2.insertAfter("3", QPDFObjectHandle::newString("3!"));
|
iter2.insertAfter("3", QPDFObjectHandle::newString("3!"));
|
||||||
assert((*iter2).first == "3");
|
assert(iter2->first == "3");
|
||||||
iter2.insertAfter("4", QPDFObjectHandle::newString("4!"));
|
iter2.insertAfter("4", QPDFObjectHandle::newString("4!"));
|
||||||
assert((*iter2).first == "4");
|
assert(iter2->first == "4");
|
||||||
for (auto i: new2)
|
for (auto& i: new2)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -1996,21 +2004,21 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(empty.begin() == empty.end());
|
assert(empty.begin() == empty.end());
|
||||||
assert(empty.last() == empty.end());
|
assert(empty.last() == empty.end());
|
||||||
auto i = empty.insert("five", QPDFObjectHandle::newString("5"));
|
auto i = empty.insert("five", QPDFObjectHandle::newString("5"));
|
||||||
assert((*i).first == "five");
|
assert(i->first == "five");
|
||||||
assert((*i).second.getStringValue() == "5");
|
assert(i->second.getStringValue() == "5");
|
||||||
assert((*empty.begin()).first == "five");
|
assert(empty.begin()->first == "five");
|
||||||
assert((*empty.last()).first == "five");
|
assert(empty.last()->first == "five");
|
||||||
assert((*empty.begin()).second.getStringValue() == "5");
|
assert(empty.begin()->second.getStringValue() == "5");
|
||||||
i = empty.insert("five", QPDFObjectHandle::newString("5+"));
|
i = empty.insert("five", QPDFObjectHandle::newString("5+"));
|
||||||
assert((*i).first == "five");
|
assert(i->first == "five");
|
||||||
assert((*i).second.getStringValue() == "5+");
|
assert(i->second.getStringValue() == "5+");
|
||||||
assert((*empty.begin()).second.getStringValue() == "5+");
|
assert(empty.begin()->second.getStringValue() == "5+");
|
||||||
i = empty.insert("six", QPDFObjectHandle::newString("6"));
|
i = empty.insert("six", QPDFObjectHandle::newString("6"));
|
||||||
assert((*i).first == "six");
|
assert(i->first == "six");
|
||||||
assert((*i).second.getStringValue() == "6");
|
assert(i->second.getStringValue() == "6");
|
||||||
assert((*empty.begin()).second.getStringValue() == "5+");
|
assert(empty.begin()->second.getStringValue() == "5+");
|
||||||
assert((*empty.last()).first == "six");
|
assert(empty.last()->first == "six");
|
||||||
assert((*empty.last()).second.getStringValue() == "6");
|
assert(empty.last()->second.getStringValue() == "6");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exercise deprecated API until qpdf 11
|
// Exercise deprecated API until qpdf 11
|
||||||
@ -2030,8 +2038,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad1 -- wrong key type" << std::endl;
|
std::cout << "/Bad1 -- wrong key type" << std::endl;
|
||||||
bad1 = QPDFNameTreeObjectHelper(
|
bad1 = QPDFNameTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad1"), pdf);
|
pdf.getTrailer().getKey("/Bad1"), pdf);
|
||||||
assert((*bad1.find("G", true)).first == "A");
|
assert(bad1.find("G", true)->first == "A");
|
||||||
for (auto i: bad1)
|
for (auto const& i: bad1)
|
||||||
{
|
{
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
}
|
}
|
||||||
@ -2039,8 +2047,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad2 -- invalid kid" << std::endl;
|
std::cout << "/Bad2 -- invalid kid" << std::endl;
|
||||||
auto bad2 = QPDFNameTreeObjectHelper(
|
auto bad2 = QPDFNameTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad2"), pdf);
|
pdf.getTrailer().getKey("/Bad2"), pdf);
|
||||||
assert((*bad2.find("G", true)).first == "B");
|
assert(bad2.find("G", true)->first == "B");
|
||||||
for (auto i: bad2)
|
for (auto const& i: bad2)
|
||||||
{
|
{
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
}
|
}
|
||||||
@ -2053,8 +2061,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad4 -- invalid kid" << std::endl;
|
std::cout << "/Bad4 -- invalid kid" << std::endl;
|
||||||
auto bad4 = QPDFNameTreeObjectHelper(
|
auto bad4 = QPDFNameTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad4"), pdf);
|
pdf.getTrailer().getKey("/Bad4"), pdf);
|
||||||
assert((*bad4.find("F", true)).first == "C");
|
assert(bad4.find("F", true)->first == "C");
|
||||||
for (auto i: bad4)
|
for (auto const& i: bad4)
|
||||||
{
|
{
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
}
|
}
|
||||||
@ -2062,12 +2070,12 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
std::cout << "/Bad5 -- loop in find" << std::endl;
|
std::cout << "/Bad5 -- loop in find" << std::endl;
|
||||||
auto bad5 = QPDFNameTreeObjectHelper(
|
auto bad5 = QPDFNameTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad5"), pdf);
|
pdf.getTrailer().getKey("/Bad5"), pdf);
|
||||||
assert((*bad5.find("F", true)).first == "D");
|
assert(bad5.find("F", true)->first == "D");
|
||||||
|
|
||||||
std::cout << "/Bad6 -- bad limits" << std::endl;
|
std::cout << "/Bad6 -- bad limits" << std::endl;
|
||||||
auto bad6 = QPDFNameTreeObjectHelper(
|
auto bad6 = QPDFNameTreeObjectHelper(
|
||||||
pdf.getTrailer().getKey("/Bad6"), pdf);
|
pdf.getTrailer().getKey("/Bad6"), pdf);
|
||||||
assert((*bad6.insert("H", QPDFObjectHandle::newNull())).first == "H");
|
assert(bad6.insert("H", QPDFObjectHandle::newNull())->first == "H");
|
||||||
}
|
}
|
||||||
else if (n == 49)
|
else if (n == 49)
|
||||||
{
|
{
|
||||||
@ -2574,12 +2582,12 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
auto check_split1 = [&split1](int k) {
|
auto check_split1 = [&split1](int k) {
|
||||||
auto i = split1.insert(k, QPDFObjectHandle::newString(
|
auto i = split1.insert(k, QPDFObjectHandle::newString(
|
||||||
QUtil::int_to_string(k)));
|
QUtil::int_to_string(k)));
|
||||||
assert((*i).first == k);
|
assert(i->first == k);
|
||||||
};
|
};
|
||||||
check_split1(15);
|
check_split1(15);
|
||||||
check_split1(35);
|
check_split1(35);
|
||||||
check_split1(125);
|
check_split1(125);
|
||||||
for (auto i: split1)
|
for (auto const& i: split1)
|
||||||
{
|
{
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
}
|
}
|
||||||
@ -2591,10 +2599,10 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
auto check_split2 = [](QPDFNameTreeObjectHelper& noh,
|
auto check_split2 = [](QPDFNameTreeObjectHelper& noh,
|
||||||
std::string const& k) {
|
std::string const& k) {
|
||||||
auto i = noh.insert(k, QPDFObjectHandle::newUnicodeString(k));
|
auto i = noh.insert(k, QPDFObjectHandle::newUnicodeString(k));
|
||||||
assert((*i).first == k);
|
assert(i->first == k);
|
||||||
};
|
};
|
||||||
check_split2(split2, "C");
|
check_split2(split2, "C");
|
||||||
for (auto i: split2)
|
for (auto const& i: split2)
|
||||||
{
|
{
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
}
|
}
|
||||||
@ -2605,7 +2613,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
split3.setSplitThreshold(4);
|
split3.setSplitThreshold(4);
|
||||||
check_split2(split3, "P");
|
check_split2(split3, "P");
|
||||||
check_split2(split3, "\xcf\x80");
|
check_split2(split3, "\xcf\x80");
|
||||||
for (auto i: split3)
|
for (auto& i: split3)
|
||||||
{
|
{
|
||||||
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
std::cout << i.first << " " << i.second.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
@ -2626,11 +2634,11 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
assert(value.getUTF8Value() == "c");
|
assert(value.getUTF8Value() == "c");
|
||||||
auto iter1 = erase1.find("1B");
|
auto iter1 = erase1.find("1B");
|
||||||
iter1.remove();
|
iter1.remove();
|
||||||
assert((*iter1).first == "1D");
|
assert(iter1->first == "1D");
|
||||||
iter1.remove();
|
iter1.remove();
|
||||||
assert(iter1 == erase1.end());
|
assert(iter1 == erase1.end());
|
||||||
--iter1;
|
--iter1;
|
||||||
assert((*iter1).first == "1A");
|
assert(iter1->first == "1A");
|
||||||
iter1.remove();
|
iter1.remove();
|
||||||
assert(iter1 == erase1.end());
|
assert(iter1 == erase1.end());
|
||||||
|
|
||||||
@ -2640,14 +2648,14 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
iter2.remove();
|
iter2.remove();
|
||||||
assert(iter2 == erase2.end());
|
assert(iter2 == erase2.end());
|
||||||
--iter2;
|
--iter2;
|
||||||
assert((*iter2).first == 240);
|
assert(iter2->first == 240);
|
||||||
auto k1 = erase2_oh.getKey("/Kids").getArrayItem(1);
|
auto k1 = erase2_oh.getKey("/Kids").getArrayItem(1);
|
||||||
auto l1 = k1.getKey("/Limits");
|
auto l1 = k1.getKey("/Limits");
|
||||||
assert(l1.getArrayItem(0).getIntValue() == 230);
|
assert(l1.getArrayItem(0).getIntValue() == 230);
|
||||||
assert(l1.getArrayItem(1).getIntValue() == 240);
|
assert(l1.getArrayItem(1).getIntValue() == 240);
|
||||||
iter2 = erase2.find(210);
|
iter2 = erase2.find(210);
|
||||||
iter2.remove();
|
iter2.remove();
|
||||||
assert((*iter2).first == 220);
|
assert(iter2->first == 220);
|
||||||
k1 = erase2_oh.getKey("/Kids").getArrayItem(0);
|
k1 = erase2_oh.getKey("/Kids").getArrayItem(0);
|
||||||
l1 = k1.getKey("/Limits");
|
l1 = k1.getKey("/Limits");
|
||||||
assert(l1.getArrayItem(0).getIntValue() == 220);
|
assert(l1.getArrayItem(0).getIntValue() == 220);
|
||||||
@ -2667,7 +2675,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
pdf.getTrailer().getKey("/Erase4"), pdf);
|
pdf.getTrailer().getKey("/Erase4"), pdf);
|
||||||
iter2 = erase4.find(420);
|
iter2 = erase4.find(420);
|
||||||
iter2.remove();
|
iter2.remove();
|
||||||
assert((*iter2).first == 430);
|
assert(iter2->first == 430);
|
||||||
|
|
||||||
QPDFWriter w(pdf, "a.pdf");
|
QPDFWriter w(pdf, "a.pdf");
|
||||||
w.setStaticID(true);
|
w.setStaticID(true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user