From 8f06da75343a5e970ff7a6f275c319172e6292d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20Sch=C3=B6ning?= <6223655+ams-tschoening@users.noreply.github.com> Date: Wed, 3 Jul 2019 19:34:02 +0200 Subject: [PATCH] Change list to vector for outline helpers (fixes #297) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- ChangeLog | 10 ++++++++++ examples/pdf-bookmarks.cc | 6 +++--- fuzz/qpdf_fuzzer.cc | 6 +++--- include/qpdf/QPDFOutlineDocumentHelper.hh | 10 +++++----- include/qpdf/QPDFOutlineObjectHelper.hh | 6 +++--- libqpdf/QPDFOutlineDocumentHelper.cc | 8 ++++---- libqpdf/QPDFOutlineObjectHelper.cc | 2 +- manual/qpdf-manual.xml | 10 ++++++++++ qpdf/qpdf.cc | 8 ++++---- qpdf/test_driver.cc | 4 ++-- 10 files changed, 45 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 63f0233a..5de76343 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019-07-03 Jay Berkenbilt + + * 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 * Handle encrypted files with missing or invalid /Length entries diff --git a/examples/pdf-bookmarks.cc b/examples/pdf-bookmarks.cc index 807fc02f..20a93078 100644 --- a/examples/pdf-bookmarks.cc +++ b/examples/pdf-bookmarks.cc @@ -135,16 +135,16 @@ void show_bookmark_details(QPDFOutlineObjectHelper outline, std::cout << outline.getTitle() << std::endl; } -void extract_bookmarks(std::list outlines, +void extract_bookmarks(std::vector outlines, std::vector& numbers) { numbers.push_back(0); - for (std::list::iterator iter = outlines.begin(); + for (std::vector::iterator iter = outlines.begin(); iter != outlines.end(); ++iter) { ++(numbers.back()); show_bookmark_details(*iter, numbers); - std::list::iterator next = iter; + std::vector::iterator next = iter; ++next; bool has_next = (next != outlines.end()); if ((style == st_lines) && (! has_next)) diff --git a/fuzz/qpdf_fuzzer.cc b/fuzz/qpdf_fuzzer.cc index ac591637..32b9a0fb 100644 --- a/fuzz/qpdf_fuzzer.cc +++ b/fuzz/qpdf_fuzzer.cc @@ -170,13 +170,13 @@ void FuzzHelper::testOutlines() { PointerHolder q = getQpdf(); - std::list > queue; + std::list > queue; QPDFOutlineDocumentHelper odh(*q); queue.push_back(odh.getTopLevelOutlines()); while (! queue.empty()) { - std::list& outlines = *(queue.begin()); - for (std::list::iterator iter = + std::vector& outlines = *(queue.begin()); + for (std::vector::iterator iter = outlines.begin(); iter != outlines.end(); ++iter) { diff --git a/include/qpdf/QPDFOutlineDocumentHelper.hh b/include/qpdf/QPDFOutlineDocumentHelper.hh index f1920574..45798a47 100644 --- a/include/qpdf/QPDFOutlineDocumentHelper.hh +++ b/include/qpdf/QPDFOutlineDocumentHelper.hh @@ -28,8 +28,8 @@ #include #include -#include #include +#include #include @@ -51,7 +51,7 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper bool hasOutlines(); QPDF_DLL - std::list getTopLevelOutlines(); + std::vector 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 getOutlinesForPage(QPDFObjGen const&); + std::vector getOutlinesForPage(QPDFObjGen const&); class Accessor { @@ -95,11 +95,11 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper Members(); Members(Members const&); - std::list outlines; + std::vector outlines; std::set seen; QPDFObjectHandle dest_dict; PointerHolder names_dest; - std::map > by_page; + std::map > by_page; }; PointerHolder m; diff --git a/include/qpdf/QPDFOutlineObjectHelper.hh b/include/qpdf/QPDFOutlineObjectHelper.hh index 9063b86f..a97cf126 100644 --- a/include/qpdf/QPDFOutlineObjectHelper.hh +++ b/include/qpdf/QPDFOutlineObjectHelper.hh @@ -24,7 +24,7 @@ #include #include -#include +#include class QPDFOutlineDocumentHelper; @@ -55,7 +55,7 @@ class QPDFOutlineObjectHelper: public QPDFObjectHelper // Return children as a list. QPDF_DLL - std::list getKids(); + std::vector 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 parent; - std::list kids; + std::vector kids; }; PointerHolder m; diff --git a/libqpdf/QPDFOutlineDocumentHelper.cc b/libqpdf/QPDFOutlineDocumentHelper.cc index 411ccf34..b736ff08 100644 --- a/libqpdf/QPDFOutlineDocumentHelper.cc +++ b/libqpdf/QPDFOutlineDocumentHelper.cc @@ -42,7 +42,7 @@ QPDFOutlineDocumentHelper::hasOutlines() return ! this->m->outlines.empty(); } -std::list +std::vector 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 kids = oh.getKids(); + std::vector kids = oh.getKids(); queue.insert(queue.end(), kids.begin(), kids.end()); } } -std::list +std::vector QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen const& og) { if (this->m->by_page.empty()) { initializeByPage(); } - std::list result; + std::vector result; if (this->m->by_page.count(og)) { result = this->m->by_page[og]; diff --git a/libqpdf/QPDFOutlineObjectHelper.cc b/libqpdf/QPDFOutlineObjectHelper.cc index 6cdd182e..c06c63d8 100644 --- a/libqpdf/QPDFOutlineObjectHelper.cc +++ b/libqpdf/QPDFOutlineObjectHelper.cc @@ -45,7 +45,7 @@ QPDFOutlineObjectHelper::getParent() return this->m->parent; } -std::list +std::vector QPDFOutlineObjectHelper::getKids() { return this->m->kids; diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml index d991a611..d5ad6466 100644 --- a/manual/qpdf-manual.xml +++ b/manual/qpdf-manual.xml @@ -4314,6 +4314,16 @@ print "\n"; higher level methods for tokenizing content streams. + + + Change + QPDFOutlineDocumentHelper::getTopLevelOutlines + and QPDFOutlineObjectHelper::getKids to + return a std::vector instead of a + std::list of + QPDFOutlineObjectHelper objects. + + When qpdf --check or qpdf diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index da37ac25..a0f7f7ea 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -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 outlines = + std::vector outlines = odh.getOutlinesForPage(page.getObjGen()); - for (std::list::iterator oiter = + for (std::vector::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 outlines, JSON& j, + std::vector outlines, JSON& j, std::map& page_numbers) { - for (std::list::iterator iter = outlines.begin(); + for (std::vector::iterator iter = outlines.begin(); iter != outlines.end(); ++iter) { QPDFOutlineObjectHelper& ol = *iter; diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 7aed39ba..c6ddd715 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1805,9 +1805,9 @@ void runtest(int n, char const* filename1, char const* arg2) for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter, ++pageno) { - std::list outlines = + std::vector outlines = odh.getOutlinesForPage((*iter).getObjectHandle().getObjGen()); - for (std::list::iterator oiter = + for (std::vector::iterator oiter = outlines.begin(); oiter != outlines.end(); ++oiter) {