Commit 0df0d00c588f3ca5f71524f96817a84c4b98bc2c

Authored by m-holger
1 parent ae00ee61

Add method QPDF::Writer::getCompressibleObjSet

Create set without creation of an intermediate vector.
include/qpdf/QPDF.hh
... ... @@ -756,7 +756,13 @@ class QPDF
756 756 static std::vector<QPDFObjGen>
757 757 getCompressibleObjGens(QPDF& qpdf)
758 758 {
759   - return qpdf.getCompressibleObjGens();
  759 + return qpdf.getCompressibleObjVector();
  760 + }
  761 +
  762 + static std::vector<bool>
  763 + getCompressibleObjSet(QPDF& qpdf)
  764 + {
  765 + return qpdf.getCompressibleObjSet();
760 766 }
761 767  
762 768 static std::map<QPDFObjGen, QPDFXRefEntry> const&
... ... @@ -1110,7 +1116,10 @@ class QPDF
1110 1116 bool compressed);
1111 1117  
1112 1118 // Get a list of objects that would be permitted in an object stream.
1113   - std::vector<QPDFObjGen> getCompressibleObjGens();
  1119 + template <typename T>
  1120 + std::vector<T> getCompressibleObjGens();
  1121 + std::vector<QPDFObjGen> getCompressibleObjVector();
  1122 + std::vector<bool> getCompressibleObjSet();
1114 1123  
1115 1124 // methods to support page handling
1116 1125  
... ...
libqpdf/QPDF.cc
... ... @@ -2397,6 +2397,19 @@ QPDF::tableSize()
2397 2397 }
2398 2398  
2399 2399 std::vector<QPDFObjGen>
  2400 +QPDF::getCompressibleObjVector()
  2401 +{
  2402 + return getCompressibleObjGens<QPDFObjGen>();
  2403 +}
  2404 +
  2405 +std::vector<bool>
  2406 +QPDF::getCompressibleObjSet()
  2407 +{
  2408 + return getCompressibleObjGens<bool>();
  2409 +}
  2410 +
  2411 +template <typename T>
  2412 +std::vector<T>
2400 2413 QPDF::getCompressibleObjGens()
2401 2414 {
2402 2415 // Return a list of objects that are allowed to be in object streams. Walk through the objects
... ... @@ -2414,7 +2427,14 @@ QPDF::getCompressibleObjGens()
2414 2427 std::vector<QPDFObjectHandle> queue;
2415 2428 queue.reserve(512);
2416 2429 queue.push_back(m->trailer);
2417   - std::vector<QPDFObjGen> result;
  2430 + std::vector<T> result;
  2431 + if constexpr (std::is_same_v<T, QPDFObjGen>) {
  2432 + result.reserve(m->obj_cache.size());
  2433 + } else if constexpr (std::is_same_v<T, bool>) {
  2434 + result.resize(max_obj + 1U, false);
  2435 + } else {
  2436 + throw std::logic_error("Unsupported type in QPDF::getCompressibleObjGens");
  2437 + }
2418 2438 while (!queue.empty()) {
2419 2439 auto obj = queue.back();
2420 2440 queue.pop_back();
... ... @@ -2446,7 +2466,11 @@ QPDF::getCompressibleObjGens()
2446 2466 } else if (!(obj.isStream() ||
2447 2467 (obj.isDictionaryOfType("/Sig") && obj.hasKey("/ByteRange") &&
2448 2468 obj.hasKey("/Contents")))) {
2449   - result.push_back(og);
  2469 + if constexpr (std::is_same_v<T, QPDFObjGen>) {
  2470 + result.push_back(og);
  2471 + } else if constexpr (std::is_same_v<T, bool>) {
  2472 + result[id + 1U] = true;
  2473 + }
2450 2474 }
2451 2475 }
2452 2476 if (obj.isStream()) {
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1964,13 +1964,11 @@ QPDFWriter::preserveObjectStreams()
1964 1964 }
1965 1965 }
1966 1966 } else {
1967   - std::set<QPDFObjGen> eligible;
1968   - std::vector<QPDFObjGen> eligible_v = QPDF::Writer::getCompressibleObjGens(m->pdf);
1969   - eligible = std::set<QPDFObjGen>(eligible_v.begin(), eligible_v.end());
  1967 + auto eligible = QPDF::Writer::getCompressibleObjSet(m->pdf);
1970 1968 for (; iter != end; ++iter) {
1971 1969 if (iter->second.getType() == 2) {
1972   - QPDFObjGen og(iter->first.getObj(), 0);
1973   - if (eligible.count(og)) {
  1970 + auto id = static_cast<size_t>(iter->first.getObj());
  1971 + if (id < eligible.size() && eligible[id]) {
1974 1972 m->obj[iter->first].object_stream = iter->second.getObjStreamNumber();
1975 1973 } else {
1976 1974 QTC::TC("qpdf", "QPDFWriter exclude from object stream");
... ... @@ -2009,22 +2007,18 @@ QPDFWriter::generateObjectStreams()
2009 2007 ++n_per;
2010 2008 }
2011 2009 unsigned int n = 0;
2012   - int cur_ostream = 0;
2013   - for (auto const& iter: eligible) {
2014   - if ((n % n_per) == 0) {
2015   - if (n > 0) {
2016   - QTC::TC("qpdf", "QPDFWriter generate >1 ostream");
2017   - }
  2010 + int cur_ostream = m->pdf.newIndirectNull().getObjectID();
  2011 + for (auto const& item: eligible) {
  2012 + if (n == n_per) {
  2013 + QTC::TC("qpdf", "QPDFWriter generate >1 ostream");
2018 2014 n = 0;
2019   - }
2020   - if (n == 0) {
2021 2015 // Construct a new null object as the "original" object stream. The rest of the code
2022 2016 // knows that this means we're creating the object stream from scratch.
2023   - cur_ostream = m->pdf.makeIndirectObject(QPDFObjectHandle::newNull()).getObjectID();
  2017 + cur_ostream = m->pdf.newIndirectNull().getObjectID();
2024 2018 }
2025   - auto& obj = m->obj[iter];
  2019 + auto& obj = m->obj[item];
2026 2020 obj.object_stream = cur_ostream;
2027   - obj.gen = iter.getGen();
  2021 + obj.gen = item.getGen();
2028 2022 ++n;
2029 2023 }
2030 2024 }
... ...