aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/qpdf/QPDFWriter.hh5
-rw-r--r--libqpdf/QPDFWriter.cc17
-rw-r--r--qpdf/test_renumber.cc92
3 files changed, 114 insertions, 0 deletions
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<QPDFObjGen, QPDFXRefEntry> 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<QPDFObjGen, QPDFXRefEntry>
+QPDFWriter::getWrittenXRefTable()
+{
+ std::map<QPDFObjGen, QPDFXRefEntry> result;
+
+ for (std::map<int, QPDFXRefEntry>::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<QPDFObjectHandle>& 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 <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDFObjGen.hh>
#include <qpdf/QPDFWriter.hh>
+#include <qpdf/QPDFXRefEntry.hh>
#include <algorithm>
#include <iostream>
@@ -158,6 +159,77 @@ bool compare(QPDFObjectHandle a, QPDFObjectHandle b)
return true;
}
+bool compare_xref_table(std::map<QPDFObjGen, QPDFXRefEntry> a,
+ std::map<QPDFObjGen, QPDFXRefEntry> b)
+{
+ if (a.size() != b.size())
+ {
+ std::cerr
+ << "different size"
+ << std::endl;
+ return false;
+ }
+
+ for (std::map<QPDFObjGen, QPDFXRefEntry>::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<QPDFObjGen, QPDFXRefEntry> xrefs_w
+ = w.getWrittenXRefTable();
PointerHolder<Buffer> buf = w.getBuffer();
QPDF qpdf_ren;
qpdf_ren.processMemoryFile("renumbered",
reinterpret_cast<char*>(buf->getBuffer()),
buf->getSize());
+ std::map<QPDFObjGen, QPDFXRefEntry> xrefs_ren
+ = qpdf_ren.getXRefTable();
+ std::cout
+ << "--- compare between input and renumbered objects ---"
+ << std::endl;
for (std::vector<QPDFObjectHandle>::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;
}