From 50b329ee9f13e0c615fa8d1d637597ab3929e433 Mon Sep 17 00:00:00 2001 From: Masamichi Hosoda Date: Tue, 1 Oct 2019 23:53:50 +0900 Subject: [PATCH] Add QPDFWriter::getWrittenXRefTable() --- include/qpdf/QPDFWriter.hh | 5 +++ libqpdf/QPDFWriter.cc | 17 +++++++ qpdf/test_renumber.cc | 92 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh index eebc84c3..06de6a56 100644 --- a/include/qpdf/QPDFWriter.hh +++ b/include/qpdf/QPDFWriter.hh @@ -470,6 +470,11 @@ class QPDFWriter QPDF_DLL QPDFObjGen getRenumberedObjGen(QPDFObjGen); + // Return XRef entry that was written into the final file. + // This method can be used after calling write(). + QPDF_DLL + std::map getWrittenXRefTable(); + private: // flags used by unparseObject static int const f_stream = 1 << 0; diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 247a1ac5..e7eae5c6 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -2747,6 +2747,23 @@ QPDFWriter::getRenumberedObjGen(QPDFObjGen og) return QPDFObjGen(this->m->obj_renumber[og], 0); } +std::map +QPDFWriter::getWrittenXRefTable() +{ + std::map result; + + for (std::map::iterator iter = this->m->xref.begin(); + iter != this->m->xref.end(); ++iter) + { + if (iter->first != 0 && iter->second.getType() != 0) + { + result[QPDFObjGen(iter->first, 0)] = iter->second; + } + } + + return result; +} + void QPDFWriter::enqueuePart(std::vector& part) { diff --git a/qpdf/test_renumber.cc b/qpdf/test_renumber.cc index 1c1954cb..5e68c280 100644 --- a/qpdf/test_renumber.cc +++ b/qpdf/test_renumber.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,77 @@ bool compare(QPDFObjectHandle a, QPDFObjectHandle b) return true; } +bool compare_xref_table(std::map a, + std::map b) +{ + if (a.size() != b.size()) + { + std::cerr + << "different size" + << std::endl; + return false; + } + + for (std::map::iterator iter = a.begin(); + iter != a.end(); ++iter) + { + std::cout + << "xref entry for " + << iter->first.getObj() << "/" << iter->first.getGen() + << std::endl; + + if (b.count(iter->first) == 0) + { + std::cerr + << "not found" + << std::endl; + return false; + } + + QPDFXRefEntry xref_a = iter->second; + QPDFXRefEntry xref_b = b[iter->first]; + if (xref_a.getType() != xref_b.getType()) + { + std::cerr + << "different xref entry type" + << std::endl; + return false; + } + + switch (xref_a.getType()) + { + case 0: + break; + case 1: + if (xref_a.getOffset() != xref_a.getOffset()) + { + std::cerr + << "different offset" + << std::endl; + return false; + } + break; + case 2: + if (xref_a.getObjStreamNumber() != xref_a.getObjStreamNumber() || + xref_a.getObjStreamIndex() != xref_a.getObjStreamIndex()) + { + std::cerr + << "different stream number or index" + << std::endl; + return false; + } + break; + default: + std::cerr + << "unknown xref entry type" + << std::endl; + std::exit(2); + } + } + + return true; +} + int main(int argc, char *argv[]) { if (argc < 2) @@ -226,13 +298,20 @@ int main(int argc, char *argv[]) w.setPreserveUnreferencedObjects(bpreserve_unreferenced); w.write(); + std::map xrefs_w + = w.getWrittenXRefTable(); PointerHolder buf = w.getBuffer(); QPDF qpdf_ren; qpdf_ren.processMemoryFile("renumbered", reinterpret_cast(buf->getBuffer()), buf->getSize()); + std::map xrefs_ren + = qpdf_ren.getXRefTable(); + std::cout + << "--- compare between input and renumbered objects ---" + << std::endl; for (std::vector::iterator iter = objs_in.begin(); iter != objs_in.end(); ++iter) { @@ -260,6 +339,19 @@ int main(int argc, char *argv[]) std::exit(2); } } + std::cout << "complete" << std::endl; + + std::cout + << "--- compare between written and reloaded xref tables ---" + << std::endl; + if (!compare_xref_table(xrefs_w, xrefs_ren)) + { + std::cerr + << "different" + << std::endl; + std::exit(2); + } + std::cout << "complete" << std::endl; std::cout << "succeeded" << std::endl; }