Commit a4db9b3149562a6117b1d9edf89e3853480aeba8

Authored by m-holger
1 parent f30a5eb0

Move QPDF::read_xref to QPDF::Xref_table

include/qpdf/QPDF.hh
... ... @@ -759,7 +759,6 @@ class QPDF
759 759  
760 760 void parse(char const* password);
761 761 void inParse(bool);
762   - void read_xref(qpdf_offset_t offset);
763 762 bool resolveXRefTable();
764 763 void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
765 764 QPDFObjectHandle readTrailer();
... ...
libqpdf/QPDF.cc
... ... @@ -468,7 +468,7 @@ QPDF::parse(char const* password)
468 468 throw damagedPDF("", 0, "can't find startxref");
469 469 }
470 470 try {
471   - read_xref(xref_offset);
  471 + m->xref_table.read(xref_offset);
472 472 } catch (QPDFExc&) {
473 473 throw;
474 474 } catch (std::exception& e) {
... ... @@ -625,7 +625,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
625 625 }
626 626 if (max_offset > 0) {
627 627 try {
628   - qpdf.read_xref(max_offset);
  628 + read(max_offset);
629 629 } catch (std::exception&) {
630 630 throw damaged_pdf(
631 631 "error decoding candidate xref stream while recovering damaged file");
... ... @@ -664,8 +664,10 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
664 664 }
665 665  
666 666 void
667   -QPDF::read_xref(qpdf_offset_t xref_offset)
  667 +QPDF::Xref_table::read(qpdf_offset_t xref_offset)
668 668 {
  669 + auto* m = qpdf.m.get();
  670 +
669 671 std::map<int, int> free_table;
670 672 std::set<qpdf_offset_t> visited;
671 673 while (xref_offset) {
... ... @@ -700,7 +702,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
700 702 if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) {
701 703 if (skipped_space) {
702 704 QTC::TC("qpdf", "QPDF xref skipped space");
703   - warn(damagedPDF("", 0, "extraneous whitespace seen before xref"));
  705 + warn_damaged("extraneous whitespace seen before xref");
704 706 }
705 707 QTC::TC(
706 708 "qpdf",
... ... @@ -714,46 +716,43 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
714 716 while (QUtil::is_space(buf[skip])) {
715 717 ++skip;
716 718 }
717   - xref_offset = m->xref_table.read_table(xref_offset + skip);
  719 + xref_offset = read_table(xref_offset + skip);
718 720 } else {
719   - xref_offset = m->xref_table.read_stream(xref_offset);
  721 + xref_offset = read_stream(xref_offset);
720 722 }
721 723 if (visited.count(xref_offset) != 0) {
722 724 QTC::TC("qpdf", "QPDF xref loop");
723   - throw damagedPDF("", 0, "loop detected following xref tables");
  725 + throw damaged_pdf("loop detected following xref tables");
724 726 }
725 727 }
726 728  
727   - if (!m->xref_table.trailer) {
728   - throw damagedPDF("", 0, "unable to find trailer while reading xref");
  729 + if (!trailer) {
  730 + throw damaged_pdf("unable to find trailer while reading xref");
729 731 }
730   - int size = m->xref_table.trailer.getKey("/Size").getIntValueAsInt();
  732 + int size = trailer.getKey("/Size").getIntValueAsInt();
731 733 int max_obj = 0;
732   - if (!m->xref_table.empty()) {
733   - max_obj = m->xref_table.rbegin()->first.getObj();
  734 + if (!empty()) {
  735 + max_obj = rbegin()->first.getObj();
734 736 }
735   - if (!m->xref_table.deleted_objects.empty()) {
736   - max_obj = std::max(max_obj, *(m->xref_table.deleted_objects.rbegin()));
  737 + if (!deleted_objects.empty()) {
  738 + max_obj = std::max(max_obj, *deleted_objects.rbegin());
737 739 }
738 740 if ((size < 1) || (size - 1 != max_obj)) {
739 741 QTC::TC("qpdf", "QPDF xref size mismatch");
740   - warn(damagedPDF(
741   - "",
742   - 0,
743   - ("reported number of objects (" + std::to_string(size) +
744   - ") is not one plus the highest object number (" + std::to_string(max_obj) + ")")));
  742 + warn_damaged("reported number of objects (" + std::to_string(size) +
  743 + ") is not one plus the highest object number (" + std::to_string(max_obj) + ")");
745 744 }
746 745  
747 746 // We no longer need the deleted_objects table, so go ahead and clear it out to make sure we
748 747 // never depend on its being set.
749   - m->xref_table.deleted_objects.clear();
  748 + deleted_objects.clear();
750 749  
751 750 // Make sure we keep only the highest generation for any object.
752 751 QPDFObjGen last_og{-1, 0};
753   - for (auto const& item: m->xref_table) {
  752 + for (auto const& item: *this) {
754 753 auto id = item.first.getObj();
755 754 if (id == last_og.getObj() && id > 0) {
756   - removeObject(last_og);
  755 + qpdf.removeObject(last_og);
757 756 }
758 757 last_og = item.first;
759 758 }
... ...
libqpdf/qpdf/QPDF_private.hh
... ... @@ -12,9 +12,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
12 12 {
13 13 }
14 14  
15   - qpdf_offset_t read_table(qpdf_offset_t offset);
16   - qpdf_offset_t read_stream(qpdf_offset_t offset);
17   -
  15 + void read(qpdf_offset_t offset);
18 16 void reconstruct(QPDFExc& e);
19 17  
20 18 QPDFObjectHandle trailer;
... ... @@ -32,9 +30,14 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
32 30 qpdf_offset_t first_item_offset{0}; // actual value from file
33 31  
34 32 private:
  33 + // Methods to parse tables
  34 + qpdf_offset_t read_table(qpdf_offset_t offset);
35 35 bool parse_first(std::string const& line, int& obj, int& num, int& bytes);
36 36 bool read_entry(qpdf_offset_t& f1, int& f2, char& type);
37 37 bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type);
  38 +
  39 + // Methods to parse streams
  40 + qpdf_offset_t read_stream(qpdf_offset_t offset);
38 41 qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
39 42 std::pair<int, std::array<int, 3>>
40 43 process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);
... ... @@ -45,6 +48,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
45 48 int max_num_entries,
46 49 std::function<QPDFExc(std::string_view)> damaged);
47 50  
  51 + // Methods to insert table entries
48 52 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
49 53 void insert(int obj, int f0, qpdf_offset_t f1, int f2);
50 54 void insert_free(QPDFObjGen);
... ...