Commit db7251f17ab3d603f947c786031de49f9d779f1e

Authored by m-holger
1 parent b73f6d79

Refactor `QPDF_json` stream reading to simplify and improve performance by repla…

…cing buffered reads with direct data extraction from `InputSource`.
Showing 1 changed file with 7 additions and 19 deletions
libqpdf/QPDF_json.cc
1 1 #include <qpdf/QPDF.hh>
2 2  
3 3 #include <qpdf/FileInputSource.hh>
  4 +#include <qpdf/InputSource_private.hh>
4 5 #include <qpdf/JSON_writer.hh>
5 6 #include <qpdf/Pl_Base64.hh>
6 7 #include <qpdf/Pl_StdioFile.hh>
... ... @@ -216,18 +217,8 @@ provide_data(std::shared_ptr&lt;InputSource&gt; is, qpdf_offset_t start, qpdf_offset_t
216 217 {
217 218 return [is, start, end](Pipeline* p) {
218 219 Pl_Base64 decode("base64-decode", p, Pl_Base64::a_decode);
219   - p = &decode;
220   - size_t bytes = QIntC::to_size(end - start);
221   - char buf[8192];
222   - is->seek(start, SEEK_SET);
223   - size_t len = 0;
224   - while ((len = is->read(buf, std::min(bytes, sizeof(buf)))) > 0) {
225   - p->write(buf, len);
226   - bytes -= len;
227   - if (bytes == 0) {
228   - break;
229   - }
230   - }
  220 + auto data = is->read(QIntC::to_size(end - start), start);
  221 + decode.write(reinterpret_cast<const unsigned char*>(data.data()), data.size());
231 222 decode.finish();
232 223 };
233 224 }
... ... @@ -615,7 +606,6 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
615 606 if (!tos.object.isStream()) {
616 607 throw std::logic_error("current object is not stream in st_stream");
617 608 }
618   - auto uninitialized = QPDFObjectHandle();
619 609 if (key == "dict") {
620 610 this->saw_dict = true;
621 611 if (setNextStateIfDictionary("stream.dict", value, st_object)) {
... ... @@ -630,7 +620,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
630 620 if (!value.getString(v)) {
631 621 QTC::TC("qpdf", "QPDF_json stream data not string");
632 622 error(value.getStart(), "\"stream.data\" must be a string");
633   - tos.object.replaceStreamData("", uninitialized, uninitialized);
  623 + tos.object.replaceStreamData("", {}, {});
634 624 } else {
635 625 // The range includes the quotes.
636 626 auto start = value.getStart() + 1;
... ... @@ -638,8 +628,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
638 628 if (end < start) {
639 629 throw std::logic_error("QPDF_json: JSON string length < 0");
640 630 }
641   - tos.object.replaceStreamData(
642   - provide_data(is, start, end), uninitialized, uninitialized);
  631 + tos.object.replaceStreamData(provide_data(is, start, end), {}, {});
643 632 }
644 633 } else if (key == "datafile") {
645 634 this->saw_datafile = true;
... ... @@ -649,10 +638,9 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
649 638 error(
650 639 value.getStart(),
651 640 "\"stream.datafile\" must be a string containing a file name");
652   - tos.object.replaceStreamData("", uninitialized, uninitialized);
  641 + tos.object.replaceStreamData("", {}, {});
653 642 } else {
654   - tos.object.replaceStreamData(
655   - QUtil::file_provider(filename), uninitialized, uninitialized);
  643 + tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
656 644 }
657 645 } else {
658 646 // Ignore unknown keys for forward compatibility.
... ...