Change list to vector for outline helpers (fixes #297)

This change works around STL problems with Embarcadero C++ Builder
version 10.2, but std::vector is more common than std::list in qpdf,
and this is a relatively new API, so an API change is tolerable.

Thanks to Thorsten Schöning <6223655+ams-tschoening@users.noreply.github.com>
for the fix.
This commit is contained in:
Thorsten Schöning 2019-07-03 19:34:02 +02:00 committed by Jay Berkenbilt
parent 4db1de97ce
commit 8f06da7534
10 changed files with 45 additions and 25 deletions

View File

@ -1,3 +1,13 @@
2019-07-03 Jay Berkenbilt <ejb@ql.org>
* Non-compatible API change: change
QPDFOutlineDocumentHelper::getTopLevelOutlines and
QPDFOutlineObjectHelper::getKids to return a std::vector instead
of a std::list of QPDFOutlineObjectHelper objects. This is to work
around bugs with some compilers' STL implementations that are
choking with list here. There's no deep reason for these to be
lists instead of vectors. Fixes #297.
2019-06-22 Jay Berkenbilt <ejb@ql.org>
* Handle encrypted files with missing or invalid /Length entries

View File

@ -135,16 +135,16 @@ void show_bookmark_details(QPDFOutlineObjectHelper outline,
std::cout << outline.getTitle() << std::endl;
}
void extract_bookmarks(std::list<QPDFOutlineObjectHelper> outlines,
void extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines,
std::vector<int>& numbers)
{
numbers.push_back(0);
for (std::list<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
for (std::vector<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
iter != outlines.end(); ++iter)
{
++(numbers.back());
show_bookmark_details(*iter, numbers);
std::list<QPDFOutlineObjectHelper>::iterator next = iter;
std::vector<QPDFOutlineObjectHelper>::iterator next = iter;
++next;
bool has_next = (next != outlines.end());
if ((style == st_lines) && (! has_next))

View File

@ -170,13 +170,13 @@ void
FuzzHelper::testOutlines()
{
PointerHolder<QPDF> q = getQpdf();
std::list<std::list<QPDFOutlineObjectHelper> > queue;
std::list<std::vector<QPDFOutlineObjectHelper> > queue;
QPDFOutlineDocumentHelper odh(*q);
queue.push_back(odh.getTopLevelOutlines());
while (! queue.empty())
{
std::list<QPDFOutlineObjectHelper>& outlines = *(queue.begin());
for (std::list<QPDFOutlineObjectHelper>::iterator iter =
std::vector<QPDFOutlineObjectHelper>& outlines = *(queue.begin());
for (std::vector<QPDFOutlineObjectHelper>::iterator iter =
outlines.begin();
iter != outlines.end(); ++iter)
{

View File

@ -28,8 +28,8 @@
#include <qpdf/QPDF.hh>
#include <map>
#include <list>
#include <set>
#include <vector>
#include <qpdf/DLL.h>
@ -51,7 +51,7 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
bool hasOutlines();
QPDF_DLL
std::list<QPDFOutlineObjectHelper> getTopLevelOutlines();
std::vector<QPDFOutlineObjectHelper> getTopLevelOutlines();
// If the name is a name object, look it up in the /Dests key of
// the document catalog. If the name is a string, look it up in
@ -64,7 +64,7 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
// Return a list outlines that are known to target the specified
// page
QPDF_DLL
std::list<QPDFOutlineObjectHelper> getOutlinesForPage(QPDFObjGen const&);
std::vector<QPDFOutlineObjectHelper> getOutlinesForPage(QPDFObjGen const&);
class Accessor
{
@ -95,11 +95,11 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
Members();
Members(Members const&);
std::list<QPDFOutlineObjectHelper> outlines;
std::vector<QPDFOutlineObjectHelper> outlines;
std::set<QPDFObjGen> seen;
QPDFObjectHandle dest_dict;
PointerHolder<QPDFNameTreeObjectHelper> names_dest;
std::map<QPDFObjGen, std::list<QPDFOutlineObjectHelper> > by_page;
std::map<QPDFObjGen, std::vector<QPDFOutlineObjectHelper> > by_page;
};
PointerHolder<Members> m;

View File

@ -24,7 +24,7 @@
#include <qpdf/QPDFObjectHelper.hh>
#include <qpdf/QPDFObjGen.hh>
#include <list>
#include <vector>
class QPDFOutlineDocumentHelper;
@ -55,7 +55,7 @@ class QPDFOutlineObjectHelper: public QPDFObjectHelper
// Return children as a list.
QPDF_DLL
std::list<QPDFOutlineObjectHelper> getKids();
std::vector<QPDFOutlineObjectHelper> getKids();
// Return the destination, regardless of whether it is named or
// explicit and whether it is directly provided or in a GoTo
@ -113,7 +113,7 @@ class QPDFOutlineObjectHelper: public QPDFObjectHelper
QPDFOutlineDocumentHelper& dh;
PointerHolder<QPDFOutlineObjectHelper> parent;
std::list<QPDFOutlineObjectHelper> kids;
std::vector<QPDFOutlineObjectHelper> kids;
};
PointerHolder<Members> m;

View File

@ -42,7 +42,7 @@ QPDFOutlineDocumentHelper::hasOutlines()
return ! this->m->outlines.empty();
}
std::list<QPDFOutlineObjectHelper>
std::vector<QPDFOutlineObjectHelper>
QPDFOutlineDocumentHelper::getTopLevelOutlines()
{
return this->m->outlines;
@ -59,19 +59,19 @@ QPDFOutlineDocumentHelper::initializeByPage()
QPDFOutlineObjectHelper oh = queue.front();
queue.pop_front();
this->m->by_page[oh.getDestPage().getObjGen()].push_back(oh);
std::list<QPDFOutlineObjectHelper> kids = oh.getKids();
std::vector<QPDFOutlineObjectHelper> kids = oh.getKids();
queue.insert(queue.end(), kids.begin(), kids.end());
}
}
std::list<QPDFOutlineObjectHelper>
std::vector<QPDFOutlineObjectHelper>
QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen const& og)
{
if (this->m->by_page.empty())
{
initializeByPage();
}
std::list<QPDFOutlineObjectHelper> result;
std::vector<QPDFOutlineObjectHelper> result;
if (this->m->by_page.count(og))
{
result = this->m->by_page[og];

View File

@ -45,7 +45,7 @@ QPDFOutlineObjectHelper::getParent()
return this->m->parent;
}
std::list<QPDFOutlineObjectHelper>
std::vector<QPDFOutlineObjectHelper>
QPDFOutlineObjectHelper::getKids()
{
return this->m->kids;

View File

@ -4314,6 +4314,16 @@ print "\n";
higher level methods for tokenizing content streams.
</para>
</listitem>
<listitem>
<para>
Change
<function>QPDFOutlineDocumentHelper::getTopLevelOutlines</function>
and <function>QPDFOutlineObjectHelper::getKids</function> to
return a <type>std::vector</type> instead of a
<type>std::list</type> of
<classname>QPDFOutlineObjectHelper</classname> objects.
</para>
</listitem>
<listitem>
<para>
When <command>qpdf --check</command> or <command>qpdf

View File

@ -3493,9 +3493,9 @@ static void do_json_pages(QPDF& pdf, Options& o, JSON& j)
"label", pldh.getLabelForPage(pageno).getJSON());
JSON j_outlines = j_page.addDictionaryMember(
"outlines", JSON::makeArray());
std::list<QPDFOutlineObjectHelper> outlines =
std::vector<QPDFOutlineObjectHelper> outlines =
odh.getOutlinesForPage(page.getObjGen());
for (std::list<QPDFOutlineObjectHelper>::iterator oiter =
for (std::vector<QPDFOutlineObjectHelper>::iterator oiter =
outlines.begin();
oiter != outlines.end(); ++oiter)
{
@ -3543,10 +3543,10 @@ static void do_json_page_labels(QPDF& pdf, Options& o, JSON& j)
}
static void add_outlines_to_json(
std::list<QPDFOutlineObjectHelper> outlines, JSON& j,
std::vector<QPDFOutlineObjectHelper> outlines, JSON& j,
std::map<QPDFObjGen, int>& page_numbers)
{
for (std::list<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
for (std::vector<QPDFOutlineObjectHelper>::iterator iter = outlines.begin();
iter != outlines.end(); ++iter)
{
QPDFOutlineObjectHelper& ol = *iter;

View File

@ -1805,9 +1805,9 @@ void runtest(int n, char const* filename1, char const* arg2)
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
iter != pages.end(); ++iter, ++pageno)
{
std::list<QPDFOutlineObjectHelper> outlines =
std::vector<QPDFOutlineObjectHelper> outlines =
odh.getOutlinesForPage((*iter).getObjectHandle().getObjGen());
for (std::list<QPDFOutlineObjectHelper>::iterator oiter =
for (std::vector<QPDFOutlineObjectHelper>::iterator oiter =
outlines.begin();
oiter != outlines.end(); ++oiter)
{