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 #include <qpdf/QPDF.hh> 1 #include <qpdf/QPDF.hh>
2 2
3 #include <qpdf/FileInputSource.hh> 3 #include <qpdf/FileInputSource.hh>
  4 +#include <qpdf/InputSource_private.hh>
4 #include <qpdf/JSON_writer.hh> 5 #include <qpdf/JSON_writer.hh>
5 #include <qpdf/Pl_Base64.hh> 6 #include <qpdf/Pl_Base64.hh>
6 #include <qpdf/Pl_StdioFile.hh> 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,18 +217,8 @@ provide_data(std::shared_ptr&lt;InputSource&gt; is, qpdf_offset_t start, qpdf_offset_t
216 { 217 {
217 return [is, start, end](Pipeline* p) { 218 return [is, start, end](Pipeline* p) {
218 Pl_Base64 decode("base64-decode", p, Pl_Base64::a_decode); 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 decode.finish(); 222 decode.finish();
232 }; 223 };
233 } 224 }
@@ -615,7 +606,6 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -615,7 +606,6 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
615 if (!tos.object.isStream()) { 606 if (!tos.object.isStream()) {
616 throw std::logic_error("current object is not stream in st_stream"); 607 throw std::logic_error("current object is not stream in st_stream");
617 } 608 }
618 - auto uninitialized = QPDFObjectHandle();  
619 if (key == "dict") { 609 if (key == "dict") {
620 this->saw_dict = true; 610 this->saw_dict = true;
621 if (setNextStateIfDictionary("stream.dict", value, st_object)) { 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,7 +620,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
630 if (!value.getString(v)) { 620 if (!value.getString(v)) {
631 QTC::TC("qpdf", "QPDF_json stream data not string"); 621 QTC::TC("qpdf", "QPDF_json stream data not string");
632 error(value.getStart(), "\"stream.data\" must be a string"); 622 error(value.getStart(), "\"stream.data\" must be a string");
633 - tos.object.replaceStreamData("", uninitialized, uninitialized); 623 + tos.object.replaceStreamData("", {}, {});
634 } else { 624 } else {
635 // The range includes the quotes. 625 // The range includes the quotes.
636 auto start = value.getStart() + 1; 626 auto start = value.getStart() + 1;
@@ -638,8 +628,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -638,8 +628,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
638 if (end < start) { 628 if (end < start) {
639 throw std::logic_error("QPDF_json: JSON string length < 0"); 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 } else if (key == "datafile") { 633 } else if (key == "datafile") {
645 this->saw_datafile = true; 634 this->saw_datafile = true;
@@ -649,10 +638,9 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -649,10 +638,9 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
649 error( 638 error(
650 value.getStart(), 639 value.getStart(),
651 "\"stream.datafile\" must be a string containing a file name"); 640 "\"stream.datafile\" must be a string containing a file name");
652 - tos.object.replaceStreamData("", uninitialized, uninitialized); 641 + tos.object.replaceStreamData("", {}, {});
653 } else { 642 } else {
654 - tos.object.replaceStreamData(  
655 - QUtil::file_provider(filename), uninitialized, uninitialized); 643 + tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
656 } 644 }
657 } else { 645 } else {
658 // Ignore unknown keys for forward compatibility. 646 // Ignore unknown keys for forward compatibility.